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

Comparing Native Java REST API Frameworks - Devoxx France 2022

Comparing Native Java REST API Frameworks - Devoxx France 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.

YouTube recording: https://youtu.be/dp3YbdIEyWU
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

April 21, 2022
Tweet

More Decks by Matt Raible

Other Decks in Programming

Transcript

  1. Matt Raible | @mraible
    June 7, 2022
    Native Java REST API Comparison


    Micronaut, Quarkus,


    Spring Boot, and Helidon
    Photo by Trish McGinity


    https://www.mcginityphoto.com/Portfolio/TravelandLeisure/France/i-V4VqtL5

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

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

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

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


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

    sdk install java 18-open

    View Slide

  11. Java Releases and Features

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

  17. https://micronaut.io/launch

    View Slide

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

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

    View Slide

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

    View Slide

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

    View Slide

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


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


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


    View Slide

  23. Verify Micronaut API with HTTPie

    View Slide

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


    -DprojectGroupId=com.okta.rest \


    -DprojectArtifactId=quarkus \


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


    -Dpath="/hello" \


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

    View Slide

  25. https://code.quarkus.io

    View Slide

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

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

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

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


    http :8080/hello


    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN...


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


    View Slide

  31. Verify Quarkus API with HTTPie

    View Slide

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

    View Slide

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

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

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

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

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

  38. Verify Spring Boot API with HTTPie

    View Slide

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


    -DarchetypeGroupId=io.helidon.archetypes \


    -DarchetypeArtifactId=helidon-quickstart-mp \


    -DarchetypeVersion=2.5.0 \


    -DgroupId=com.okta.rest \


    -DartifactId=helidon \


    -Dpackage=com.okta.rest

    View Slide

  40. The Helidon CLI

    View Slide

  41. import io.helidon.security.Principal;


    import io.helidon.security.SecurityContext;


    import javax.ws.rs.GET;


    import javax.ws.rs.Path;


    import javax.ws.rs.Produces;


    import javax.ws.rs.core.Context;


    import java.util.Optional;


    import static javax.ws.rs.core.MediaType.TEXT_PLAIN;


    @Path("/hello")


    public class HelloResource {


    @GET


    @Produces(TEXT_PLAIN)


    public String hello(@Context SecurityContext context) {


    Optional userPrincipal = context.userPrincipal();


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


    }


    }

    View Slide

  42. import com.okta.rest.controller.HelloResource;

    import org.eclipse.microprofile.auth.LoginConfig;

    import javax.enterprise.context.ApplicationScoped;

    import javax.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

  43. 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-1.1.1/microprofile-jwt-auth-spec.html



    io.helidon.microprofile.jwt


    helidon-microprofile-jwt-auth



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

  45. Verify Helidon API with HTTPie

    View Slide

  46. @mraible
    Startup Performance
    Milliseconds
    0
    300
    600
    900
    1200
    Micronaut Quarkus Spring Boot Helidon
    919
    921
    334
    262
    686
    997
    227
    Dev Startup (mvn) Packaged Startup (java -jar)

    View 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/v2/#/mp/graphql/01_mp_graphql

    View Slide

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

    View 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 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-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/v2/#/mp/security/02_providers#_oidc_provider

    View Slide

  51. What about testing?

    View Slide

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

  53. @mraible
    Build with Docker
    Build your image


    docker build -t .


    Run your image


    docker run -it -p8080:8080

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

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


    Dockerfile


    Dockerfile.jlink


    Dockerfile.native


    Helidon + Jib


    Not available

    View 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 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 -p8080:8080
    https://quarkus.io/guides/building-native-image

    View Slide

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

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

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





    org.springframework.experimental


    spring-native


    0.11.4





    Build the native application


    mvn spring-boot:build-image


    View Slide

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

    View Slide

  64. @mraible
    Build the image


    docker build -f Dockerfile.native -t .


    And run it


    docker run --rm -p8080:8080
    Go Native with GraalVM and Helidon

    View Slide

  65. @mraible
    Native Startup Performance
    Milliseconds
    0
    20
    40
    60
    80
    100
    June 6, 2022
    42.4
    61
    19.2
    29.8
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  66. @mraible
    Native Memory Used (MB)
    Megabytes
    0
    25
    50
    75
    100
    June 6, 2022
    62
    62
    36
    59
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  67. @mraible
    Tests Run on a 2019 MacBook Pro

    View Slide

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

    View Slide

  69. Community

    View Slide

  70. @mraible
    Stack Overflow Tags
    0
    35,000
    70,000
    105,000
    140,000
    June 6, 2022
    67
    122,797
    2,719
    1,352
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  71. @mraible
    GitHub Stars
    0
    18,750
    37,500
    56,250
    75,000
    June 6, 2022
    2,700
    61,500
    10,000
    5,300
    Micronaut Quarkus Spring Boot Helidon

    View Slide

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

    View Slide

  73. @mraible
    Jobs on Indeed (US)
    0
    10,000
    20,000
    June 6, 2022
    16
    13,696
    188
    187
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  74. @mraible
    Twitter Followers
    0
    25,000
    50,000
    75,000
    100,000
    June 6, 2022
    3,712
    88,300
    15,000
    11,800
    Micronaut Quarkus Spring Boot Helidon

    View Slide

  75. Hot Web Frameworks https://hotframeworks.com

    View Slide

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

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

    View Slide

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

    View Slide

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

    View Slide

  80. What about M1 Max?
    https://twitter.com/mraible/status/1509371877348843525

    View Slide

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


    🚀 Micronaut is the easiest to use and has been since the beginning


    🌱 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

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

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


    @oktadev

    View Slide

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

  85. Thanks!


    Keep in Touch


    raibledesigns.com


    @mraible


    Presentations


    speakerdeck.com/mraible


    Code


    github.com/oktadev
    developer.okta.com

    View Slide

  86. developer.okta.com

    View Slide