Slide 1

Slide 1 text

Matt Raible | @mraible January 16, 2024 Native Java REST API Comparison Micronaut, Quarkus, Spring Boot, and Helidon Photo by Christopher Alvarenga https://unsplash.com/photos/concrete-buildings-during-golden-hour-K5iyVtWYXqo

Slide 2

Slide 2 text

@mraible Who is Matt Raible? Father, Husband, Skier, Mountain Biker, Whitewater Rafter Bus Lover Web Developer and Java Champion Developer Advocate Architect Blogger on raibledesigns.com and auth0.com/blog @mraible

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

developer.okta.com

Slide 7

Slide 7 text

developer.auth0.com

Slide 8

Slide 8 text

@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

Slide 9

Slide 9 text

@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

Slide 10

Slide 10 text

@mraible Download the Oracle builds of OpenJDK https://jdk.java.net/21 Or Eclipse builds from Adoptium https://adoptium.net Get Started with Java 21

Slide 11

Slide 11 text

@mraible Get Started with Java 21 Better yet, use SDKMAN! curl -s https://get.sdkman.io | bash sdk install java 21-open

Slide 12

Slide 12 text

Java Releases and Features

Slide 13

Slide 13 text

https://developer.okta.com/blog/2020/01/09/java-rest-api-showdown Build REST APIs with Java

Slide 14

Slide 14 text

https://developer.okta.com/blog/2021/06/18/native-java-framework-comparison Build Native Java REST APIs

Slide 15

Slide 15 text

https://developer.okta.com/blog/2022/01/06/native-java-helidon Build REST APIs and Native Apps with Helidon

Slide 16

Slide 16 text

Serverless 💵 💸 https://unsplash.com/photos/glRqyWJgUeY

Slide 17

Slide 17 text

Use Cases for Native Images https://twitter.com/therealdanvega/status/1666098085616046081

Slide 18

Slide 18 text

@mraible sdk install micronaut mn create-app com.okta.rest.app \ -f security-jwt -f micronaut-aot Get Started with Micronaut

Slide 19

Slide 19 text

https://micronaut.io/launch

Slide 20

Slide 20 text

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() + "!"; } }

Slide 21

Slide 21 text

micronaut.security.token.jwt.signatures.jwks.okta.url= https://dev-1337.us.auth0.com/.well-known/jwks.json Micronaut JWT Security

Slide 22

Slide 22 text

micronaut.security.token.jwt.signatures.jwks.okta.url= https://dev-1337.us.auth0.com/.well-known/jwks.json Micronaut JWT Security https://micronaut-projects.github.io/micronaut-security/latest/guide/#jwt

Slide 23

Slide 23 text

Install HTTPie (a better cURL) $ install httpie https://httpie.org

Slide 24

Slide 24 text

Test Micronaut with HTTPie https://httpie.org gradle run http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"

Slide 25

Slide 25 text

Verify Micronaut API with HTTPie

Slide 26

Slide 26 text

@mraible Get Started with Quarkus sdk install quarkus quarkus create app com.okta.rest:quarkus \ --extension="smallrye-jwt,resteasy-reactive" --gradle

Slide 27

Slide 27 text

@mraible mvn io.quarkus:quarkus-maven-plugin:3.6.4:create \ -DprojectGroupId=com.okta.rest \ -DprojectArtifactId=quarkus \ -DclassName="com.okta.rest.HelloResource" \ -Dpath="/hello" \ -Dextensions="smallrye-jwt,resteasy-reactive" Get Started with Quarkus

Slide 28

Slide 28 text

https://code.quarkus.io

Slide 29

Slide 29 text

package com.okta.rest; import io.quarkus.security.Authenticated; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.MediaType; import jakarta.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() + "!"; } }

Slide 30

Slide 30 text

mp.jwt.verify.issuer=https:// dev-1337.us.auth0.com/ mp.jwt.verify.publickey.location= ${mp.jwt.verify.issuer}.well- known/jwks.json MicroProfile JWT Security https://www.eclipse.org/community/eclipse_newsletter/2017/september/article2.php

Slide 31

Slide 31 text

mp.jwt.verify.issuer=https:// dev-1337.us.auth0.com/ mp.jwt.verify.publickey.location= ${mp.jwt.verify.issuer}.well- known/jwks.json MicroProfile JWT Security https://www.eclipse.org/community/eclipse_newsletter/2017/september/article2.php

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Test Quarkus with HTTPie https://httpie.org gradle --console=plain quarkusDev http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"

