Matt Raible | @mraible October 8, 2021 Java REST API Comparison Micronaut, Quarkus, and Spring Boot
@mraible Who is Matt Raible? Father, Husband, Skier, Mountain Biker, Whitewater Rafter Bus Lover Web Developer and Java Champion Okta Developer Advocate Blogger on raibledesigns.com and developer.okta.com/blog @mraible
@mraible Today’s Agenda Why Java? Build { REST, GraphQL } APIs with Java Secure your APIs with OAuth 2.1 Build with Docker Go Native with GraalVM https://unsplash.com/photos/JsTmUnHdVYQ
@mraible Why Java? 25+ Years of use, abuse, and improvements Open Source code is available; many popular open source frameworks and tools Hugely Popular and widely used by many enterprises and web-scale companies
@mraible Download the JDK from OpenJDK https://jdk.java.net/17 Or from Adoptium https://adoptium.net Get Started with Java 17
@mraible Get Started with Java 17 Better yet, use SDKMAN! curl -s https://get.sdkman.io | bash 
 sdk install java 17-open
Java Releases and Features
https://developer.okta.com/blog/2020/01/09/java-rest-api-showdown Build REST APIs with Java
Serverless 💵 💸 https://unsplash.com/photos/glRqyWJgUeY
@mraible sdk install micronaut mn create-app com.okta.rest.app -b maven -f security-jwt Get Started with Micronaut
https://micronaut.io/launch
package com.okta.rest.controller; import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.Produces; import io.micronaut.security.annotation.Secured; import io.micronaut.security.rules.SecurityRule; import java.security.Principal; @Controller("/hello") public class HelloController { @Get @Secured(SecurityRule.IS_AUTHENTICATED) @Produces(MediaType.TEXT_PLAIN) public String hello(Principal principal) { return "Hello, " + principal.getName() + "!"; } }
micronaut.security.enabled=true micronaut.security.token.jwt.enabled=true micronaut.security.token.jwt.signatures.jwks.okta.url= https://dev-133337.okta.com/oauth2/default/v1/keys Micronaut JWT Security
micronaut.security.enabled=true micronaut.security.token.jwt.enabled=true micronaut.security.token.jwt.signatures.jwks.okta.url= https://dev-133337.okta.com/oauth2/default/v1/keys Micronaut JWT Security https://micronaut-projects.github.io/micronaut-security/latest/guide/#jwt
Install HTTPie (a better cURL) $ <tool> install httpie https://httpie.org
Test Micronaut with HTTPie https://httpie.org mvn mn:run http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"
Verify Micronaut API with HTTPie
@mraible Get Started with Quarkus mvn io.quarkus:quarkus-maven-plugin:2.3.0.Final:create -DprojectGroupId=com.okta.rest -DprojectArtifactId=quarkus -DclassName="com.okta.rest.quarkus.HelloResource" -Dpath="/hello" -Dextensions="smallrye-jwt,resteasy-reactive"
https://code.quarkus.io
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 @Path("/") @Authenticated @Produces(MediaType.TEXT_PLAIN) public String hello(@Context SecurityContext context) { Principal userPrincipal = context.getUserPrincipal(); return "Hello, " + userPrincipal.getName() + "!"; } }
mp.jwt.verify.publickey.location= https://dev-133337.okta.com/ oauth2/default/v1/keys mp.jwt.verify.issuer=https:// dev-133337.okta.com/oauth2/ default MicroProfile JWT Security https://www.eclipse.org/community/eclipse_newsletter/2017/september/article2.php
mp.jwt.verify.publickey.location= https://dev-133337.okta.com/ oauth2/default/v1/keys mp.jwt.verify.issuer=https:// dev-133337.okta.com/oauth2/ default MicroProfile JWT Security https://www.eclipse.org/community/eclipse_newsletter/2017/september/article2.php
Test Quarkus with HTTPie https://httpie.org mvn quarkus:dev http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"
Verify Quarkus API with HTTPie
@mraible Get Started with Spring Boot http https://start.spring.io/starter.zip dependencies==web,oauth2-resource-server,native packageName==com.okta.rest name==spring-boot type==maven-project baseDir==spring-boot | tar -xzvf -
https://start.spring.io
package com.okta.rest.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.security.Principal; @RestController public class HelloController { @GetMapping("/hello") public String hello(Principal principal) { return "Hello, " + principal.getName() + "!"; } }
Spring Security OAuth 2.0 Resource Server https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2resourceserver okta.oauth2.issuer=https://dev-133337.okta.com/ oauth2/default
Test Spring Boot with HTTPie https://httpie.org mvn spring-boot:run http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"
Verify Spring Boot API with HTTPie
@mraible Startup Performance Milliseconds 0 750 1500 2250 3000 Micronaut Quarkus Spring Boot 2,262 632 599 1,297 1,582 479 Dev Startup (mvn) Packaged Startup (java -jar) https://developer.okta.com/blog/2020/01/09/java-rest-api-showdown
@mraible Build GraphQL APIs with Java Why GraphQL? Does your favorite framework support GraphQL? Micronaut https://micronaut-projects.github.io/micronaut-graphql/latest/guide Quarkus https://quarkus.io/guides/smallrye-graphql Spring Boot https://spring.io/projects/spring-graphql
@mraible Secure your API with OAuth 2.0 https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1
@mraible Secure your API with OAuth 2.1 https://oauth.net/2.1 PKCE is required for all clients using the authorization code flow Redirect URIs must be compared using exact string matching The Implicit grant is omitted from this specification The Resource Owner Password Credentials grant is omitted from this specification Bearer token usage omits the use of bearer tokens in the query string of URIs Refresh tokens for public clients must either be sender-constrained or one-time use
@mraible Authenticate with OpenID Connect (OIDC) What is OpenID Connect? Does your favorite framework support OIDC authentication? Micronaut https://guides.micronaut.io/latest/micronaut-oauth2-okta.html Quarkus https://quarkus.io/guides/security-openid-connect-web-authentication Spring Boot https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login
What about testing?
@mraible Build with Docker Create a Dockerfile 
 FROM openjdk:17-alpine ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
