 Hello, Java developers. My name is Matt Ravel. And today I'd like to show you how to build native Java apps and REST APIs using Micronaut, Quarkus, and Spring Boot. Let's get it up. This screencast is based on a blog post that I published way back in June of 2021. But you can see it's been updated as of December 9. So you can see I updated to use Micronaut 321 and Spring Native 0.11. And the week before I updated it to Java 17, Micronaut 320, Quarkus 251, and Spring Boot 261. And up at the top here, there's a link to a GitHub repo that I've already got pulled up right here. And it has all the completed code that I will be showing you today, if you just wanted to clone it and run it yourself. And that's kind of what this post does here. It just has you clone it and run everything instead of creating it from scratch. But today, I'll create everything from scratch. So there's a demo.adoc in here, adoc for ASCII doc, I have a handy dandy ASCII doctor plugin. So if I do the raw version, it looks kind of nice. I'll go ahead and throw this on the left here. And I'll open up a terminal on the right. And you can see the first thing it says is you'll need SDK man, which I already have installed. If I do SDK version, you can see it there. And then HTTP, which is installed as well. And we'll use octa CLI to create an octa developer account. So you can get that from CLI octa.com. And so I will use some shortcuts at some point. And those will be intelligent live templates that I've prerecorded. So if you see me type just a bit of code and it spits out a bunch of code, that's what's happening that you can get mine from mrable idea live templates on GitHub. And so the first thing is you'll need SDK man to install Java 17 with growl VM. And so if I did SDK install Java 21 dot three dot zero dot r 17. You'll see I already have it installed. And then if I do go install native image, it'll say I've already installed that as well. Okay, so we should be good to go. And if but I did Java version, you can see it's got growl VM in there. And so if you're not using a version with growl VM, this will probably work on Java 11. But you'll still need growl VM, it'll basically give you a weird sort of maven stack trace. So make sure and check that using a growl VM version. And so the first thing is using the octa CLI, we're going to create an access token so we can access all these secure API as it will be building. So I have the octa CLI installed. If you don't have an octa account, you can run octa register. And I already have one. So I'm not going to overwrite that file or create a new one. But it's really easy to create when a prompted for like, first name, last name, email and company or something like that. And you can also unlock octa login if you already have one, and basically log into that admin console that way. But I'm going to start by creating a app that we can use to get an access token. So octa apps create. And we'll just call this OIDC debugger, because that's the site we're going to use. And it's going to be a single page app number two. And then we're going to use this debug for the redirect URI. That's a callback on the OIDC debugger site. The default for the logout is just fine. And if you have multiple authorization service configured to get prompted like this, choose the default one. And then these are the values that we'll need. So you can navigate to the open ID connect debugger website. And then you'll need an authorized URI. And you'll want to substitute this with your octa domain. So mine is dev 253. And then the client ID, then the state, whatever you want it to be. And then we'll do token. And you'll see here, it's actually using authorization code flow by default. So one of the things you have to do is go and enable implicit flow on this app. So you'll log into your octa application. And I'm going to continue anyway here. And I'll go to applications to the one we just created. And we'll go to its general settings. And you need to enable implicit and allow an access token with implicit grant type. Then you can save that. That'll be able to close that window. And then we can try again. Didn't like it. One more time. Open ID. Let's do email and profile. And then 123. No code. Boom. Now we got an access token. Okay, we'll need that in a future step, put this back on the left here. And we can set it as an environment variable. Okay, so now let's create a micronaut API. And what I'll do is I'll start by creating a directory called native Java examples. And in here, we'll do SDK install micronaut. And the take command just as a maker and CDs into it. So that's pretty fancy. I already have the latest version of the micronaut CLI installed. And then I can do mn create app. And we'll give a package name, comhawk the rest app. And we'll specify a maven for the build. So we're consistent between all of them because some of them have maven by default. And then the feature is security dot JWT. And we'll create it. And then we'll move it to just be named micronaut so we can tell, you know, these apps apart. So and then in that micronaut, I'll open it up in IntelliJ. And then I'll create a hello controller in the controller package. So that's the IntelliJ live template I was warning you about spits out all that code for me. And it's just going to enable a get for that hello and secure it. So it's authenticated and just return plain text. And then we can enable JWT security in this file by basically deleting all the existing security stuff and putting in a whole bunch of new stuff. So this is where we need our octo domain. And I have it right here. So my live template allows me to copy it once and it paste into both places. So we're just enabling security, we're enabling JWT security. And then we're doing some validation on the claims. And we're specifying the URL to the JWK. So this is JSON web key set. And then we'll start the app. mvn mn run. So that starts up pretty quick. You'll get faster times on the jvm as you start it more. So we could start with HTTP and go 8080 hello. And it gives us a 401 on authorized, right? We don't have access to it. But if we pass in that token, using HTTP and passing in the authorization header with that token, and everything will work and look you there, we got our name right there. And that's today's date. And so now we can actually package it as a native image using mvn package. I'll go ahead and stop this one back here. And dash d packaging equals native dash image that took about two minutes. And just to let you know, these times will vary tremendously based on your machine, what you're building on Linux or Mac, or if you're recording your screen. So I'm recording my screen right now with Camtasia. And that certainly slows things down. So normally when I do this without Camtasia, I just did it this morning. It was about a minute to build it. So you can see that that's slowing things down by about half. So I encourage you to run these tests yourself, to see what kind of results you get. So I can now start that native app target app. And it's going to prompt me to allow incoming connections. It started in 25 milliseconds. If I try it again is 23, try it again 20. So, you know, those times do vary a bit. And then we can make a request to it. So we'll need to reset our token here. Just go up until we get it. And then we can pass in that bearer token. And you can see it's all working. So even as a native app, it still returns my information. So it's still talking doc to validating that JWT and everything's working quite nicely. So we'll exit out of this one. And then stop this one, close this one. And now we'll do a corkis API. So let's generate with this command. So this is a Maven archetype that does this corkis does have a CLI, but you can't stop through SDK man or at least I didn't know you can if you can. And so we will just use this command using 251. It creates a group idea of Kamak the rest artifact ID of corkis and a default Hello resource class. And then we can open that up so idea corkis. And we'll create that Hello resource or actually just modify the existing one. So this is my short cut of QK Hello, you'll see it requires it be authenticated sets the path and the HTTP method. And then it just grabs a user principle and prints out their name. So now we can add the octa endpoints into this application dot properties. And grab these from here. The login will give us our domain name. And now we have a public key location for those JWKS key sets and our issuer right there. I'm not sure why micro profile actually allows or makes you call that the issuer, because the issuer actually contains that JWKS K URI. Maybe it's an optimization technique. But if I was to go here, and actually go to the well known endpoint, let me show you what that looks like. So it's dot well dash known, open ID configuration. There's the JWKS URI right there. So not sure why they make you look it up, but they do. So that's how you have to do it. And then we'll need to modify the test, because by default, it expects a 200. And we're going to do a 401 instead. So we'll just change that. Do some reformatting. And that test will now pass. And then we can test everything using MVN corpus dev. Once that starts up, we can go ahead and hit it with HTTP. And we'll get that 401 as expected. And if we try it with the bearer token, then it returns our name. So everything's working there. And we can compile it as a native app now. So stop it here and close that window. And you just need to do it MVNW, CD into corpus here, MVNW and package dash P native. That took about a minute and a half. So a bit faster than micronaut. We can start it up with target and corpus 100 runner. And then allow it. You can see that was pretty fast 15 milliseconds subatomic supersonic, or so they call it. So now if we go here and try it with 8080. Hello. All right, we get the unauthorized. And if we try it with the bearer token, or unauthorized as well, because we don't have the token. So let's go back here. Grab it token equals. Try it again. Now that's working. And you can see our corpus app works in native mode as well. Last one is spring boot. So we'll close this back to our instructions. And we'll start by creating a spring boot app using start dot spring.io. It'll use spring boot 261 dependencies are web OAuth to resource server and native. And then we'll open that up in intelligent. And we'll create that hello controller. And spring wins the longest import names, right? Mostly because we got org spring framework here. So it's always been famous for long class names. But it's actually the most concise as far as lines of code it requires. So they've been around a lot longer. The first release of spring boot was April 4, April 1, 2014. And then Mike or not was like October 2018. And corpus was I think November 2019. So spring boot has a fair amount of history that's now allowed it to refine things and get more concise. So now that we have our hello controller, we will can figure everything to be a OAuth to resource server. So that's where we put the issuer URI right here. And grab our octave domain. Put that in there. And then we'll add a security configuration. If you're using the octa starter for spring boot, you won't need this. But if you're just using a resource server, you will. And so we're basically specifying the resource server and telling it to use JWT for authentication. And then we can start this up using MVNW spring boot run. And you do have to mod plus x to that MVNW file. If you're using Windows, just do MVNW. Once that's up and running, we can hit it with the HTTP. And you'll see it's all working. It's got that 200 returns my username. And you might notice it's actually got a whole bunch of security headers in here. So that's one of the unique things about spring boot over the others is it does return a bunch of security headers by default. So that's great stuff. We can compile this to native using MVNW dash package and then dash P native. We'll stop this one so that doesn't interfere and close out IntelliJ. And what spring actually recommends by default is you build a native app and a Docker container for it. So that is possible using this spring boot build image command. The others allow you to build Docker containers as well. It just requires, you know, a different command. That took four minutes 23 seconds on that execution time. When I tried this earlier today without Camtasia, you know, recording my screen, it was just under three minutes. So there's quite a bit of lag added by doing a screencast of this. So now we can test our spring boot up using target demo. And then say allow that you can see it was 200 milliseconds there obviously on the JVM or not on the JVM. So that's a native app. And that time does vary. So if we try it again, now it's, you know, 065. So kind of tough to get consistent numbers here. But 068 is kind of consistent. So now we can do token set that and HTTP and everything's working. So even in native mode. So now what we can do is we can compare all the various frameworks. And again, this comparison isn't going to be great because I am recording my screen. So I encourage you to look at the blog post what it has. And these numbers do go up and down between releases, they're pretty consistent. But I guarantee if I actually ran all the numbers again, without Camtasia recording it like they might, you know, vary by a few milliseconds. And when you're talking a few milliseconds, you're really splitting hair. So if we were to start with Micronaut, well, we got a CD into there and then target app and allow it. So you see 22 milliseconds. And how I was doing it is I was running it three times and then recording the next five and then dividing by five. So we'll run it three times there. 22 is the last one. So now we're going to count them, right? We got 20, we got 29, 21, 23. And I'm not going to write them down because I do think like screen recording does slow it down a bit. But, you know, still pretty consistent. So right around 20 milliseconds or, you know, 23 milliseconds or so. You can see when I did this last week, it was actually 19. So the blog post numbers are better if we were to go into corkis and 41 milliseconds, 17. Oh, we're supposed to do the three before we start counting. So there's 20 milliseconds, there's 18, there's 19, there's 16. So a little bit faster than Micronaut, but not by much, right? Like we're talking a couple milliseconds. And then spring boot, target demo. So that's 68. But we're not counting yet. All right, we got to do it three times before we start counting. So we got 65 milliseconds, 66 milliseconds, 69, 66. So it's around three times as much as for a startup time versus the other three. And then the other thing I like to show is memory usage consumption. So we'll do this and we'll put this over here. And we'll start with Micronaut. And target is app. I'm going to hit it with my token here. But first, I'm going to record the memory usage. So I'm going to use this command. And executable is going to be app. You can see it uses 27 megabytes, right? And then if we hit it with the HTTP and run it again, now we're using 58 megabytes. So a bit of a jump there, right? Almost 2x when you actually hit it with the request. And so now we will try corkis and target corkis. So that starts up and then we'll run this command. And we're looking for runner now is executable. And so it's around 20 megs, right? And then clear that and then hit it with the request. And then try it again. And 32. So it goes from 20 to 32, which isn't bad at all, right? Not a 2x increase. So still a very lean, mean fighting machine. And then if we were to go to Spring Boot and did the target demo to run it. And then here, we're going to hit it with that PS command and use demo as our executable. So we're looking at 48 megs to begin. And we'll hit it with HTTP. And try it again. And now we're getting 62. So 48 to 62 again, not a 2x increase, but certainly a pretty lean, mean fighting machine as well. And so these are all the numbers I recorded earlier. If you disagree with these numbers or things are faster on your machine, I encourage you to clone the repo, do what I did and see what kind of numbers you get. And also this blog post I said I just updated today. And if you were to go down to the startup time comparison, let's look at the numbers here. This is what I got. Micronaut 272048. So actually the same that I got running it here with Camtasia. So maybe native apps, right? Aren't as vulnerable to Camtasia as a JVM is. And the interesting thing here is the megabytes after five requests. Micronaut does have an issue. I did tell them on Twitter, they will fix it in 322. So just to be aware of that, otherwise the numbers look very similar. And then there's some stuff on testing here. And some more links you might find useful. So I hope you enjoyed this presentation. If you liked it, follow me on Twitter. If you're interested in more, you know, Micronaut, Corkus and Spring Boot stuff, here's my tweet this morning about updating everything. And then you can see where I discovered the Micronaut stuff. If you click into that, you'll see there's an issue here. And Graham Rocher says they'll fix it next release. So follow my team on Twitter at Octodev. And of course, smash that button. Subscribe to our YouTube channel. And I hope you have a fabulous day. Cheers.