Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Comparing Native Java REST API Frameworks - JCON 2023

Comparing Native Java REST API Frameworks - JCON 2023

Use Spring Boot! No, use Micronaut!! Nooooo, Quarkus is the best!!! What about Helidon?

There are a lot of developers praising the hottest and fastest Java REST frameworks: Micronaut, Quarkus, Spring Boot, and Helidon. In this session, you'll learn how to do the following with each framework:

✅ Build a REST API
✅ Secure your API with OAuth 2.0
✅ Optimize for production with Docker and GraalVM

I'll also share some performance numbers and pretty graphs to compare community metrics.

GitHub repo: https://github.com/oktadev/auth0-java-rest-api-examples
Demo script: @oktadev/auth0-java-rest-api-examples/blob/main/demo.adoc

Matt Raible

June 22, 2023
Tweet

More Decks by Matt Raible

Other Decks in Programming

Transcript

  1. Matt Raible | @mraible
    June 22, 2023
    Native Java REST API Comparison


    Micronaut, Quarkus,


    Spring Boot, and Helidon
    Photo by Leon Seibert


    https://unsplash.com/photos/xj_x5FD9V08

    View full-size slide

  2. @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

    View full-size slide

  3. developer.okta.com

    View full-size slide

  4. developer.auth0.com

    View full-size slide

  5. @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

    View full-size slide

  6. @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

    View full-size slide

  7. @mraible
    Download the Oracle builds of OpenJDK


    https://jdk.java.net/20


    Or Eclipse builds from Adoptium


    https://adoptium.net
    Get Started with Java 20

    View full-size slide

  8. @mraible
    Get Started with Java 20
    Better yet, use SDKMAN!


    curl -s https://get.sdkman.io | bash

    sdk install java 20-open

    View full-size slide

  9. Java Releases and Features

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. @mraible
    sdk install micronaut


    mn create-app com.okta.rest.app \


    -b maven -f security-jwt -f micronaut-aot
    Get Started with Micronaut

    View full-size slide

  16. https://micronaut.io/launch

    View full-size slide

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


    }


    }

    View full-size slide

  18. micronaut.security.token.jwt.enabled=true


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


    Micronaut JWT Security

    View full-size slide

  19. micronaut.security.token.jwt.enabled=true


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

    View full-size slide

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

    View full-size slide

  21. Test Micronaut with HTTPie
    https://httpie.org
    mvn mn:run


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


    http :8080/hello Authorization:"Bearer $TOKEN"


    View full-size slide

  22. Verify Micronaut API with HTTPie

    View full-size slide

  23. @mraible
    Get Started with Quarkus
    sdk install quarkus


    quarkus create app com.okta.rest:quarkus \


    --extension="smallrye-jwt,resteasy"

    View full-size slide

  24. @mraible
    mvn io.quarkus:quarkus-maven-plugin:3.1.2.Final:create \


    -DprojectGroupId=com.okta.rest \


    -DprojectArtifactId=quarkus \


    -DclassName="com.okta.rest.HelloResource" \


    -Dpath="/hello" \


    -Dextensions="smallrye-jwt,resteasy"
    Get Started with Quarkus

    View full-size slide

  25. https://code.quarkus.io

    View full-size slide

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


    }


    }

    View full-size slide

  27. 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

    View full-size slide

  28. 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

    View full-size slide

  29. Test Quarkus with HTTPie
    https://httpie.org
    mvn quarkus:dev


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


    http :8080/hello Authorization:"Bearer $TOKEN"


    View full-size slide

  30. Verify Quarkus API with HTTPie

    View full-size slide

  31. @mraible
    Get Started with Spring Boot
    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 -

    View full-size slide

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

    View full-size slide

  33. @mraible
    Use the Spring Boot CLI
    sdk install springboot


    spring init -d=web,oauth2-resource-server,native \


    --package-name=com.okta.rest spring-boot \


    --build=maven

    View full-size slide

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


    }


    }

    View full-size slide

  35. Spring Security OAuth 2.0 Resource Server
    https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server
    okta.oauth2.issuer=https://dev-1337.us.auth0.com

    View full-size slide

  36. Test Spring Boot with HTTPie
    https://httpie.org
    mvn spring-boot:run


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


    http :8080/hello Authorization:"Bearer $TOKEN"


    View full-size slide

  37. Verify Spring Boot API with HTTPie

    View full-size slide

  38. @mraible
    Get Started with Helidon
    mvn -U archetype:generate -DinteractiveMode=false \


    -DarchetypeGroupId=io.helidon.archetypes \


    -DarchetypeArtifactId=helidon-quickstart-mp \


    -DarchetypeVersion=3.2.1 \


    -DgroupId=com.okta.rest \


    -DartifactId=helidon \


    -Dpackage=com.okta.rest

    View full-size slide

  39. https://helidon.io/starter

    View full-size slide

  40. Use the Helidon CLI
    helidon init --flavor MP \


    --groupid com.okta.rest \


    --artifactid helidon


    --package com.okta.rest

    View full-size slide

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


    }


    }

    View full-size slide

  42. 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);


    }


    }

    View full-size slide

  43. 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



    View full-size slide

  44. 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"


    View full-size slide

  45. Verify Helidon API with HTTPie

    View full-size slide

  46. @mraible
    Startup Performance
    Milliseconds
    0
    400
    800
    1200
    1600
    2000
    Micronaut Quarkus Spring Boot Helidon
    1,010
    910
    413
    409
    824
    722
    1,460
    361
    Dev Startup (gradle or mvn) Packaged Startup (java -jar)

    View full-size slide

  47. @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/v3/#/mp/graphql

    View full-size slide

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

    View full-size slide

  49. @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

    View full-size slide

  50. @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-openid-connect-web-authentication


    Spring Boot


    https://docs.spring.io/spring-security/reference/servlet/oauth2/login


    Helidon


    https://helidon.io/docs/v3/#/mp/security/providers#OIDC-Provider

    View full-size slide

  51. What about testing?

    View full-size slide

  52. @mraible
    Build with Docker
    Create a Dockerfile



    FROM openjdk:20-alpine


    ARG JAR_FILE=target/*.jar


    COPY ${JAR_FILE} app.jar


    EXPOSE 8080


    ENTRYPOINT ["java","-jar","/app.jar"]

    View full-size slide

  53. @mraible
    Build with Docker
    Build your image


    docker build -t .


    Run your image


    docker run -it -p 8080:8080

    View full-size slide

  54. @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

    View full-size slide

  55. @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"


    View full-size slide

  56. @mraible
    Build with Docker
    Spring Boot 2.3+ has built-in support


    mvn spring-boot:build-image


    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

    View full-size slide

  57. @mraible
    Build with Docker
    Helidon generates three Docker-related files


    Dockerfile


    Dockerfile.jlink


    Dockerfile.native


    Helidon + Jib


    Not available

    View full-size slide

  58. @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

    View full-size slide

  59. @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 \


    .


    And run it


    docker run -it -p 8080:8080
    https://quarkus.io/guides/building-native-image

    View full-size slide

  60. @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.20'


    }


    View full-size slide

  61. @mraible
    Go Native with GraalVM and Spring Boot
    Build the native application


    mvn native:compile -Pnative


    gradle native:compile -Pnative


    Build an image and Docker container


    mvn spring-boot:build-image -Pnative


    gradle bootBuildImage

    View full-size slide

  62. @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

    View full-size slide

  63. @mraible
    Native Startup Performance (GraalVM 22.3)
    Milliseconds
    0
    12
    24
    36
    48
    60
    June 22, 2023
    33.2
    47.6
    39.8
    25.8
    23.8
    33.4
    Micronaut Micronaut (optimized) Quarkus Spring Boot
    Helidon Helidon (optimized)

    View full-size slide

  64. @mraible
    Native Memory Used (MB)
    Megabytes
    0
    30
    60
    90
    120
    150
    June 22, 2023
    111
    124
    75
    48
    47
    54
    Micronaut Micronaut (optimized) Quarkus Spring Boot
    Helidon Helidon (optimized)

    View full-size slide

  65. @mraible
    Tests Run on a 2021 MacBook Pro M1 Max

    View full-size slide

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

    View full-size slide

  67. @mraible
    Stack Overflow Tags
    0
    45,000
    90,000
    135,000
    180,000
    June 21, 2023
    123
    140,593
    3,779
    1,628
    Micronaut Quarkus Spring Boot Helidon

    View full-size slide

  68. @mraible
    GitHub Stars
    0
    18,750
    37,500
    56,250
    75,000
    June 21, 2023
    2,800
    63,700
    10,900
    5,500
    Micronaut Quarkus Spring Boot Helidon

    View full-size slide

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

    View full-size slide

  70. @mraible
    Jobs on Indeed (DE)
    0
    2,500
    5,000
    June 21, 2023
    3
    2,812
    342
    80
    Micronaut Quarkus Spring Boot Helidon

    View full-size slide

  71. @mraible
    Twitter Followers
    0
    30,000
    60,000
    90,000
    120,000
    June 21, 2023
    4,024
    101,600
    17,800
    13,100
    Micronaut Quarkus Spring Boot Helidon

    View full-size slide

  72. @mraible
    JHipster Support 🤓
    Spring Boot 3 - github.com/jhipster/generator-jhipster/issues/22488


    Micronaut Blueprint - github.com/jhipster/generator-jhipster-micronaut


    - v1.0.2, 18 releases, 18 contributors, 393 commits


    // TODO: Micronaut 3, Reactive, Microservices, GraalVM native images


    Quarkus Blueprint - github.com/jhipster/generator-jhipster-quarkus


    - v2.0.0, 7 releases, 18 contributors, 649 commits


    // TODO: Quarkus 3, Dev Services, Reactive, Microservices

    View full-size slide

  73. https://auth0.com/blog/full-stack-java-with-react-spring-boot-and-jhipster

    View full-size slide

  74. https://developer.okta.com/blog/2020/08/17/micronaut-jhipster-heroku

    View full-size slide

  75. https://developer.okta.com/blog/2021/03/08/jhipster-quarkus-oidc

    View full-size slide

  76. @mraible
    🏆 Quarkus provides the best DevEx, startup time, and memory usage


    🚀 Micronaut is the easiest to use; startup time increased recently


    🌱 Spring Boot has the strongest community, ecosystem, and growth


    🔮 Helidon still has some catching up to do


    ⚡ Spring Boot 3 not as fast as expected
    My Thoughts

    View full-size slide

  77. @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

    View full-size slide

  78. developer.auth0.com


    @oktadev

    View full-size slide

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

    View full-size slide

  80. 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!

    View full-size slide

  81. Thanks!


    Keep in Touch


    raibledesigns.com


    @mraible


    Presentations


    speakerdeck.com/mraible


    Code


    github.com/oktadev
    developer.okta.com
    developer.auth0.com

    View full-size slide

  82. developer.okta.com

    View full-size slide