@mraible Build with Docker Build your image docker build -t <tag-name> . Run your image docker run -it -p8080:8080 <tag-name>
@mraible Build with Docker: Jib Get Jibby with it! mvn verify jib:build Or build directly to your Docker daemon mvn verify jib:dockerBuild https://github.com/GoogleContainerTools/jib
@mraible Build with Docker Micronaut uses Jib, but you must configure plugins Quarkus generates three Docker-related files Dockerfile.jvm Dockerfile.legacy-jar Dockerfile.native Dockerfile.native-distroless Quarkus + Jib mvn quarkus:add-extension -Dextensions="container-image-jib"
@mraible Build with Docker Spring Boot 2.3+ has built-in support mvn spring-boot:build-image Uses layered JARs for for faster builds dependencies snapshot-dependencies resources application https://spring.io/blog/2020/01/27/creating-docker-images-with-spring-boot-2-3-0-m1
@mraible Use Micronaut CLI mn create-app ... mvn package -Dpackaging=native-image gradle nativeImage gradle dockerBuildNative Go Native with GraalVM and Micronaut https://docs.micronaut.io/latest/guide/#graal
@mraible Go Native with GraalVM and Quarkus Create an executable without GraalVM installed mvn package -Pnative -Dquarkus.native.container-build=true Then, build the image docker build -f src/main/docker/Dockerfile.native -t <tag-name> . And run it docker run -it -p8080:8080 <tag-name> https://quarkus.io/guides/building-native-image
@mraible Use start.spring.io to get plugins and profiles <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <classifier>${repackage.classifier}</classifier> <image> <builder>paketobuildpacks/builder:tiny</builder> <env> <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE> </env> </image> </configuration> </plugin> <plugin> <groupId>org.springframework.experimental</groupId> <artifactId>spring-aot-maven-plugin</artifactId> <version>${spring-native.version}</version> <executions> Go Native with GraalVM and Spring Boot
@mraible Go Native with GraalVM and Spring Boot Add milestone repositories to your pom.xml <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </pluginRepository> </pluginRepositories>
@mraible Go Native with GraalVM and Spring Boot Add Spring Native dependency <dependency> <groupId>org.springframework.experimental</groupId> <artifactId>spring-native</artifactId> <version>0.10.4</version> </dependency> Build the native application mvn spring-boot:build-image
@mraible How we fixed the Okta Spring Boot Starter https://youtu.be/8vY-9tXlCW4
@mraible Native Startup Performance Milliseconds 0 15 30 45 60 October 7, 2021 46.8 19 24 Micronaut Quarkus Spring Boot
@mraible Native Memory Used (MB) Milliseconds 0 25 50 75 100 October 7, 2021 82 34 62 Micronaut Quarkus Spring Boot
@mraible Tests Run on a 2019 MacBook Pro
@mraible Demo Time! https://github.com/oktadev/native-java-examples
Community
@mraible Stack Overflow Tags 0 32500 65000 97500 130000 October 7, 2021 111,521 2,011 1,205 Micronaut Quarkus Spring Boot
@mraible GitHub Stars 0 18750 37500 56250 75000 October 7, 2021 57,600 8,600 5,100 Micronaut Quarkus Spring Boot
star-history.t9t.io/#micronaut-projects/micronaut-core&quarkusio/quarkus&spring-projects/spring-boot GitHub Star Growth
@mraible Jobs on Indeed (US) 0 3250 6500 9750 13000 October 7, 2021 10,532 178 136 Micronaut Quarkus Spring Boot
@mraible Twitter Followers 0 25000 50000 75000 100000 October 7, 2021 78,500 12,600 10,600 Micronaut Quarkus Spring Boot
Hot Web Frameworks https://hotframeworks.com
@mraible JHipster Support 🤓 Micronaut Blueprint - github.com/jhipster/generator-jhipster-micronaut - v1.0.2, 18 releases, 16 contributors, 382 commits // TODO: Micronaut 3, Reactive, Microservices, GraalVM native images Quarkus Blueprint - github.com/jhipster/generator-jhipster-quarkus - v2.0.0-beta.1, 6 releases, 16 contributors, 550 commits // TODO: Quarkus 2.3, Dev Services, Reactive, Microservices
https://developer.okta.com/blog/2021/01/20/reactive-java-microservices
https://developer.okta.com/blog/2020/08/17/micronaut-jhipster-heroku
https://developer.okta.com/blog/2021/03/08/jhipster-quarkus-oidc
Recommendations from Twitter https://twitter.com/mraible/status/1445753175978360832
@mraible Action!
developer.okta.com/blog/tags/java @oktadev
git clone https://github.com/oktadeveloper/okta-spring-webflux-react- example.git https://github.com/oktadev/native-java-examples Use the Source, Luke!
Thanks! Keep in Touch raibledesigns.com @mraible Presentations speakerdeck.com/mraible Code github.com/oktadev developer.okta.com
developer.okta.com

Java REST API Framework Comparison - UberConf 2021