KEMBAR78
Java REST API Framework Comparison - UberConf 2021 | PDF
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