Slide 34

Slide 34 text

Verify Quarkus API with HTTPie

Slide 35

Slide 35 text

@mraible Get Started with Spring Boot https start.spring.io/starter.tgz \ dependencies==web,oauth2-resource-server,native \ packageName==com.okta.rest \ name==spring-boot \ bootVersion==3.2.0 \ baseDir==spring-boot | tar -xzvf -

Slide 36

Slide 36 text

https://start.spring.io https://start.spring.io

Slide 37

Slide 37 text

@mraible Use the Spring Boot CLI sdk install springboot spring init -d=web,oauth2-resource-server,native \ --group-id=com.okta.rest -b=3.2.0 \ --package-name=com.okta.rest spring-boot

Slide 38

Slide 38 text

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() + "!"; } }

Slide 39

Slide 39 text

The Okta Spring Boot Starter https://github.com/okta/okta-spring-boot okta.oauth2.issuer=https://dev-1337.us.auth0.com

Slide 40

Slide 40 text

Test Spring Boot with HTTPie https://httpie.org gradle bootRun http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"

Slide 41

Slide 41 text

Verify Spring Boot API with HTTPie

Slide 42

Slide 42 text

Verify Spring Boot API with HTTPie

Slide 43

Slide 43 text

@mraible Get Started with Helidon mvn -U archetype:generate -DinteractiveMode=false \ -DarchetypeGroupId=io.helidon.archetypes \ -DarchetypeArtifactId=helidon-quickstart-mp \ -DarchetypeVersion=4.0.2 \ -DgroupId=com.okta.rest \ -DartifactId=helidon \ -Dpackage=com.okta.rest

Slide 44

Slide 44 text

https://helidon.io/starter

Slide 45

Slide 45 text

Use the Helidon CLI sdk install helidon helidon init --flavor MP \ --groupid com.okta.rest \ --artifactid helidon \ --package com.okta.rest --batch

Slide 46

Slide 46 text

package com.okta.rest.controller; import io.helidon.security.Principal; import io.helidon.security.annotations.Authenticated; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Context; @Path("/hello") public class HelloResource { @Authenticated @GET public String hello(@Context SecurityContext context) { return "Hello, " + context.userName() + "!"; } }

Slide 47

Slide 47 text

package com.okta.rest; import com.okta.rest.controller.HelloResource; import org.eclipse.microprofile.auth.LoginConfig; import jakarta.enterprise.context.ApplicationScoped; import jakarta.ws.rs.core.Application; import java.util.Set; @LoginConfig(authMethod = "MP-JWT") @ApplicationScoped public class HelloApplication extends Application { @Override public Set> getClasses() { return Set.of(HelloResource.class); } }

Slide 48

Slide 48 text

MicroProfile JWT Security mp.jwt.verify.issuer=https://dev-1337.us.auth0.com/ mp.jwt.verify.publickey.location=${mp.jwt.verify.issuer}.well- known/jwks.json https://download.eclipse.org/microprofile/microprofile-jwt-auth-2.0/microprofile-jwt-auth-spec-2.0.html io.helidon.microprofile.jwt helidon-microprofile-jwt-auth

Slide 49

Slide 49 text

Test Helidon with HTTPie https://httpie.org mvn package && java -jar target/helidon.jar http :8080/hello TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"

Slide 50

Slide 50 text

Verify Helidon API with HTTPie

Slide 51

Slide 51 text

@mraible Startup Performance Milliseconds 0 500 1000 1500 2000 Micronaut Quarkus Spring Boot Helidon 1,097 953 418 389 789 728 1,346 369 Dev Startup (gradle or mvn) Packaged Startup (java -jar)

Slide 52

Slide 52 text

@mraible What about GraphQL APIs? 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 Helidon https://helidon.io/docs/v4/mp/graphql

Slide 53

Slide 53 text

@mraible Secure your API with OAuth 2.1 https://aaronparecki.com/2019/12/12/21/its-time-for-oauth-2-dot-1

Slide 54

Slide 54 text

@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

Slide 55

Slide 55 text

@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-auth0.html Quarkus https://quarkus.io/guides/security-oidc-auth0-tutorial Spring Boot https://docs.spring.io/spring-security/reference/servlet/oauth2/login Helidon https://helidon.io/docs/v4/mp/security/providers#OIDC-Provider

Slide 56

Slide 56 text

What about testing?

Slide 57

Slide 57 text

