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

Comparing Native Java REST API Frameworks - Manchester JUG 2022

Comparing Native Java REST API Frameworks - Manchester 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
Manchester JUG PR: https://github.com/oktadev/native-java-examples/pull/54

Matt Raible

October 26, 2022
Tweet

More Decks by Matt Raible

Other Decks in Programming

Transcript

  1. Matt Raible | @mraible October 26, 2022 Native Java REST

    API Comparison Micronaut, Quarkus, Spring Boot, and Helidon Photo by Chris Ford https:// fl ic.kr/p/97sLcj
  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
  3. @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
  4. @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
  5. @mraible Download the Oracle builds of OpenJDK https://jdk.java.net/19 Or Eclipse

    builds from Adoptium https://adoptium.net Get Started with Java 19
  6. @mraible Get Started with Java 19 Better yet, use SDKMAN!

    curl -s https://get.sdkman.io | bash 
 sdk install java 19-open
  7. @mraible sdk install micronaut mn create-app com.okta.rest.app \ -b maven

    -f security-jwt -f micronaut-aot Get Started with Micronaut
  8. 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() + "!"; } }
  9. @mraible Get Started with Quarkus sdk install quarkus quarkus create

    app com.okta.rest:quarkus quarkus ext add smallrye-jwt
  10. 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() + "!"; } }
  11. @mraible Get Started with Spring Boot https start.spring.io/starter.zip \ bootVersion==3.0.0-RC1

    \ dependencies==web,oauth2-resource-server,native \ packageName==com.okta.rest \ name==spring-boot \ type==maven-project \ baseDir==spring-boot | tar -xzvf -
  12. 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() + "!"; } }
  13. Test Spring Boot with HTTPie https://httpie.org mvn spring-boot:run http :8080/hello

    TOKEN=eyJraWQiOiJxOE1QMjFNNHZCVmxOSkxGbFFWNlN... http :8080/hello Authorization:"Bearer $TOKEN"
  14. @mraible Get Started with Helidon mvn -U archetype:generate -DinteractiveMode=false \

    -DarchetypeGroupId=io.helidon.archetypes \ -DarchetypeArtifactId=helidon-quickstart-mp \ -DarchetypeVersion=3.0.2 \ -DgroupId=com.okta.rest \ -DartifactId=helidon \ -Dpackage=com.okta.rest
  15. 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() + "!"; } }
  16. 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<Class<? >> getClasses() { return Set.of(HelloResource.class); } }
  17. 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"
  18. @mraible Startup Performance Milliseconds 0 300 600 900 1200 1500

    Micronaut Quarkus Spring Boot Helidon 1,098 919 372 270 689 1,072 234 Dev Startup (mvn) Packaged Startup (java -jar)
  19. @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
  20. @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
  21. @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
  22. @mraible Build with Docker Create a Dockerfile 
 FROM openjdk:19-alpine

    ARG JAR_FILE=target/*.jar COPY ${JAR_FILE} app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","/app.jar"]
  23. @mraible Build with Docker Build your image docker build -t

    <tag-name> . Run your image docker run -it -p 8080:8080 <tag-name>
  24. @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
  25. @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"
  26. @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
  27. @mraible Build with Docker Helidon generates three Docker-related files Dockerfile

    Dockerfile.jlink Dockerfile.native Helidon + Jib Not available
  28. @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
  29. @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 -p 8080:8080 <tag-name> https://quarkus.io/guides/building-native-image
  30. @mraible Use start.spring.io to get plugins and profiles <plugin> <groupId>org.springframework.boot

    </ groupId> <artifactId>spring-boot-maven-plugin </ artifactId> <configuration> <image> <buildpacks> <buildpack>gcr.io/paketo-buildpacks/bellsoft-liberica:9.9.0-ea </ buildpack> <buildpack>gcr.io/paketo-buildpacks/java-native-image </ buildpack> </ buildpacks> </ image> </ configuration> </ plugin> Go Native with GraalVM and Spring Boot
  31. @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> <snapshots><enabled>false </ enabled> </ snapshots> </ repository> </ repositories> <pluginRepositories> <pluginRepository> <id>spring-milestones </ id> <name>Spring Milestones </ name> <url>https: // repo.spring.io/milestone </ url> <snapshots><enabled>false </ enabled> </ snapshots> </ pluginRepository> </ pluginRepositories>
  32. @mraible Go Native with GraalVM and Spring Boot Build the

    native application mvn native:compile -Pnative Build an image and Docker container mvn spring-boot:build-image -Pnative
  33. @mraible Build the image docker build -f Dockerfile.native -t <tag-name>

    . And run it docker run --rm -p 8080:8080 <tag-name> Go Native with GraalVM and Helidon
  34. @mraible Native Startup Performance (GraalVM 22.3) Milliseconds 0 10 20

    30 40 50 October 26, 2022 43.2 39 20.6 18 Micronaut Quarkus Spring Boot Helidon
  35. @mraible Native Memory Used (MB) Megabytes 0 30 60 90

    120 150 October 26, 2022 131 99 50 69 Micronaut Quarkus Spring Boot Helidon
  36. @mraible Stack Overflow Tags 0 37,500 75,000 112,500 150,000 October

    24, 2022 69 129,542 3,162 1,432 Micronaut Quarkus Spring Boot Helidon
  37. @mraible GitHub Stars 0 18,750 37,500 56,250 75,000 October 24,

    2022 2,800 63,700 10,900 5,500 Micronaut Quarkus Spring Boot Helidon
  38. @mraible Jobs on Indeed (US) 0 6,000 12,000 October 24,

    2022 9 10,653 194 86 Micronaut Quarkus Spring Boot Helidon
  39. @mraible Twitter Followers 0 30,000 60,000 90,000 120,000 October 24,

    2022 4,024 93,800 16,100 12,300 Micronaut Quarkus Spring Boot Helidon
  40. @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
  41. @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 Boot 3 not as fast as expected My Thoughts
  42. @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