Kickstart a Java REST API with Quarkus
In this tutorial, I’ll show you how to create a secure REST API and native image with Quarkus. You’ll see how to run a secure, OAuth 2.0-protected, Java REST API that allows JWT authentication. Then, I’ll compare its performance with Micronaut, Spring Boot, and Helidon.
This tutorial is also available as a screencast.
Prerequisites:
-
SDKMAN (for Java 17 with GraalVM)
-
HTTPie (a better version of cURL)
-
An Okta Developer Account (or the Okta CLI)
The brackets at the end of some steps indicate the IntelliJ Live Templates I used in the video. You can find the template definitions at mraible/idea-live-templates. |
Install a JDK with GraalVM
Use SDKMAN to install Java 17 with GraalVM
sdk install java 22.1.0.r17-grl
Generate an OAuth 2.0 access token
-
Install the Okta CLI and run
okta register
to sign up for a new account. If you already have an account, runokta login
. -
Run
okta apps create spa
. Setoidcdebugger
as an app name and press Enter. -
Use
https://oidcdebugger.com/debug
for the Redirect URI and set the Logout Redirect URI tohttps://oidcdebugger.com
. -
Navigate to the OpenID Connect Debugger website.
-
Fill in your client ID
-
Use
https://{yourOktaDomain}/oauth2/default/v1/authorize
for the Authorize URI -
Select code for the response type and Use PKCE
-
Click Send Request to continue
-
-
Set the access token as a
TOKEN
environment variable in a terminal window.TOKEN=eyJraWQiOiJYa2pXdjMzTDRBYU1ZSzNGM...
Create a Quarkus Java REST API
-
Use Maven to generate a new Quarkus app with JWT support:
mvn io.quarkus:quarkus-maven-plugin:2.9.0.Final:create \ -DprojectGroupId=com.okta.rest \ -DprojectArtifactId=quarkus \ -DclassName="com.okta.rest.quarkus.HelloResource" \ -Dpath="/hello" \ -Dextensions="smallrye-jwt,resteasy-reactive"
-
Edit
src/java/com/okta/rest/quarkus/HelloResource.java
and add user information to thehello()
method: [qk-hello
]package com.okta.rest.quarkus; import io.quarkus.security.Authenticated; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.SecurityContext; import java.security.Principal; @Path("/hello") public class HelloResource { @GET @Authenticated @Produces(MediaType.TEXT_PLAIN) public String hello(@Context SecurityContext context) { Principal userPrincipal = context.getUserPrincipal(); return "Hello, " + userPrincipal.getName() + "!"; } }
-
Add your Okta endpoints to
src/main/resources/application.properties
: [qk-properties
]mp.jwt.verify.publickey.location=https://{yourOktaDomain}/oauth2/default/v1/keys mp.jwt.verify.issuer=https://{yourOktaDomain}/oauth2/default
-
Modify the
HelloResourceTest
to expect a 401 instead of a 200:package com.okta.rest.quarkus; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.Test; import static io.restassured.RestAssured.given; @QuarkusTest public class HelloResourceTest { @Test public void testHelloEndpoint() { given() .when().get("/hello") .then() .statusCode(401); } }
Run and test your Quarkus REST API with HTTPie
-
Run your Quarkus app:
./mvnw quarkus:dev
-
Test it from another terminal:
http :8080/hello
-
Test with access token:
http :8080/hello Authorization:"Bearer $TOKEN"
Build a Native Quarkus App
-
Compile your Quarkus app into a native binary:
./mvnw package -Pnative
-
Start your Quarkus app:
./target/quarkus-1.0.0-SNAPSHOT-runner
-
Test it with HTTPie and an access token:
http :8080/hello Authorization:"Bearer $TOKEN"
Startup time comparison
I compared startup times between frameworks by running each image three times before recording the numbers. Then, I ran each app five more times and averaged the results. I gathered these numbers on a 2019 MacBook Pro with an SSD, 2.4 GHz 8-Core Intel Core i9 processor, and 64 GB of RAM.
Versions used: Quarkus 2.9.0, Micronaut 3.4.3, Helidon 2.5.0, and Spring Boot 2.6.7 with Spring Native 0.11.5.
Memory usage comparison
I tested the memory usage (in megabytes) of each app using the command below. I ran it right after I started the app, after a single authenticated request, and after five authenticated requests.
ps -o pid,rss,command | grep --color <executable> | awk '{$2=int($2/1024)"M";}{ print;}'
The chart below shows the memory usage after five requests.
Comparing Native Java REST API Frameworks Live Stream
I missed Devoxx France this year, but I’m still doing my presentation! I’ll be live-streaming Comparing Native Java REST API Frameworks on June 7, 2022 at 6:00 MDT (14:00 CEST). Join me or watch the recorded version below!
Secure Native Java with Quarkus FTW!
⚡️ Create a secure REST API with Quarkus and the Okta CLI: okta start quarkus
🚀 Find this example’s code on GitHub: @oktadev/native-java-examples/quarkus
👀 Related blog post: Build Native Java Apps with Micronaut, Quarkus, and Spring Boot
Okta Developer Blog Comment Policy
We welcome relevant and respectful comments. Off-topic comments may be removed.