@mraible Build with Docker Create a Dockerfile FROM openjdk:21-alpine ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]

Slide 58

Slide 58 text

@mraible Build with Docker Build your image docker build -t . Run your image docker run -it -p 8080:8080

Slide 59

Slide 59 text

@mraible Build with Docker: Jib Get Jibby with it! mvn verify jib:build gradle jib Or build directly to your Docker daemon mvn verify jib:dockerBuild gradle jibDockerbuild https://github.com/GoogleContainerTools/jib

Slide 60

Slide 60 text

@mraible Build with Docker Micronaut uses Jib, but you must configure plugins Quarkus generates four Docker-related files Dockerfile.jvm Dockerfile.legacy-jar Dockerfile.native Dockerfile.native-micro Quarkus + Jib mvn quarkus:add-extension -Dextensions="container-image-jib" gradle addExtension --extensions="container-image-jib"

Slide 61

Slide 61 text

@mraible Build with Docker Spring Boot 2.3+ has built-in support mvn -Pnative spring-boot:build-image gradle bootBuildImage Uses layered JARs 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

Slide 62

Slide 62 text

@mraible Build with Docker Helidon generates three Docker-related files Dockerfile Dockerfile.jlink Dockerfile.native Helidon + Jib mvn compile jib:dockerBuild

Slide 63

Slide 63 text

@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

Slide 64

Slide 64 text

@mraible Go Native with GraalVM and Quarkus Create an executable without GraalVM installed mvn package -Dnative -Dquarkus.native.container-build=true gradle build -Dquarkus.package.type=native \ -Dquarkus.native.container-build=true Then, build the image docker build -f src/main/docker/Dockerfile.native -t \ . And run it docker run -it -p 8080:8080 https://quarkus.io/guides/building-native-image

Slide 65

Slide 65 text

@mraible Use start.spring.io to get plugins Go Native with GraalVM and Spring Boot org.graalvm.buildtools native-maven-plugin org.springframework.boot spring-boot-maven-plugin plugins { ... id 'org.graalvm.buildtools.native' version '0.9.28' }

Slide 66

Slide 66 text

@mraible Go Native with GraalVM and Spring Boot Build the native application mvn native:compile -Pnative gradle nativeCompile Build an image and Docker container mvn spring-boot:build-image -Pnative gradle bootBuildImage

Slide 67

Slide 67 text

@mraible Build the image docker build -f Dockerfile.native -t . And run it docker run --rm -p 8080:8080 Go Native with GraalVM and Helidon

Slide 68

Slide 68 text

@mraible Native Startup Performance (M1; time from console) Milliseconds 0 12 24 36 48 60 January 9, 2024 35.8 42.6 43.2 21.8 15.6 16.2 Micronaut 4.2.3 Micronaut (optimized) Quarkus 3.6.4 Spring Boot 3.2.0 Helidon 4.0.2 Helidon (optimized)

Slide 69

Slide 69 text

@mraible Native Startup Performance (M1; scripted) Milliseconds 0 25 50 75 100 January 9, 2024 53.8 66.6 71.4 48.2 51.2 49.2 Micronaut 4.2.3 Micronaut (optimized) Quarkus 3.6.4 Spring Boot 3.2.0 Helidon 4.0.2 Helidon (optimized)

Slide 70

Slide 70 text

@mraible Tests Run on a 2021 MacBook Pro M1 Max

Slide 71

Slide 71 text

@mraible t2.small: 1 vCPUs and 2 GiB RAM - Fails to build any projects t2.medium: 2 vCPUs and 4 GiB RAM - Quarkus and Spring Boot fail to build; Helidon took too long t2.large: 2 vCPUs and 8 GiB RAM 🌟 Building GraalVM images on AWS

Slide 72

Slide 72 text

Build Docker Images with GitHub Actions https://github.com/oktadev/auth0-java-rest-api-examples/blob/main/.github/workflows/docker.yml steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup GraalVM uses: graalvm/setup-graalvm@v1 with: java-version: '21' distribution: 'graalvm' github-token: $ {{ secrets.GITHUB_TOKEN }} - run: | echo "GRAALVM_HOME: $GRAALVM_HOME" echo "JAVA_HOME: $JAVA_HOME" java -- version - name: Build Micronaut project run: | cd micronaut ./gradlew dockerBuildNative docker tag app:latest mraible/micronaut:latest shell: bash

Slide 73

Slide 73 text

