 Hello everyone, Twitchers. I don't know if we have anyone watching yet. So one of the things we wanted to do is just kind of chat and let people join over the next few minutes. So we won't quite get started right yet. We do have Josh and the green room, we can see them, but we're not gonna quite introduce them just yet. So the point of today is I wrote a blog post last week about how to do native builds for Myconaut Spring Boot and Quarkus. And we discovered, well, we'd already known this a while ago, but if you do Spring Security, set up an OAuth2 Resource Server, works great. If you use our Octa Spring Boot Starter, it does. So we're looking to fix that. And I have Brian DeMurze here, he's one of my colleagues on the Octa Developer Relations team. And he wrote our Spring Boot Starter originally and that's why we have him here. So we'll bring up Josh. So welcome Josh. Hey, good morning. Morning. It is morning. Yeah, it's morning for me. It's noon for you two. Where are you? Two for me. I'm on the East Coast. Oh, yeah. You're six hours ahead of people in Hawaii and they're happy people. So just think about that. I try to wake up late. I mean, that's as close as I can get. Yeah, you're doing it wrong. We're all doing it wrong. Yes, yeah, I agree. I would go ahead. I was gonna say we spent some time in Hawaii in February and my wife Trish has to do presentations just like we do as part of her job. And she was waking up for the East Coast at 3.30. So, you know, Hawaii isn't always great. But I think her mistake was she worked, right? You're not supposed to work when you're in Hawaii. Unless you live there maybe. Yeah, even then, I don't know. I mean, if you're in Hawaii, that's probably not the first thing on your mind even if you live there. No, no. I don't know a lot of turtles that are just eager to hack on Spring Native. I am pretty pumped about, for what? Learning about more Spring Native. So I've done a bunch. I'm telling Matt, I've done a bunch with Grawl and building Native binaries. But apparently there's some differences with Spring Native. But in general, I'm super excited for this technology in Java because I feel like everyone's laughed at us for years that you couldn't build a binary. Now, now we can. What is the link for people to watch? Where should I tell somebody who wants to watch this child? Twitch.tv.octative or slash octative. Octative. Okay. Probably a banner I can put up here at some point. We probably should do that. For all the people watching in Twitch, they can click the link to watch in Twitch. Right. So that's not going to do any good. Well, okay. Well, this is fun. It's fun. It's been fun seeing you all. I got to go look at the time. Oh, there we go. We got one. We got Micah. Micah's watching. We got a troll. He's going to totally troll us. You know, he is. It's all over. Well, hi, buddy, and this Micah. So let's dive right into it. Well, let's give one more minute. OK. And I'm going to reproduce the problem here. Yes. So it's always good to start with that. Or at least talk about it. Or at least show the example, all right? I'll share my screen after I've made sure it works. Talks amongst yourselves in the meantime. All right. All right. Well, Josh, you're in SF or somewhere over on the left coast, right? Yeah, San Francisco. Yeah. It's summer, so that's why we have cool. We have the great clouds and stuff. Yeah, typical summer day over there. Oh, yeah. Well, over here, it's been rainy. It's been nice the past few weeks, but it's always been a rainy day. What's that? Where abouts are you? I'm in about the center of New Hampshire. Oh, good gravy. That's in the middle of nowhere. Yeah, it's great. San Francisco is kind of the middle of nowhere, if you think about it. I mean, it's so tiny. You can easily trip over it and miss it, you know? Like, it's a little bit of an inch. Yeah, although the first time I actually worked in San Francisco, I had spent some time out there in just south of the city. But the first time I was actually staying in SF, I was like, I'll just stay a couple miles away from our office. I was in, like, Fisherman's Wharf, beautiful area. I figured I could walk around after work. I mean, it took over an hour to get to the office. I was not prepared for that. It would have been much, much faster to walk the two hours, maybe, I don't know. It was miserable either way. Beautiful, but miserable. So you came from South San Francisco and you were trying to get to the Fisherman's Wharf? No, no, no. So the first time I actually had to work in the city. So, but still, yeah, there's some inception going on here. OK, I'm going to just share my screen and show you what's going on here. So I just have this simple, like, resource server app, right? It's got this for GraalVM because we need to enable HTTPS when we're talking to Okta or any sort of, you know, secure issuer. And then we just have a Spring Security, you know, sets it up. And then the changes that I've made from the blog post is you can see application of properties, right? Instead of using the Spring Security settings, I'm using the Okta OAuth2 issuer. And then I replace the Spring Framework OAuth2 resource server with our starter. And so what our starter does, Brian can probably explain it better, but it basically encapsulates Spring's resource server and its OAuth2 login. So you can have both already preconfigured and then it does, like, audience validation and stuff like that. But for the most part, it's a wrapper around Spring Security. So I started up here. I have it running. And if I use, you know, a bearer token or an access token with HTTP, I can talk to it. And it'll return my information, right? And so if we were to look back at the project at the hello controller, you can see it's just grabbing the principal's name. And that happens to be my email. And so if I was to build this, right, you can build it two ways. And hopefully Josh will clarify this. Well, not that. You want to do MVM package-p-native is one way. And I believe you need a Grawl-enabled JDK for that. The other way is Spring Boot Build Image, right? And that uses Docker. So you don't need Grawl VM. I'm going to use the Grawl VM way because that's a little faster. So if I do package like that, it fails, right? It gets close with the AOT stuff. And then it'll eventually spit out an error here. Ow. I will say, so I poked around this a little bit, that error messages are pretty great. At least they try to punch in the right direction. I got to a point where I was utterly confused, but that may have likely just me and not an error message. I think we figured out the issue. Mike, let's just fix that. So I'll stop sharing at this point. And I think mute. No, we can hear you. Well, my buddy is watching, and he says, I'm on mute. Is that possible? What's possible? Like what we see here and what happens on Twitch is two different things. So we'll wait for someone else to comment. Hey, Micah, is Josh on mute? The turnaround is like 45 seconds though. All right, it could take a while for the delay. I'm sorry. I think I misunderstood the message. My friend's watching, but he has me on mute, which is even worse if you think about it, right? Like what kind of friends? Like I'm going to turn it on, but definitely not going to listen to that. All right, well, Jay Walter said he can hear us just fine, so we're good. OK, I'm at Macopa. OK, let's go fix that bug. I know how to help. We just do what the message says. Like let's open up that starter. All right. So I have got to share my screen again, right? Or did you want to share yours, Brian? I can share yours. I think I'm already connected to yours. So we're ready to go, I think. So you share back to here and whoop, whoop. Yeah, bear with us because we're trying out IntelliJ's new code with me feature. So far, it's been cool. Bear with us. But it's new, so bear. No. All right, where's the error message? So the error is back in this window. Oh, right, right, right, right, right. Because this is your example. Right. Yep. Let's go to octa.of2 auto-config. It'll be awesome. This is going to be so much fun. Yeah, so I think Josh will pick up. So there's some low-hanging fruit. And then, like I said, I was thoroughly confused after that. And there's apparently a light mode, and there's a whole bunch of things you can talk about with chelibc and all that fun stuff. Explain the whys and what nots, right? Sure. All right. I'm not seeing that map. You don't see the octa.of2 auto-config? Or are you going to follow you? No, I was going to follow you. Maybe that's what I need to do. I'm following you now. Oh, OK. I'm just going to start scrolling here. Can you see this? Yep. That's the right file. It is the wrong file. So the error message, actually, Matt, switch to the error message pointed to what class? Octa.of2 auto-config. All right. So that is over here somewhere. Oh, two auto-config. All right. So there's a few things here, right? There is my configuration. I think what it's telling me, and Josh, fill me in. I need to turn, what is it, proxy? Come on, type completion. No. I need to do this on all my configurations. No, I think that's required anyway. So what it's saying is that because that's required, because that's the default state right now. And by the way, there's some possibility that that restriction will go away. But for now, basically, you've got beans that are invoking each other. You've got a bean method that's invoking another bean method, which is a no-no. You need to do parameter injection. Oh, yes. Yes, I've seen that, too. So that is right here. OK, yeah. And this is really just a, so taking a step back, I assume this is a general bad practice to begin with. Is that fair or is that not really the case? No, it's OK. So long story short, CGlib. We use CGlib to subclass that configuration class at runtime. And CGlib is used to then dynamically create a subclass that overrides the methods so that when you call OAuth2 user service, it does memoization. Basically, it intercepts a call. If that one object has already been created, the singleton bean has already been created, it just returns that pre-computed, pre-created bean. Otherwise, it creates it anew for the first time, and then all subsequent calls get the pre-created bean. So with me so far, that's like spring 3.0, 2009 behavior. And that's how that works. And it's a bit of a magic trick. And it makes it so that you can call the method 1,000 times and still get the same object, the same instance. Well, Graubium doesn't know about CGlib proxies. We call them AOT proxies. It doesn't know about dynamically subclassing classes like that. It knows about JDK interface proxies, but not about that kind of proxy. And so we just added support in spring native 010.0. That just dropped. That just got released. So now there is a technical component in spring native that you can use to configure an AOT proxy. Basically, we have the ability to tell Graubium that this class is going to be dynamically subclassed, and it'll look like this because it'll implement these interfaces in this concrete class. But that doesn't have an equivalent in Graubium itself. There's no JDK thing we can point to and say, this is just like that. It's something that we created. And a lot of frameworks have similar tricks with byte buddy or CGlib or whatever. So there's no standard thing across all these different portfolio projects that do this. So in spring native, we have now a new mechanism called an AOT proxy hint. So this is the first time that spring native has a hint that doesn't have an analog in the JSON config files in Graubium. Unfortunately, we haven't actually applied all that magic yet to the business of dynamically subclassing configuration classes and creating proxies of them so that we can intercept the method calls. So for now, it just doesn't work. But like I say, technically, maybe it could work. Like now that we have AOT proxies, maybe that's a thing we could do. I don't know. So this isn't a bad practice. It's just because of the limitations of how Graubium has supported these kinds of use cases and because we just got support for it in spring native, which released like a week ago, spring native 010.0, I would avoid it for now. Yeah. And the alternative is just to inject the parameter. So it's impossible. So we should be able to, whoops, whoops, whoops. Quartz, oh, quartz. What is it? What is that? I helped with the spring native integration for quartz, by the way. Qualifier, wait, what, wait, qualifier. I want this name here, right? I think it's this one. That should be. Come on, come on. It's copy and paste. It's a little slower here. And then, it's this big long class here and then whoops, whoops, whoops. What do I do? Code with me is goofy. Yeah, it's a little slow. Oh, I need a argument, you know. It's a little long here, but, and then I can go like this. Did I do it? No, I didn't. Yeah, there it goes. All right. It's so, okay, there you go, yeah. Cool, so that gets rid of that dependency. Yeah, but if you do that anywhere else, we need to fix that too, so, you know. I think that was the only one, but like I said, I only looked at this briefly Friday, so. Okay, well, I guess recompile and let's retry. I hope you got the client app, the blog app, set to snapshot releases. Oh, that's a good point. Well, I think what you can do here is just, you know, MVN install, right? And then I can switch it. Yeah. All right, let's make this fast, all right? Hashtag skip tests. We can also just do the actual, a lot too project, right? You don't need to do all of them. Too late. Wait, it's done. All right, well, let's switch back to this one. You're absolutely right, though. That would have made a lot of sense, but I... All right, so back here, what's the snapshot? 211? It is, that's a good question. Let's look. I would assume it's 211 snapshot. 211 snapshot, yep. All right, so let's try it again. Back to the sample and... 15 seconds to compile, not only like running the test and stuff, it takes like two and a half minutes. So that's... Oh, yeah. Skipping the test for the win. Given our abbreviated time together and the fact that we're doing Gromium compilation, you're gonna appreciate every opportunity to compile faster. Okay, OF2, octa-config. These methods are directly invoked methods marked being OIDC user service. Oh, did I lie? Did I... Is that different from the previous one? Uh-huh. That was the same one, right? Am I a liar? So... Octa-2, octa-config, yep. Field failed. These methods are directly, yeah, I don't know. Can we go back to the code and look at it? Oh, okay, let's scroll down. I can barely see. Wait, what if I go to my IDE? Can I drive over it? I think you can drive. I'll let you in and then I gotta follow you, though, here. Are you sure that's the right... Are you sure it's installed? Like, octa-ov2-config. Oh, that's a good question. Let's see which... Make sure this version is actually installed here. Installing. Yeah, two-one-one snapshot. Let's see. Did you rebuild? You might have to do that. I did this, right? Yeah, that's true. I can do it clean. People don't like it when you do MVN clean, though. I gotta be honest, I know better and I still... It's been in my brain since, I don't know, almost 20 years at this point. I type clean way more than I should. And I tried myself after I do it, but then I do it again. Builds fail down. Okay. Octa-ov2-config. Octa-ov2-config. And it's already user service. I don't know. Doesn't look all that bad to me. I think there's something, obviously, we're missing something obvious here. Like, what if you just RMRF your local M2 for this particular starter? Okay. I love that guy. M2 repository. Everything just started, yeah. I'm Octa. Sure. Yeah, sure. This is another trick that I'm still amazed is he's still in a bag of tricks. You did package and install. I did install. All right, we did install over here. Well, I ran it from the code with me thing. Ah, maybe it's like... I mean, I'm running random commands on your computer, so I don't know. I just piped it straight in it. We've never done Java code before, friends. This is... First time. This is it first time. We're doing good. All things... Well, I think it would be an interesting code with me feature if it like, Brian ran it and it actually installed it on his machine instead of mine, right? The whole point was that we wouldn't have to do that. So we'll see you here. It'd be great if it was like a Clip-It Clippy thing. Looks like you're trying to, you know, take advantage of Graphium Native Compilation. Would you like a drink? Ha, ha, ha. You're gonna need it when you're build times to go through the roof. Yeah. All right, so try it again here. 30 seconds. What was different in that time? I think you ran some other... I don't know what you ran. Well, it downloaded stuff, so it might have... When Brian ran it, it might have ran on his machine. I don't know. We'll see you here shortly. We will see. This is the other thing, Joe. I mean, I don't know how much of my time, you know, I spend dealing with like dependency issues. You know, and I see a lot of logging questions. There's still a lot of people confused about Java logging. It's like there's a handful of these problems that are just never going to go away. I just let Spring Boot do the logging. I don't, I've forgotten everything related to logging. I have no idea how to do it. It's been eight years since I had to care. I don't care. That's a great statement right there. Yeah, just let the platform forward it to some, you know, system log d thing, system log d thing. It'll be fine, you know. It seems like we're actually getting somewhere. So I think code with me, like MVN install, if you run it, it does it on your machine, not mine, which is, that's strange, but... Yeah, I don't know. Wait, so are we looking at, whose laptop are we looking at right now? Mine. Okay. And I'm building the example, right? And it's actually building now. Okay, so are you the one running the Maven command or who's running the Maven commands? Well, I ran it in order to get it to install locally because when Brian ran it, it didn't actually seem like it installed. Oh, that's bizarre. That is so confusing. I am not... I mean, if I'm sharing my ID, everything that you do should happen on my computer, right? Yeah. Are you thinking so? It's on this? What's that? What was the question? Are you skipping? No, I didn't, but we're already past those, so... Oh, no, you're not. Look, it's... You know we compile the tests to native code now? Oh, wow. That's a thing we do for you, but it does double the compile time. So next time, skip that. Skip test. This is one. We got, you know, more pressing, low-hanging fruit kind of bugs to fix. Oh, this is the other one that probably happened, but I wasn't building from the ID, but you notice this, like the latest IntelliJ, they don't reload your Maven files for you, so you gotta click this guy? There was like a brief period in time when it reloaded automatically the Maven index, and then it was like one release like three years ago where it just made the CPU crawl. Do you remember that? It was like running Slack, it just... Yeah, I do. I do remember that. And then they stopped doing it. It's like, it just no longer the default, and I've checked that little checkbox, it just never seems to do it, but now I'm not getting it. It's back on the command line, just, okay, if I wanted to work, I'll do it myself, you know? I'm glad, because that you also have this problem, because I've had this problem, and I thought it was me, so at least now it's just us, I guess. I mean, I love IntelliJ so much, but please make this work. I don't wanna have to reload entities when things get installed. Yep. It was working fine for a few years, and then it got really, like they did something, and just overnight it became dog slow, and I don't know, it's given all of a sudden. Well, I also think in the streaming times, we're still in streaming times versus in-person times, like the sharing of the screen really slows things down quite a bit, like two to three X. Oh, yeah. So that's when it's tough, especially when Josh and I are thinking about doing a native talk, it's gonna, we're gonna have to do a jig on stage just to get through the time when it's building it all. So one of the one upside of this forsaken pandemic is that now I can submit prerecorded talks and that I can use like, I can speed up the native image builds, like just a little animation showing a clock ticking for five seconds. Cause it's that, it's not, it's native image code, native image compilation. That's a thing, I guess. So my goal, my hope is that this, the idea is that you can trust that the code you've written in Java that runs in the JVM will work exactly as it will in the compiled code for Gravium, right? But obviously you just saw today, it's not a hundred percent there yet, you know, like small things like C to the proxies for configuration classes, little quirks. Right, and you mentioned something like we're seeing all these warnings about like couch base and web flux and stuff, even though we don't have them in this project, you said those are, those will be hidden in like the 11.o release or something? Not hidden. What we're trying to do is to take advantage of functional translation or something like that. So basically, you know, those configuration classes, there's also a mechanism where you can do functional configuration. So you can actually, you can, it's a, what is it called, application context initializer or something like that, application initializer, it's a callback interface that was in Spring, like years ago, like five years ago. Maybe, I think it's Spring five. And that interface, yeah, it's Spring five. Let's say that, that sounds right. It's a interface that gives you a pointer to the context that you can then programmatically register beams on. So you can say application context.registerbeam, then the class in a food.class, comma, and then a supplier that produces an instance of food, right? And that requires no configuration class. That requires no reflection. Configuration classes do require reflection and so on, right? But the hope is that we can work, we have something called Spring and DIT that we worked on that actually at compile time turns all of your Java configuration classes into this functional configuration. All right, we worked through your configuration classes, turn it into functional config, and that requires no reflection at all anywhere. Like it doesn't require us to provide int for it. This is like, Spring and DIT is experimental, but it's do Spring hyphen and it, maybe it's like desires thing, I don't know. Yeah, so I just got a comment. We have been ignoring the chat, which is partially my fault, because I can't do more than one thing at once. Yeah, but there are some great comments in here. James Ward is definitely agreeing with us about the change in IntelliJ. And we've got a little flak for not answering questions here, but some people are switching to dropping off the IntelliJ bandwagon going right to VS Code. There's a little bit of everything on here, but one other question from Micah here, which isn't actually a troll, which is surprising, is has anyone done any testing with building growl images on the M1 versus the Intel machine? Yeah, it's slower for me. I don't know, growl VM seems slower. I don't understand why. Maybe I did it wrong. It was actually when I was working with Matt on this thing last week. So I want that to be faster. It is so fast in every other respect. I don't understand why it's not faster. So there's something I'm missing clearly. Anyway, this is springing it. There you go. You can see the idea. It takes that configuration class, turns it into a configuration initializer, the application context initializer. That in turn requires no configuration, no AOT proxies, nothing. And so now the compiler doesn't need any JSON config or ints or anything because it knows exactly what's gonna be used. There's no question about what's gonna be used. We don't have to provide an extra configuration. It can statically analyze the code base. And for this to work, by the way, we have to run this on all of the spring boot configuration classes, all auto config, all configuration everywhere, right? Yes, so this is great because I know every time I've used growl to build a native image, I spent most of my time hacking up JSON files to say which bits of reflection I'm using or other libraries are using or I would dream about using or anything in the future. So do doing this automatically is huge. Well, spring native is doing it automatically already, right? It's just that, you know, we have to do it. We do it for all of our configuration classes. It'd be nice to not need to do that in the first place. So what happened here, friends? This is a test and I don't know if skipping the test would actually fix this, but it seems to be related to this configuration validator and it's resource-funded. Yeah, wonderful. Can you grab that spring com, forward slash octa, commons, blah, blah, blah, blah, all the way to the configuration validator? This one? Yeah, just grab that whole thing and then go to the configuration class or, I don't know, do you have a hint somewhere? For now. I don't think so, do you, Brian? Go, go in the starter or Matt's example? Go into, for now let's just do this on Matt's example and then at the very end for the cherry on top we'll extract it out into a hint jar that ships like auto-configuration forward Gravian's Oh, cool, okay. Add this to your demo application. Add the following, a resource hint annotation to the demo application, springboard application annotation. Okay, resource like that. Yeah, and then parentheses and then there's like pattern is the path there and then is bundle, is that true or false? And it looks like it is. Okay, so pattern and put this in there and then is bundle true like that? Looks right. Yeah, okay. And this, oh, while skipping test, excuse me. Right, cause that took seven minutes. It only did it like five more times and we're out of time. So maybe we're all waiting for this. It's a great way to fill time. All right, I had mentioned at one point that I was doing dash P native to use JDK with grawl to build this, but if you use the build image that uses Docker, is that correct, Josh? Yeah, that's correct. And why would you want to do one over the other? Well, so most organizations want to take the application and deploy it into a container orchestrator of some sort anyway. So we just put those two steps together. The other thing is they don't need to have grawl VM installed. It runs the build inside of a Docker container. So as long as you've got Docker daemon running somewhere, it'll do the right thing. The idea is that we're using a thing called a build pack. The core conceded build packs is that there are only so many different ways to, there are only so many different ways to take an application and turn it into a container. So why bother reinventing it, just reuse that recipe and the recipes come from the Heroku and Cloud Foundry teams or they represent the best sort of work for those two different teams over the last almost a decade, I guess. So yeah, just let us do it. We figured out how to run Java minus jar for you. Why bother reinventing this with every single new image? That makes sense. And so have you seen like differences in your own tests and the building time if you use one technique over another? Up until recently they didn't even like, okay, I knew how to run the Maven, Gradle, Gravium compiler thing for all this time. I just didn't do it very often because the build packs thing was the default and it was supported out of the box and it's so darn easy. So I don't really know. They just in the last week or two, it must be, it couldn't be more than a week. They on start.spring.do now, when you go there, it'll generate the native build tools version and all that stuff. It'll do that for you automatically. That's new though. That wasn't the case beginning of June, for example. Right. So I generated this project like a week ago, right? And it's got this native profile in here that this is the new stuff that Josh is talking about because this uses Gravium to build it. And if you don't have Gravium installed, like you'll get a failure. Yeah, it's a profile too. So you get regular, if you do Maven package, you get a JVM build. If you do Maven package minus P native, you get a Gravium build and time for copy. So I used SDK man to install it. I don't need the new one, but if I do, was it SDK less Java? It's my life right there. By the way, this is simultaneously terrifying, but also awesome. Look at all those different ways to get Java installed that do seem to be the same thing, except for Gravium. And so this one right here is the one that I have installed. So if I was to use like Java 11 and I ran with the dash P native, it would fail, right? But if I did the build image and I had Docker running, then it would succeed. So I guess that's the biggest advantage, right? Is you don't have to have that for all VM SDK. I love me some SDK man, but my one gripe is that I think they only hold on to the last couple versions of each major version of Java, version of versions. So if you handful of projects I've used, like the dot equivalent, I forget what it is, a dot file to specify the version of Java or the version and SDK and provider of this Java. So for all projects, it's great because you can pin the version. But for other projects, that version may not be there next week. So it's really hard to pin to a specific version. So you're saying I have 11, 0, 11 here and I don't see like 11, 0, 3, but it's probably a thing, right? If I tried to install that, it wouldn't work. It may, it may not be there anymore because it's on some CDN. I haven't looked at this in a year or two, but they were removing those versions to probably save money, right? I can't go ironically in those folks. I didn't even, I didn't, but look at the example it's doing exactly what I'm trying to do. It compiles, let's run it, let's see what happens. Right, you're right, it's not available, right? Yeah. That is funny. So that's probably great, but it's a great tool. We've got target demo here. So this was the issue that I threw my hands up with. Is that because it's like an inner class or what? There's an inner class that's, it's used. So there's a custom set of conditions. So there's a conditional annotation that has a few inner conditional classes that's used. And this is done elsewhere in spring and spring security and other spring boot things. So I don't know if there's something we need to configure specifically or if I'm doing something wrong and I need to expose it some other way. And to be honest, this may be something we can look at removing. Cause this was, you know, some of this stuff was needed back in whatever spring, spring boot 1.5. And then what was that? It was the older spring security OAuth library, which is now in the source tree and lots of things have changed. What's the one that it's missing? I'm into inspection URI condition. If you search for that conditional class, you'll find where it's used. It's not used. Search for. This is the one I'm in. Yeah, search for that class. It's, it should be defined in a conditional annotation. Somewhere else? Somewhere else in that OAuth2 tree somewhere. Hopefully I'm not lying to you. There, right on the bottom. But that's what I don't know where to go from here. Me either, if I'm honest. Can we try adding a type hint? Maybe that'll work, I don't know. Sure, in the demo project? Yeah, just for those three sub types. Although you're probably not public, that might be an issue. You think these guys need to be public? Well, the type names do, because you want to reference them from an annotation. You can do the, oh no, no, no, I'm sorry. You can use a, yeah. Yeah, that's, by the way, that's Andy Clement, he's a resident mad scientist. Yeah, I'm kind of surprised it's missing that too, if I'm honest. Like, I don't know, it's one thing as a Hail Mary that I might work, I don't know, maybe Andy can correct me here, but what if we did a type hint? Yeah, okay, so just add a type hint for all three of those types. That'll force it to keep the, it'll keep it in the config. Yeah, type hint dot parentheses. And then I think it's like, you can do a string name or a type name. Yeah, string version, right? Type names. Yeah. Right. Yeah. All right, so I've had to hack up a bunch of JSON files, so I'm assuming all of these hint annotations prevent me from going down the JSON hell that I normally have to do. Right, and then you can refactor them with the types, so that's nice. But okay, so what you wanna do is get that full package to the class and then it's like dollar sign client ID connection or something like that. I think that's right. Whatever the sub path thing for a string version. This guy, the full like that, and then the full this guy. Andy, should we do the top level type or do you think we need to do the sub types as well? Like if I kept the top level type, it wouldn't throw away the inner types, right? Surely not. Where's this guy though? That's in a different class. Inner class, it's a static inner class. Yeah, so this is Andy, so treating one hell for the other. Yeah. Let's see. All right, so we need this client ID, client secret. I think, yeah, it's my hunch. I'm not sure if we, so my question is, will Gravium throw away the inner type? Like if we tell it to keep octa opaque, whatever. Okay, yeah, just animal, like worst case, we only need one, but I think that's the right syntax, isn't it, for a fully qualified subclass with a dollar sign? Yeah, I mean, that's what it is down here, right? Unless it needs to be slash instead of dot. Yeah, I'm not sure. I think Andy's saying do everything, because reduce the round trip here. Well, he's saying don't do everything, but he understands the pain, so let's just do everything just to fail fast, and then we can prune it later. Andy, is that the right syntax? Client ID, is that opaque token introspection conditional dollar sign, client ID condition? Does that, hey, would reference a specific one? Hell, he's looking. He's looking, he's looking. She's just pulling in here, what's going on? Why don't we just pull him in this? Well, yeah, he's my friend, right? Like, he's my lifeline. He's got like real work to do, so. Right, right, I understand. Even, you know, heckling from the internet. He doesn't get paid to be on camera. Yeah, he gets paid to make, he gives us reasons so that we can be on camera. There you go. This is going to be awesome when it works, and we're going to all be glad that, you know, Andy woke up and wrote the code that made itself. Well, let's talk about, let's get ahead of ourselves because we're going to be waiting here a bit for that to compile. How would you move like these resource hints and these type hints into the Octa Spring Boot Starter? Is that the JSON file that Brian's talking about? It wouldn't be in the starter because the problem is that you need to put, you need a dependency that gets added to the dependencies of the Gravium compiler itself, the plugin. Right, so the Maven plugin has a dependency section. So, we don't really have a lot of standard device. What I've just been doing is I create a separate jar called something something hints, hyphen hints. In there, you can put a class, call it, you know, Octa Starter native configuration. It extends native configuration. You can then add these annotations to that type and then you put that in a service loader, JDK6 service loader reference. So meta-inf services and then it's like the fully qualified name of native configuration type as the file name, right? And then you put the class that implements that interface the one you've just defined in that text file. So meta-inf services fully qualified name to the type called native configuration for the text file name and then put a reference to your hints class that you'll have defined. So now it's basically the same annotations just in that other class? Yeah, and that class implements or extends the native configuration interface or type, rather, from, you know, you also need, when you create that spring dependency, that extra hints library, you're gonna wanna add the spring hyphen AOT dependency. So it's exactly the same as the spring, whatever the spring native, what do you, yeah, go up there, it's in your build. Right here. No, no, keep going up. Spring native, see where it says org spring framework experimental spring native, replace the word native with AOT and that'll give you access to the programmatic because going beyond annotations, there's actually a mechanism you can use to programmatically register hints as opposed to with just static annotations, right? So we'll do that, but... So is any of these, you know, sugary awesomeness, is any of this like sort of being done by the growl team themselves? What do you mean? Well, like, you know, this is great for spring folks, right? Which is, I mean, you know, what we're here to talk about, but, you know, like Corkis and Micronaut and all those folks, I mean, do they have to then come up with their own sort of equivalent or is any of this getting sort of lumped into growl to make these things easier? I have no idea, no idea. I know that the growl team has, I know our team and that team has, you know, collaborated here and there, I don't know, the extent of that. I'm not, it's above my pay grade. I'm just here to write. No worries. I just, I'm making silence. Reflection is hard, you know, that's all. Yeah. And so then, as far as the dependency, so we had a new jar, right? It's a new Maven coordinates and all that. Do we make our starter dependent on that or do people actually need to pull in that dependency into their projects? If they want to use the octabit, they need to bring in the starter and then bring in the hints jar for their Maven plugin. What happened? Oh, no. Did you miss one? Octa. The ocean, because it does not exist. How about the parent class there? Yeah, you might want to. The training class. Yeah, I would just add that. Which one's that? The opaque octa. Yeah. This one? Yeah. Okay. Just, you know, you can never be too sure. So like that? Yeah. And then one last thing I would try. I don't know if it makes a difference. I don't know what the default is. But for me, you know, I threw some salt off my shoulder and then I also make it so that the access equals access bits dot all. So for the attribute for the annotation, it's access equals access bits capital A, capital B, dot all. Cool. I don't know. Yeah, well, let's just rinse and repeat. That's gonna be so much fun. How long did that take? Yeah, we got another, let's see, four minutes. Yeah. Do you want to set up that extra jar quickly? Sure. Yeah. Well, start, kick off the build and then we can set up the jar. I don't know. I did. Okay. Yep, let's go on. So I, me, I just go to start.spring.io and go to new, I could just create a new jar, a new project that way. And then I gut it and get rid of the plugins for everything except for the dependencies. So add spring experiment. Yeah. And then call it. Anything else? No, yeah, I mean, you know, whatever you, just call it spring native. You know, whatever you want to call it, octa, hints. I'm out there. Scoring, right? And then, hints. Or a spring native. Okay. And then anything else? Nope. Just, you know, fingers crossed. All right, can we do it? We got, what, 13 minutes? Oh, the anxiety. Why don't IntelliJ in that kind of thing? I just realized that, you know, when you install the IntelliJ command line tools, and if you have, you know, whatever it is the IntelliJ toolbox or, you know, with, with, with all the other awesome IDs they have, there's a command line tool for each one, which I feel silly admitting I didn't know until yesterday. So even, I don't have to run immediately. I just looked, I don't have to run it new and exactly, but, you know, it would be. Oh, we're getting it done before then. So we're, we're. Dirty. Always out there. So would you take everything, even the native hint for the HTTPS and put it in there? Yep. Okay, so. Oh, Andy, welcome to my life. I don't, I think Rable's probably met Andy. He, he's a saint. I would just create a new class. Oh yeah, whatever. Create a new class called, you know, ints or something and just get rid of that one. You don't need that one. You have to have monk like patients to. Yeah. I mean, if it doesn't work, we're just going to hold Josh hostage, I guess. I mean. Oh. Okay. So call and then extend native configuration. Your class. Yeah. And so you just, I think this is why you have to add that extra jar or go, go back to the build. And then. Oh, that was the AOT one. Yeah, I know. Oh, this one. Yeah. Just call it spring AOT. Yeah. Don't get, it's not spring native AOT. Just spring AOT. Okay. Can you, what's the GitHub repository for this. OctoSpring Security OOF. I will, I will paste it in here. Yeah. Is it public? Is it open to us? It is, yep. Yep. I just can't type right now. Okay. It's usually at the top of my history. Now it's, you know. Oh, it's. Because I'm looking for it. All right. So it is octa slash octa dash spring boot. Oh, I didn't show it. There we go. Okay, cool. Thanks. Have a look at you later. So, okay. That's part of it. The other thing is you need, by the way, look at that. See that native configuration class? Can you do, you know, implement methods or? Yeah. Overwrite the compute hints method. Compute hints, okay. That's one of my favorite methods in all of spring native. That method, you can return a dynamic list of hints. So if you want to return, you basically, you create a list of hint declarations. It just, it can be zero or it can be five or it can be whatever. And you get access to this kind of reflection-like thing called the type system. It's not actually the JDK type system. It's not Java reflection, because of course we're doing this at compile time. But you get access to this thing that you can use to query things about the type system. So for example, find all classes that are descendants of this class or, you know, find, you know, give me a reference to a type and all that. And so you can actually check to see what annotations are present on types. You can find classes, you can find subclasses, hierarchies, and you can, you know, programmatically based on this dynamic introspection, register these hints programmatically, right? So you can actually register custom hints using for loops and all that stuff, which is cool. So if you're doing frameworky kind of stuff, and I'm not sure if this stuff that you're doing quite falls into the domain where you might need this, but if you're doing frameworky kind of bits, it can be very useful because, you know, if somebody registers a custom component type, we can programmatically discover that with the presence of the annotation and then register a hint for it automatically. So you never even need to know about it. Very cool. Yeah. You can go ahead and un, you can just comment out that method. There's nothing, I think, yeah, just for your own reference for later. And then you need to create a source main resources meta-inf. Is it not commenting? Oh, there you go, whatever, yeah. First main resources meta-inf directory. And then there's another folder called services service, think services. All right. Let me go check. Fine, I'll do work. I'll see how we're building here back here. Oh, five minutes and moment of truth. Oh boy. Oh, is it working? Let's find out what my access token here. I'm scared. Come on, baby. Hold me. Boom. Oh, that's great. So those typepins, nice. Ravel for the win. Ravel and Brian for the win. Awesome. Yeah, that's cool, man. All right, well, I can even just share. All right, services with an S. And then it'll be the fully qualified class name for native constrictions. With no extension for the file and so just copy org spring framework native X type native configuration that package import there. Which one, this one? Google has a little a second part. That one. Yeah. This one? No, no, the native configuration one. Where it says import spring framework native X type native configuration. Just copy that whole thing. Create a text file called that. Yeah, Google has a little, I think I figured what it's called auto services. It's a little project that you can annotate and will generate those files for you. Which is pretty handy. And then copy the fully qualified name to the hints class. It pasted into that text file. That's maybe. Yeah. Like that? Yeah, that's it. So let's try. So now if we do this, you go ahead and do a maybe install on that. Oh, no, sorry. Go to your POM.xml first. Let's get rid of the spring boot maybe plug-in and the Gravian plug-ins and all that. Cause we just want a regular jar or nothing else. I think you just delete anything. Yeah. We don't need any plug-ins? No plug-ins. You might need the repositories, but nothing else. Okay. Good. And you can delete the profile I think cause it's sort of, you know, not gonna help yet. Okay. And then do a maybe install on that artifact. And then the moment of the real proof of the pudding is to build to then reference this from the client app instead of, you know, what would comment out the hints that are in your client app and then reference it from the Maven plug-in dependencies. All right. So we got this right here. Well, we can copy all of it, right? Yeah. And we go back to our project. Just here, add it here. Not there. You have to go down to the build plugin for the spring AOT Maven plug-in. Yeah. It's in here? Yeah, above executions. There's like a dependency stanza. Oh, hello. What's this? You sure? Well, maybe it's, I don't know. It's above executions, not inside of it. Okay. And you're saying we can remove all these? I would comment them out first just in case, but yeah. The comment shortcut isn't working, so it'll be the whole fashion way. No. All right. Okay. Oh yeah. Here we go. Four minutes until we, oh, we have exactly five minutes according to it. All right. Yeah. This is it. So, I'll wait. I mean, I think if you fix a bug like this in an hour, I think that's a huge win. I mean, I guess technically it's three hours because there's three of us, but you know, who's counting? Actually, Andy did most of the work. That's true. It's true. We'll bill Andy's time in here too. Yeah. We're just, I'm just a great observer. We gotta send Andy a T-shirt now. Oh yeah, absolutely. This is so cool. That is cool. You guys got this starter up and running and you had to do some changes. It wasn't exactly perfect yet, but can you imagine how good it's gonna be just to give it another hot minute, you know, at the rate of change and the way things are getting better? Yeah. No, that's pretty minimal, right? I mean, you know, these hints in here and there was what, there was one bean that needed tweaking? Yeah. And so I think both that type hint, Andy can correct me wrong, but I think that the bug, I don't think you need that type hint. It shouldn't be required. So hopefully that goes away one day and then the other thing is the, having to change the parameter method, that's, you can just leave that. It's not a bad change. It didn't break your code or anything like that, but hopefully that won't even be required one day either. Either way, you're functionally, you didn't lose anything. You didn't make a compromise with that change. It's just different. Yep. All right. Oh, so excited. All right, three minutes. Hit the turbo button. Well, the question is, if I don't show that screen, will it build faster? Well, we're gonna claim victory. I mean, you could just turn it off. Oh, it worked. Okay. Yeah, all right, so. Oh, yeah. Oh, you got, do you see that? That's a good message to get. That's help from somebody who knows. Oh, that's so cool. We will absolutely do that. That's legit. Like you're helping me spring better with your bugs. This is so cool. Oh, it compiled, no, it's not compiled yet. No, we're down on wire. The agony. You got three intelligent windows here at this point, right? You got the client app, the actual starter and the hints jar. Right, yeah. Make sure you don't. That's a normal day. Write that in 50, 50 browser tabs and call yourself a developer. Well, so my. Stream yard, right? Stream yard. So my life is that I always do these demos on stage or on screen or whatever the 2021 equivalent of that is. And then as soon as I'm done, I'm like, oh well, RMRF all those projects that I created because it's the same thing. I've done it before. I'm not particularly attached to it, but sometimes I have actual code that I do. And I, for reasons, sometimes let those projects live in downloads just so I can hack something out. And then invariably, I'll go do a presentation, generate like four more modules or whatever in the course of my demo. And then at the end of my demo, I'm like, goodbye everybody. Close, turn off the camera. And then RMRF everything in downloads. And I'm like, oh my actual code is there. Son of a, you know, so make sure whatever you do when you close the camera, when you turn off the camera, don't just chuck all the code you created as a sample like I always do. Good call. Well, at least we got it recorded, right? Like this is on Twitch. We'll save it and put it on YouTube later. So even if I do delete everything, we can rewatch it and know what we did. Absolutely. All right. Are we gonna do it? Yeah, we got it. Yeah, we're down to seconds, Matt. Seconds. Come on, baby. Do they literally like a cane and a hook? Do they literally? Yeah, they just pulls it. Oh, there we go. I don't think Twitch cares. No. We're here. Ah, no. Oh, no. What did you do? I want one. Well. Well. Well, we know what we need to do. Yeah, we're working. It's way cooler, right? I'm still gonna call victory. I don't, let's see. Oh, yeah. I'm missing something, obviously. Let me see spins. As the same one that can't find it or whatever the, okay. Is that file? Can you go back to the meta-inf directory? Is that a file or is that a, what is that? It doesn't look like it's a file. No, but is it inside of a folder called services inside of another folder called meta-inf? Looks like CD source main resources. All right, CD meta-inf services. Oh, wow, it looks like a, okay, that's weird. Yeah, it looks good. What did we do? And your, no weird maven problems, right? Like that jar did get pulled in to your project? Yeah, I mean, I added the coordinates over here, right? And it worked. Yeah. Unless there's some misconfiguration here on the AOT maven plugin. Can we see the, let me just go check some of the project. Which one did I work on? Here's where the pair programming aspect comes in. Let's make sure and watch the chat. We're in sudden death now, right? Like, yeah, okay, how bizarre. All right, yeah. So I assume a resources config, JSON gets generated at build time. So you could control your target directory looking for resource-config. Yeah, but it should be exactly the same as before. I'm missing something obvious. Yeah, and then. Andy, you've been a huge help. Thank you. We will get your address and send you a T-shirt. Okay, so are you two turning to pumpkin or do you have a minute? Oh, I got a minute. I got nothing. Yeah, let's see if we can figure this out because this has to work. We can't just leave it here, friend. You can't go to sleep till you figure it out, right? It's one of those bugs. Okay, so. I know this is ridiculously obvious, but did you do a minute install for the hints jar? Yep, right here, right? So close, okay. What is the issue? It's a native hint. It's not about the type hint over here works, but it doesn't overheat it. Yeah, but it's literally the same, right? Hints. Can you, I mean, does it matter? I know this is gonna try to sound ridiculous, but can you rename hints to like octahints or something? Is this one right here? Yeah, just trying everything. And then reinstall it. Uh-huh. He didn't share the app. Let's see, we're gonna install, okay. That's so bizarre. Why would, did you change the text file, the services? Oh, no. Oh, yep, yep. Oh, it did for me though. Look at that. All the J's smart like that. So smart, so smart. All right, so we got another four minutes. Why would that make a difference? I don't know. I still don't know what I'm, I lost here. Did I, okay. So if I look here, demo, pomegranate somehow. And it, the dependency needs to be the dependency of the plugin, right? Yeah, just the dependency of the Spring AOT Maven plugin. I mean, if we took it out with it, give us that error that it was before, like the original error. Probably the idea, right? The other thing, by the way, we tried removing the Spring AOT dependency from the client app, from the demo. So yeah, it's transitively brought in. Yeah. Oh, you've already got it there. Okay, so it's just Spring Native. That's fine. Is it the same version for both? Yeah, it should be, right? 10.10? Yeah, 0.10. 0.10.0. How do you, okay, let's see here. Dependency, Spring AOT Maven plugin. Yeah, you might try like removing some of the hints and see if it breaks the old fashioned way. Yeah, we'll wait till this one finishes. Yeah. The other thing is, can you go back to the hint class? Okay, so we got type hint, native hint. Just indulge me here. In the native hint, there are attributes. One called resources and other one called types, I think. So can you put those other two hints as part of the native hint? Because that native hint, believe it or not, is an umbrella. It should just find all of them, but just try doing that. Try doing resources equals and then put the resource hint. And do this string here? No, the whole annotation. Oh, you're saying put it inside there? Yeah, nested. Like I have no idea if this would make a difference, but it, yeah, okay. And then same thing for comma types, I think. Yeah, and then put the type hint, the giant hint of typiness. Okay, that's an ugly annotation. Yeah, yeah. I don't know if that'll make a difference, no idea. Just trying to see if it's not detecting it or something. Because it is the root of that API. You saw it work, so I don't know why it would be different. But do you need the spring boot starter as a dependency on the octahint library? I don't know why you would. Can't imagine. You just need that AOT one, right? Well, that's what I'm wondering is because, you know, in this one, like it has access to the starter, right? This one doesn't. Yeah, so maybe copy and paste that starter into the hint library just for, you know, giggles. Like this thing right here? Yeah, trying to get it as similar as possible and as canonical as possible. I literally just got this whole process to work for the JetBrains Exposed ORM, like five days ago. So I know it works, or at least it can work. I'm just don't know why it's not working here in particular. All right, it's something small. Yeah, it's always is, right? Is this where you spend most of your time? Yeah. You know, like try this, run the build, come back in five minutes, change one character, run the build again. The nice thing is if we do this, nobody else will have to do it, right? Exactly. You can just update the docs and now people will be able to take their apps to production with Gravium and Spring Native. Unchanged, hopefully. Totally. And by the way, you should test the other stuff that your app does. Maybe it might be time to re-enable those tests to see if there's any corner cases appropriate. Okay, great. Yeah, but we could start, so we have a whole suite of integration tests, but we can build a native image for one of those tests and run the same test and... Yeah, everything should work. Okay. All right, so that first one that I tested was just the octahints, right? We renamed it from hints to octahints, so that wasn't a very big change, but this one obviously is bigger. Yeah, just throwing the kitchen sink at it. But in your other examples, did you end up doing all this nested stuff? No, I think I did, did I, let me check. You know, I had just one type hint at the root. That was the thing. What I was doing is I had to bring in like 20 different types from the exposed ORM project. So it was just one type hint annotation with like a typed array pointing to 20 different class literals. Right. And it was in Kotlin too, so that was cool. It was like the class itself was just class exposed ORM hints called a native configuration. And then there's like every other line except for the imports was all this annotation. It's like 59 to 16, so 16 to 59 lines of code. Well, cool though. I mean, even if we don't quite figure this part out, we figure out the problem. Yeah. We built it, it works. I mean, like I said, I'm pretty excited that it was this easy. I mean, I know we tripped over it, but there's not a lot that we had to do, so. No. And we'll get this to work too. Like I know it can be done. I just want to get it done now, now. Yeah. I like the idea of the hints jar too. That way, keep it separate. If you're building, you know, native jars or native images, you can just pull us one extra dependency in and. Well, yeah, you can imagine the circulator problem we'd have other ways, right? Like we need the hints to tell GraphM how to compile the starter and you can't have the starter unless it's already compiled. Yeah. Doobie doobie doobie. Come on, growl. Do the thing. We talked about this. GraphM is. It is a bit painful to debug it, right? Yeah, yeah. But you know, hopefully some of the, like again, the fact that 90% of it works flawlessly without changes and hopefully soon that'll be closer to a hundred. You know, like that. The goal is that you don't have to debug this. Or if anybody has to debug it, it's you and me and other people that are shipping libraries that other people depend on. But I want this to just be like, just flawlessly simple, right? And like I said, ideally, you know, the result from your hint will just be those two little annotations, native hint and resource hint. Right. That'll be it. Hopefully we get rid of some of the need for the other stuff. Come on, compiler. Oh, go ahead. I was just gonna say, even though I'm covenching, Valvam is pretty amazing. I'm legit impressed. Yeah. And even that the resource hint probably belongs in that other project. So that's a, you know, another oxy dependency that just does some common validation, but that should probably belong in that project anyway for, you know, even non-native spring native folks. Oh, true. You could just put the JSON file, yeah. Ship the JSON file. You can do, what is it, image.properties or something? That's what the native hint gets used to this. Wait, what? What happened here? Same thing. This is about the time I break down and I start using the Maven dash X flag and verbose and digging through things and crying a little and... Yeah. Can you share that? Can you code with me for the native hints one? This one here? Yeah. It's gonna give me a URL, I think it pops up here and says. Oh, do you wanna turn off your camera for that? Well, we don't want just anyone joining. No, it's probably the other advice. Yeah, I'll stop it and then try it here. Little access. Weather. 26 degrees. It feels warmer. Maybe there's another one I have to stop first or something. Do, do, do, do, do. I have no idea what this fuzzy thing is on my screen here. I'm mesmerized by whatever, whatever, whatever that is. It's, it's right, it's right. Where is it? I can't figure it out. It's right, right here. Oh, it's my other camera. All right, so now face us into the private chat and stream yard. Like, I see Michael calling, it was my camera. Hey, so you want me to share my screen again? Yeah, it's all you. So I, okay. So this is here. Let's opt to Springwood Starter. This is the snapshot that you're working on right now, right? Right. Just think about it. So that's made of configuration. Source, main, resources. Why does it show as a period? That is so weird to me. Which one? It shows as a meta-in-period services and I don't understand why. I think it's because under resources, they expect package names, right? So even if you did like comm slash whatever it would do comm dot. Oh, open up your terminal mat and do find space target slash, what are the compiled classes? I forget what that, gener, where is it? Just classes. Oh, I should have known that off my head, but. Enter me on my client. And then see what you got. Looks like services. Yeah. Is there like a, is there a space in the file name or anything like that? I don't think so. But what about in the IDE if you click on that? Cause, oh yeah. Okay. That's fine. I'm gonna delete, you should delete application of properties. Yeah. And then what else do we need? I'm gonna add a, the other thing I wanna see is what happens if you go to the source, if you go to the target, you know, go to the target directory of the client application. What's the hint for generated? Under where? Look for like a, look for the meta-inf directory and then look for spring AOT, you know. Are we looking for com octane here? Yeah, I look for all that stuff, like the hints that you'd expect to be there. Are they? Well, there aren't any hints that we added though, right? These aren't the ones. That's the conditional. Or is that a different one? Yeah. Go to reflect config. Yeah, there they are. Well, what the hell? It even has all of two properties proxy. So we know it's the right syntax. All of that is generated by the, spring AOT processing those annotations. Yeah, okay. I mean, at what point, like I don't get it, like we're putting in the same config, right? Right. Can you do a reinstall of the octahints native hints library? I just made some changes. And then just do maven spring AOT, colon generate and the client and the demo. We're just gonna be an install here. Yeah. Or maybe skip test, not that we have any, funny. And then here we want to do, just do maven clean spring hyphen AOT colon generate. So that I put, I did the good old fashioned, there you go. Hello from octahints. So that's definitely getting involved. Okay. What? Oh, do a maven package quick. I don't know why it does this, but you need to have a target directory. Okay. Now do the spring, hyphen AOT generate again. No, oh, no clean. Sorry. No. Package and then this. Yeah. Just do that. We don't want the target directory to go away. Always, always keep your test. That's a T-shirt waiting to happen. That would be the worst. Okay. Now you want me to look at something? Yeah. Do they result in JSON files? Do they, do they reflect what we put in there? Do you see in the image properties? Do you see the enable URL protocol? I should guess. Yep. Yeah. Okay. That's our thing. And then what about the resources? Do you see that calm, you know, commons config check, whatever. No. The resource config. On the resources? Yeah. Yeah. On what was it? Config. Check for slash. Yeah, that one. Nope. Yeah. You know, that's there. And then what about the type hints? Are those there? That's in the reflect here? Yeah. Yep. Maybe try recompiling. I don't know. Like it's bizarre. Our Maven plugins are still fairly new. That's why I think cleaning it up once was a good idea. Cause we threw away the old thing. So now try doing a native build again. I don't know. Those files are there, right? So at this point it's just, we know Spring AOT is doing the right thing. It's generating the right resources you'd expect. I'd be kind of interested to see what the delta is between this and what you would have gotten had you added those annotations to the demo application itself as opposed to the via the transitive int jar. Right. So that's probably the next step, right? Yeah. That's when we're having a lot of fun. That's when... When we're creating another build and then dipping. Yeah, exactly. We're dipping JSON files that have millions and trillions of entries. Still not as much as your typical JavaScript app, of course, for Hello World, but, you know. I had found a great JSON and XML diff tool at one point, but I haven't had to do that in a while, luckily. So... I use Smart Synchronize. Does that work well for JSON? It'll do like directories. It'll do directories, but it's still raw like comparison of files. Oh, yeah, yeah. The issue is that with this, sometimes the entries can get written in different orders. Right, so... Yeah, it can make a little... This is the only directory with the files, right? Yeah, I think so. By the way, it doesn't have to be, by the way. That's what other jars that have a meta-inf directory in it, if they have the right config files, it doesn't matter what directory it is underneath meta-inf for slash native image. Gravian will pick all of them up. There we go. We're going to do it. What else is there? This is, yeah, this is where it gets interesting. Wait, what did you just do? Did you re-named it while it was coming out? Well, no, I copied it so we can... Now we have the hints version, right? And then, if this works, like... Yeah. You change something, and so that's great. Or we, you know, the clean did something. Yeah. Then we'll do it with the annotations on the demo class, demo application, and then we'll see the difference to the files. That'll be, again, that's the fun. That's where, you know, turn on the music. Now the question is, can you just change the files and run it or not really? Because these feed into the grawl process, right? So not really. Yeah, but, yeah, you don't want to fix the source. Right. We need, like, some background music. Yeah, yeah, I feel like, you know, or, like, some sort of, you know, lightning talk. Every time we run the build. No one has to do a tack. I would like to have some really awkwardly inappropriate music, like, because we're, you know, this is starting to get... This is starting to border on depressing. So if we had some really uplifting music that just felt completely wrong, like, you know, fling on or whatever, like, you know, helping it out from the top of her lungs. But meanwhile, we're all like, what the heck, come on. That's the best. Just let people wallow in the awkwardness at all. All right, I think, I think Matt, this is by itself is probably enough to get, to get, you know, some sort of approval to get you an expensive, bigger machine, right? Oh, yeah. For sure. I think, you mean? One of those cheese graders, maybe? Yeah. Oh, okay, 355. Target, demo. Nope. What is that? And why? Now we'll change it to this. All right, let's copy it again just to make sure in case anything changed. Delete the old one. We've re-enabled that. We go into here and we... Disable that. Move that one, yeah. And then clean it. Up, up, you gotta, you gotta, you gotta straight. There weren't too many there. Ah, ah, the deeper. And here we go. The next talk will be. What a profit with Rable. I got one for you. I'll stop screen sharing. So, you know, I'm not taking up resources there. Josh, do you have the OCTACILI installed? No, sir. So maybe Brian, if you wanna walk him through that and I'll do like a dip over here and see and... All right, all right. Cause that uses GraalVM as well, right? It does. So, what do you wanna know? You want me to just walk through a little demo here of it or... Well, I think Josh doesn't have it installed. So like show him how to install it and see if he can, you know, create an order. All right, all right, let's do that. Let me go to attempt director here. Make sure it's not in my downloads directory so I don't delete everything. It'll be interesting to see if it works again still, not that you've re-enabled annotations on the demo. Right. If it doesn't work, then we're like, what the hell? Yeah, it was like a fluke, something... Or it went right when it shouldn't have... Here we go. I might have to bump up my fonts here a little bit. Bear with me. All right, so this is how I got sort of interested in Graal. So we have this little tool, this little CLI tool called Octa. And if you're on a Mac, you know, you can install it with new... No, brew. Brew install. Actually, it's in a... It's in a cask. So I always have to go to... I'll grab the thing here. I gotta open up a new window. I'll share it. Don't worry. My computer's slow now too. I've got whatever Matt has. Yeah, oh yeah, that's still running. So yeah, so on a Mac, it's a cask. So it's Octa developer tab Octa. And you can install this. If you're on Windows and you're using Chocolatey, it's actually just Choco Choco Choco. The Chocolatey install command of just install Octa. And then on Linux, we have a Flatpak distribution. So any Flatpak fans, it is very similar, although much of anything we do on Linux, it's a little more verbose, right? So I already have this installed. It is just a native binary that I built the project.source also on GitHub. If you go to GitHub, octa slash octa dash CLI, you can see that project. And it doesn't use Spring Native, it just uses grawl sort of out of the box with a whole bunch of JSON config, which I'm interested in figuring out how to get out of here and remove. But the idea behind the Octa CLI is that we try to come up with a way to get you started, get a new application, basically as fast as possible using Octa. So there's a couple of ways to do it. You can actually download something from start.spring.io and then run octa, it would be octa apps create in that directory and that will walk you through, setting up an OpenID connect project and it'll set up all the properties you need for your Spring property to use Spring Security or the octa Spring Boot Starter. Or one of our favorites is you can just do octa start and then you can pick something like, I think this is one, right? Is it just Spring Boot? Yep. We'll see. It's been a little while since I've tried this, but that will download a project for you and I have a bit of a complex setup here. So I have a couple of options. Normally you have fewer options than I do. But octa, you pick an issuer, I have two set up. Normally you just have one, so ignore that. But that's it. So I've created a project, I can change directory into the Spring Boot directory and I can run, I can run MVN Spring Boot and it should run. And I'm gonna have to share my browser here. I should just share with my screen. Let's do that. Let's see if Matt's gonna beat me. Ah, it's still compiled. Yeah. All right. I gotta kill this code with me thing that my computer is killing me. And I'll move this window over here. I don't love the don't ever commit source man resources application properties. Like, could you tell them? Oh, yes. Yeah, oh yeah. Try to strike the balance, right? It's a really easy way to get properties into your application, but it's also potentially dangerous too. You should tell them it should be externalized but the rest of it can be committed or something. That's a great point. Point to some other examples and things. Yeah. All right. Let's see. Also properties could be environment variables. All right. So this is a very, very, very simple example, but if it works, it should. My whole application is protected. So this is a standard octa login page. I'm gonna go find my passwords here somewhere. Where is it? Where are you? One password? Like the hardest part of any octa demos and remembering your credentials. Yeah. My computer is still going slow here. And you're just doing a spring boot demo. Imagine a J-Hipster microservices when you get the Docker containers gone. I definitely think it's the sharing here. All right. Come on. Log in. How to cut your development time in half. Don't stream it. Perfect. All right. So yeah. So this is a standard login. I'm glad everyone's waiting so long for me to open up my password tool here. Yeah. So I've logged in. I'm crossing my fingers. Cool. It's doing the OAuth redirect dance here and it's gonna send me back to my very simple spring boot application that is literally a hello world. But I've done nothing. So the idea was I don't have to know a whole lot about security or OpenID Connect or all of those things. But now that I have an application up and running I can go learn some more and figure it out and at least I have something working to start with which is more than I can say about math's application right now. All right. Well, the good news is I rebuilt it and it actually does still work. So that's good news. All right. So let's switch back over to your screen here. Yeah, please. See, so I got an octa app working on my side too anyway. So thanks for that walkthrough. That was cool. Sweet. Let's see. So go back to your screen or something. Hold on here. Here we go. Share screen. Okay. So I dipped the directories. We got one difference. What's that? The one on the left is the one that works and the one on the right doesn't. All right. That's the hints one. Yeah. Weren't those in there before? Apparently not. Which one is the working one and which one is not? The one on the left is the working one. Okay. So I guess that's what we would expect is those are the hints we want. All right, you see it's missing dollar sign. Oh. Are they in the one on the right though? No, I didn't think they're there on the right. Look for just client ID condition or whatever. Just that by itself. Interesting. So maybe the inner classes on the other one on the hint chart need to have a dot instead of a dollar sign? Or maybe you need a, that's a resource hint, not a type hint that you just looked at. We have type hints, but we don't have resource hints. Oh. So let's see. Can you copy and paste those three lines? These right here? Yeah, let's just go ahead and add resource hints to the hints jar. Some bit hacky, but might work. So you're saying like these guys? Yeah, you have to put a curly bracket around the attribute value. So equals curly bracket at resource hint. Sorry, I give it to that. Yeah, I was just gonna have you do multiple resource hints, but yeah, so resources equals curly bracket space at resource hint, right? Yeah, and then on the other side, and then create another resource hint annotation inside the curly brackets. Okay. And yeah, patterns equals, yeah. I would just put then a comment above so we can work from it. Yeah, okay, that's fine. So just try adding those directly. I don't know why you need this, but just in case, yeah. Okay. All right, let's do the whole dance. Make sure to re-enable the entity. Well, where did, I'm curious. How do you know these are resource hints? Because it says resource config that Jason. Oh, it's in the resource config. Huh, that's strange. It's strange. Well, we don't know if these need to be nested either, right? They shouldn't, yeah. I think that nesting thing I did was a Hail Mary, you know? And I don't think it, it didn't hurt us. It made us more organized. Because one of the things that's, go to the native hint at the top there, there's a thing inside, there's an attribute called trigger. Click on that, yeah trigger. That's the, you can make, you can have multiple native hints. There's actually an umbrella or aggregate native hint annotation called native hints plural. But, and the reason you'd want that is because you can have a native hint that's only activated when there's a class on the class path. So that's where the trigger is. Like a conditional? Yeah, yeah, exactly. So you conditionally activate the hint, but only if this particular type's there, right? So you can get very fancy. And, and so native hint is the, the vessel for those, you know, those, like, if this type is here, then do all these things, you know? But why would there need to be a resource hint if they're classes? Just as an inner class thing or? Well, it's, they're, they're classes that get read, but I, like, I don't know why we need to specify it if we didn't need to specify it the other time. Yeah, that's, I don't know. That's class, right? Yeah, whenever you do a class, if you do like class that forename, or if you load a class in bytecode without actually reading it actively, that could be a resource. You know, anytime you read something from a jar, that's a resource, right? So the loading of the class file itself is. Could be a resource. This was the only diff mat in those directories? Yep. Amazing. Good tool to have though. I'm glad you had that. I'm glad we looked. It's just interesting that when it's on the demo application it knows to generate those, right? That's a strange thing. Let's see if it works. If it does all, you know, like all, everything related to that, to those conditions is weird. Like it's definitely an action item for us to figure out why that didn't just work out of the box. The fact that we have to register a hint or a resource hint, a type hint or a resource hint, that's, you know, we don't want that. Right. Smart synchronizer, huh? That's the real lesson here. Right. It's Java based too. Ooh. And it's even, you gotta pay for it, but it's been worth every penny. How much is it? Is it like a? Oh, I think it's like 20 bucks or something. Oh yeah, okay. Sign me the hiccup. Okay. Cine Tevo. Cine Tevo. Cine Tevo. How do I buy? Buy now. Purchase. Yes. Smart gear. Oh, nice. They even a smart CVS if you wanna go back in time. Wait, what? Freeway merge? Oh, need. One year at 50 bucks. Yeah, 50 bucks. That's fine. That's a coffee money. Let's do it. This is in no way an endorsement of a particular paid product to anybody who's watching. I'm gonna use it. I'm gonna use it. You don't have to use it. Nobody cares. Yeah, so pay your developers. I don't know how many times, you know, my life that I've been told I can't buy a particular product that a company and, you know, the alternative is always like hours and hours cost more than, you know, the $20 to $50 tool. Oh my God. If this works too, it'll be worth it. We saved ourselves, well. Nice. 50 bucks right there. Yeah. Okay. It's almost hour two, but nonetheless, you know. We can always edit the YouTube version to take out this part. Right. And then like just Julia Child didn't like take it out from the oven and ta-da, it works, you know. Yeah. The first time we do the hints, it'll work. Yeah. We change these three things and it's done. For some reason, the video jumps forward and Matt has like more gray hair and his cheek and overall like visibly aged and older and the sun's down. Didn't behind me, there's no sun. I mean, it's a good thing I'm using crisp, right? Because I have like an air conditioner blowing on me that's quite noisy. If I didn't have that, there would just be sweat, right? You'd be like- I'm worried about mine. My air conditioner is off and it is warm in here. It's funny, cause I just saw like a tweet from Tim Bergman like a week or two ago where he was like prepping for a video and like wiping the sweat off his head. And I was like, I never have that problem. And then sure enough last week I recorded some videos around this same time a day. And I didn't go and edit them until like a day or two later. And when I saw him, I was like, ooh, shiny forehead, can't do those. All right, moment of truth. All right, here we go. Oh boy. Oh ho ho. Oh ho ho ho ho. That is dumb, but at least it works. All right, hey, woo hoo. Okay, you got something working for now, ship it, but we can make it better. We should make it better. That's about, I'll follow up. If you wanna file a bug, wait, if not, I'll do it. No, I'll file a bug. Okay. So cool, thanks for your time. You kidding? Thank you, we fixed it. We found the thing that'll make spring needed better for everybody by doing this. And now the octa story will be better for everybody. It's just right for everybody, you know. Good job, Jets. You're awesome. Good to see you. Yeah, thank you. Good to see you. We'll see you all later. Bye, thanks everyone. Bye.