$30 off During Our Annual Pro Sale. View Details »

Comparing Native Java REST API Frameworks - Seattle JUG 2022

Comparing Native Java REST API Frameworks - Seattle JUG 2022

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.

Related blog post: https://developer.okta.com/blog/2021/06/18/native-java-framework-comparison
Helidon companion post: https://developer.okta.com/blog/2022/01/06/native-java-helidon
GitHub repo: https://github.com/oktadev/native-java-examples

Matt Raible
PRO

September 13, 2022
Tweet

More Decks by Matt Raible

Other Decks in Programming

Transcript

  1. Matt Raible | @mraible
    September 13, 2022
    Native Java REST API Comparison


    Micronaut, Quarkus,


    Spring Boot, and Helidon
    Photo by Eric Zhang


    https://unsplash.com/photos/aJmmebD4NpE

    View 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 Slide

  3. View Slide

  4. View Slide

  5. View Slide

  6. developer.okta.com

    View Slide

  7. developer.auth0.com

    View Slide

  8. @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 Slide

  9. @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 Slide

  10. @mraible
    Download the Oracle builds of OpenJDK


    https://jdk.java.net/18


    Or Eclipse builds from Adoptium


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

    View Slide

  11. @mraible
    Get Started with Java 18
    Better yet, use SDKMAN!


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

    sdk install java 18-open

    View Slide

  12. Java Releases and Features

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. @mraible
    sdk install micronaut


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


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

    View Slide

  18. https://micronaut.io/launch

    View Slide

  19. 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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

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


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


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


    View Slide

  24. Verify Micronaut API with HTTPie

    View Slide

  25. @mraible
    Get Started with Quarkus
    mvn io.quarkus:quarkus-maven-plugin:2.12.2.Final:create \


    -DprojectGroupId=com.okta.rest \


    -DprojectArtifactId=quarkus \


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


    -Dpath="/hello" \


    -Dextensions="smallrye-jwt,resteasy-reactive"

    View Slide

  26. https://code.quarkus.io

    View Slide

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


    @Authenticated


    @Produces(MediaType.TEXT_PLAIN)


    public String hello(@Context SecurityContext context) {


    Principal userPrincipal = context.getUserPrincipal();


    return "Hello, " + userPrincipal.getName() + "!";


    }


    }

    View Slide

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

    View Slide

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

    View Slide

  30. View Slide

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


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


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


    View Slide

  32. Verify Quarkus API with HTTPie

    View Slide

  33. @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 Slide

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

    View Slide

  35. 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 Slide

  36. @mraible
    Optimize Tomcat for Spring Native



    org.springframework.boot


    spring-boot-starter-web








    org.apache.tomcat.embed


    tomcat-embed-core








    org.apache.tomcat.embed


    tomcat-embed-websocket














    org.apache.tomcat.experimental


    tomcat-embed-programmatic


    ${tomcat.version}



    View Slide

  37. Spring Security OAuth 2.0 Resource Server
    https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server
    okta.oauth2.issuer=https://dev-133337.okta.com/
    oauth2/default

    View Slide

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


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


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


    View Slide

  39. Verify Spring Boot API with HTTPie

    View Slide

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


    -DarchetypeGroupId=io.helidon.archetypes \


    -DarchetypeArtifactId=helidon-quickstart-mp \


    -DarchetypeVersion=3.0.1 \


    -DgroupId=com.okta.rest \


    -DartifactId=helidon \


    -Dpackage=com.okta.rest

    View Slide

  41. https://helidon.io/starter

    View Slide

  42. The Helidon CLI

    View Slide

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

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

  45. MicroProfile JWT Security
    mp.jwt.verify.issuer=https://dev-133337.okta.com/oauth2/default


    mp.jwt.verify.publickey.location=${mp.jwt.verify.issuer}/v1/keys
    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 Slide

  46. 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 Slide

  47. Verify Helidon API with HTTPie

    View Slide

  48. @mraible
    Startup Performance
    Milliseconds
    0
    300
    600
    900
    1200
    Micronaut Quarkus Spring Boot Helidon
    1,082
    943
    347
    262
    662
    863
    240
    Dev Startup (mvn) Packaged Startup (java -jar)

    View Slide

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

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

    View Slide

  51. @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 Slide

  52. @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/reference/servlet/oauth2/login


    Helidon


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

    View Slide

  53. What about testing?

    View Slide

  54. @mraible
    Build with Docker
    Create a Dockerfile



    FROM openjdk:18-alpine


    ARG JAR_FILE=target/*.jar


    COPY ${JAR_FILE} app.jar


    EXPOSE 8080


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

    View Slide

  55. @mraible
    Build with Docker
    Build your image


    docker build -t .


    Run your image


    docker run -it -p 8080:8080

    View Slide

  56. @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 Slide

  57. @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 Slide

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

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


    Dockerfile


    Dockerfile.jlink


    Dockerfile.native


    Helidon + Jib


    Not available

    View Slide

  60. @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 Slide

  61. @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 Slide

  62. @mraible
    Use start.spring.io to get plugins and profiles





    org.springframework.boot


    spring-boot-maven-plugin





    ${repackage.classifier}





    paketobuildpacks/builder:tiny





    true

















    org.springframework.experimental


    spring-aot-maven-plugin


    ${spring-native.version}



    Go Native with GraalVM and Spring Boot

    View Slide

  63. @mraible
    Go Native with GraalVM and Spring Boot
    Add milestone repositories to your pom.xml








    spring-milestones


    Spring Milestones


    https://repo.spring.io/milestone














    spring-milestones


    Spring Milestones


    https://repo.spring.io/milestone






    View Slide

  64. @mraible
    Go Native with GraalVM and Spring Boot
    Add Spring Native dependency





    org.springframework.experimental


    spring-native


    0.12.1





    Build the native application


    mvn spring-boot:build-image


    View Slide

  65. @mraible
    How we fixed the Okta Spring Boot Starter
    https://youtu.be/8vY-9tXlCW4

    View Slide

  66. @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 Slide

  67. @mraible
    Native Startup Performance
    Milliseconds
    0
    20
    40
    60
    80
    100
    September 13, 2022
    40
    36.8
    19
    18.2
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  68. @mraible
    Native Memory Used (MB)
    Megabytes
    0
    30
    60
    90
    120
    150
    September 13, 2022
    132
    76
    51
    69
    Micronaut Quarkus Spring Boot Helidon

    View Slide

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

    View Slide

  70. @mraible
    Demo Time!
    https://github.com/oktadev/native-java-examples

    View Slide

  71. Community

    View Slide

  72. @mraible
    Stack Overflow Tags
    0
    35,000
    70,000
    105,000
    140,000
    September 9, 2022
    68
    127,585
    3,042
    1,395
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  73. @mraible
    GitHub Stars
    0
    18,750
    37,500
    56,250
    75,000
    September 9, 2022
    2,700
    63,100
    10,700
    5,500
    Micronaut Quarkus Spring Boot Helidon

    View Slide

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

    View Slide

  75. @mraible
    Jobs on Indeed (US)
    0
    10,000
    20,000
    September 9, 2022
    8
    11,675
    121
    117
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  76. @mraible
    Twitter Followers
    0
    25,000
    50,000
    75,000
    100,000
    September 9, 2022
    3,826
    92,000
    15,800
    12,100
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  77. @mraible
    JHipster Support 🤓
    Micronaut Blueprint - github.com/jhipster/generator-jhipster-micronaut


    - v1.0.2, 18 releases, 17 contributors, 385 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.9, Dev Services, Reactive, Microservices

    View Slide

  78. https://developer.okta.com/blog/2021/01/20/reactive-java-microservices

    View Slide

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

    View Slide

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

    View Slide

  81. Intel vs M1 Max
    https://twitter.com/mraible/status/1509371877348843525

    View Slide

  82. @mraible
    🏆 Quarkus provides the best DevEx and memory usage


    🚀 Micronaut is the easiest to use and starts the fastest


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


    🔮 Helidon still has some catching up to do but has made great progress


    ⚡ Spring 6 could be a game changer
    My Thoughts

    View Slide

  83. @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 Slide

  84. developer.okta.com/blog/tags/java


    @oktadev

    View Slide

  85. git clone https://github.com/oktadeveloper/okta-spring-webflux-react-
    example.git
    https://github.com/oktadev/native-java-examples
    Use the Source, Luke!

    View Slide

  86. Thanks!


    Keep in Touch


    raibledesigns.com


    @mraible


    Presentations


    speakerdeck.com/mraible


    Code


    github.com/oktadev
    developer.okta.com

    View Slide

  87. developer.okta.com

    View Slide