@mraible Docker Startup Performance (AWS EC2 t2.micro) Milliseconds 0 40 80 120 160 200 January 10, 2024 131.2 137.8 38.4 53.8 Micronaut 4.2.3 Quarkus 3.6.4 Spring Boot 3.2.0 Helidon 4.0.2

Slide 74

Slide 74 text

@mraible Native Memory Used after 10 requests (M1) Megabytes 0 30 60 90 120 150 January 9, 2024 73 93 87 52 67 66 Micronaut Micronaut (optimized) Quarkus Spring Boot Helidon Helidon (optimized)

Slide 75

Slide 75 text

@mraible Docker Memory Used after 10 requests (EC2 t2.micro) Megabytes 0 20 40 60 80 100 January 10, 2024 51 47 14 19 Micronaut Quarkus Spring Boot Helidon

Slide 76

Slide 76 text

@mraible Demo Time! https://github.com/oktadev/auth0-java-rest-api-examples

Slide 77

Slide 77 text

Community

Slide 78

Slide 78 text

@mraible Stack Overflow Tags 0 45,000 90,000 135,000 180,000 January 10, 2024 150 146,344 4,272 1,743 Micronaut Quarkus Spring Boot Helidon

Slide 79

Slide 79 text

@mraible GitHub Stars 0 20,000 40,000 60,000 80,000 January 10, 2024 3,300 71,200 12,700 5,900 Micronaut Quarkus Spring Boot Helidon

Slide 80

Slide 80 text

https://star-history.t9t.io/#micronaut-projects/micronaut-core&quarkusio/quarkus&spring-projects/spring-boot&oracle/helidon GitHub Star Growth

Slide 81

Slide 81 text

@mraible Jobs on Indeed (US) 0 2,500 5,000 January 10, 2024 28 3,477 48 52 Micronaut Quarkus Spring Boot Helidon

Slide 82

Slide 82 text

@mraible Twitter Followers 0 30,000 60,000 90,000 120,000 January 10, 2024 4,746 104,700 18,700 13,300 Micronaut Quarkus Spring Boot Helidon

Slide 83

Slide 83 text

@mraible JHipster Support 🤓 Spring Boot 3 - JHipster 8 is now available! Micronaut blueprint - github.com/jhipster/generator-jhipster-micronaut - v2.0.0 for Micronaut 3, 19 releases, 20 contributors, 495 commits - v3.0.0 with Micronaut 4 with JHipster 8 is next! Quarkus blueprint - github.com/jhipster/generator-jhipster-quarkus - v2.0.0 for Quarkus 2, 7 releases, 18 contributors, 653 commits - v3.0.0 with Quarkus 3 is on the horizon!

Slide 84

Slide 84 text

@mraible What I found this time 🐳 Had to forcibly remove Docker containers on EC2 to get the latest 🚀 The optimized Micronaut app starts slower than the non-optimized app 🌱 Spring Boot 3.2.1 doesn't work with GraalVM when using web + security 🔮 Helidon needs -H:+AddAllCharsets added to properties 🤥 The frameworks are filthy liars when it comes to printed startup times

Slide 85

Slide 85 text

@mraible 🏆 Quarkus provides the best developer joy and memory usage 🚀 Micronaut is consistently competitive with Quarkus 🌱 Spring Boot has the strongest community, ecosystem, and growth 🔮 Helidon is competitive with Spring Boot but not very popular My Thoughts

Slide 86

Slide 86 text

@mraible Action! New to Java? Try Spring Boot Know Spring? Trial migration paths Testing is important, invest early and often Design your apps with security in mind Use OpenID Connect and OAuth 2.1 https://unsplash.com/photos/JsTmUnHdVYQ

Slide 87

Slide 87 text

developer.auth0.com developer.okta.com @oktadev

Slide 88

Slide 88 text

Make login our problem. Not yours. How we can help: Authorization Authentication Security Try Auth0 for free! Up to 7,500 monthly active users. Unlimited user logins. Includes passkeys support. No credit card required. Special Plans for Startups & Nonprofits

Slide 89

Slide 89 text

Subscribe to our Zero Index newsletter! a0.to/nl-signup/java

Slide 90

Slide 90 text

git clone https://github.com/oktadeveloper/okta-spring-web fl ux-react-example.git https://github.com/oktadev/auth0-java-rest-api-examples Use the Source, Luke!

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

Thanks! Keep in Touch raibledesigns.com @mraible Presentations speakerdeck.com/mraible Code github.com/oktadev developer.okta.com developer.auth0.com