Matt Raible | @mraible
September 30, 2020
Java REST API Comparison
Micronaut, Quarkus, and
Spring Boot
Photo by Matt Duncan on https://unsplash.com/photos/IUY_3DvM__w
Matt Raible
Developer Advocate
Okta
@mraible
I ❤ Java AND JavaScript! 🤓
https://jconf.dev
@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/15
Or from AdoptOpenJDK
https://adoptopenjdk.net
Get Started with Java 15
@mraible
Get Started with Java 15
Better yet, use SDKMAN!
curl -s https://get.sdkman.io | bash
sdk install java 15.0.0.hs-adpt
What’s New in Java 15
https://blogs.oracle.com/java-platform-group/the-arrival-of-java-15
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:1.8.1.Final:create 
-DprojectGroupId=com.okta.rest 
-DprojectArtifactId=quarkus 
-DclassName="com.okta.rest.quarkus.HelloResource" 
-Dpath="/hello" 
-Dextensions="jwt"
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 compile 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,okta 
packageName==com.okta.rest 
name=spring-boot 
type=maven-project 
-o spring-boot.zip
https://start.spring.io
package com.okta.rest.controller;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
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(@AuthenticationPrincipal Principal principal) {
return "Hello, " + principal.getName() + "!";
}
}
Spring Security OAuth 2.0 Resource Server
https://docs.spring.io/spring-security/site/docs/5.4.0/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 PerformanceMilliseconds
0
525
1050
1575
2100
Micronaut Quarkus Spring Boot
1,878
658596
1,014
1,132
474
Dev Startup (mvn) Packaged Startup (java -jar)
@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/microprofile-graphql
Spring Boot
https://github.com/leangen/graphql-spqr-spring-boot-starter
@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/micronaut-oauth2-okta/guide
Quarkus
https://quarkus.io/guides/security-openid-connect-web-authentication
Spring Boot
https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2login
@mraible
What about Testing?
@mraible
Build with Docker
Create a Dockerfile
FROM openjdk:15-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 -i --rm -p 8080: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 generates a Dockerfile
Quarkus generates three Docker-related files
Dockerfile.fast-jar
Dockerfile.jvm
Dockerfile.native
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 ... -f graalvm
mn feature-diff --features=graalvm
mvn package
./docker-build.sh
Go Native with GraalVM and Micronaut
https://docs.micronaut.io/latest/guide/#graal
@mraible
Go Native with GraalVM and Quarkus
It’s built-in to Quarkus!
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 -i --rm -p 8080:8080 <tag-name>
https://quarkus.io/guides/building-native-image
@mraible
Go Native with GraalVM and Spring Boot
Upgrade to Spring 2.4.0-M2
<version>2.4.0-M2</version>
Update configuration to avoid proxies
https://tanzu.vmware.com/content/slides/the-path-towards-spring-boot-native-applications-2
@SpringBootApplication(proxyBeanMethods = false)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@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
Configure your Spring Boot Maven Plugin
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<env>
<BP_BOOT_NATIVE_IMAGE>1</BP_BOOT_NATIVE_IMAGE>
<BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
-Dspring.native.remove-yaml-support=true
-Dspring.spel.ignore=true
--enable-https
</BP_BOOT_NATIVE_IMAGE_BUILD_ARGUMENTS>
</env>
</image>
</configuration>
</plugin>
https://www.graalvm.org/reference-manual/native-image/JCASecurityServices/
@mraible
Go Native with GraalVM and Spring Boot
Add Spring GraalVM dependency
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-graalvm-native</artifactId>
<version>0.8.0</version>
</dependency>
Build the native application
mvn spring-boot:build-image
@mraible
Go Native with GraalVM and Spring Boot
Run your native Spring Boot app!
docker run -p 8080:8080 docker.io/library/demo:0.0.1-SNAPSHOT
💣
🐛 https://github.com/okta/okta-spring-boot/issues/192
@mraible
Attempted Workaround for Okta + GraalVM
Use Spring Security’s resource server
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://...
@mraible
Native Startup Performance
Milliseconds
0
12.5
25
37.5
50
September 21, 2020
13
26
Micronaut Quarkus
@mraible
Tests Run on a 2019 MacBook Pro
Community
@mraible
Stack Overflow Tags
0
26250
52500
78750
105000
September 20, 2020
91,030
919732
Micronaut Quarkus Spring Boot
@mraible
GitHub Stars
0
15000
30000
45000
60000
September 20, 2020
50,600
5,9004,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
1050
2100
3150
4200
September 20, 2020
3,745
1012
Micronaut Quarkus Spring Boot
Hot Frameworks https://hotframeworks.com
@mraible
JHipster Support 🤓
Micronaut Blueprint - github.com/jhipster/generator-jhipster-micronaut
- v0.3.8, 15 releases, 12 contributors, 289 commits
// TODO: NoSQL, Reactive, Microservices, Graal VM native images
Quarkus Blueprint - github.com/jhipster/jhipster-quarkus
- v0.1.6, 7 releases, 7 contributors, 80 commits
// TODO: Gradle, OAuth / OIDC, NoSQL, Reactive, Microservices
https://developer.okta.com/blog/2020/08/17/micronaut-jhipster-heroku
@mraible
Action!
developer.okta.com/blog
@oktadev
Curious about Microservice Security?
https://developer.okta.com/blog/2020/03/23/microservice-security-patterns
Thanks!
Keep in Touch
raibledesigns.com
@mraible
Presentations
speakerdeck.com/mraible
Code
github.com/oktadeveloper
developer.okta.com
developer.okta.com

Java REST API Comparison: Micronaut, Quarkus, and Spring Boot - jconf.dev 2020