Skip to content

Latest commit

 

History

History
206 lines (146 loc) · 6.36 KB

demo-helidon.adoc

File metadata and controls

206 lines (146 loc) · 6.36 KB

Build a Secure Java REST API with Helidon

In this demo, I’ll show how to create a secure REST API and native image with Helidon. You’ll see how to run a secure, OAuth 2.0-protected, Java REST API that allows JWT authentication. Then, I’ll compare its performance with Micronaut, Quarkus, and Spring Boot.

Check this video’s description below for links to its blog post, comments, demo script, and code example.

Prerequisites:

Tip
The brackets at the end of some steps indicate the IntelliJ Live Templates to use. You can find the template definitions at mraible/idea-live-templates.

Install a JDK with GraalVM

Use SDKMAN to install Java 17 with GraalVM

sdk install java 22.3.r17-grl

Generate an OAuth 2.0 Access Token

  1. Install the Okta CLI and run okta register to sign up for a new account. If you already have an account, run okta login.

  2. Run okta apps create spa. Set oidcdebugger as an app name and press Enter.

  3. Use https://oidcdebugger.com/debug for the Redirect URI and set the Logout Redirect URI to https://oidcdebugger.com.

  4. Navigate to the OpenID Connect Debugger website.

    1. Fill in your client ID

    2. Use https://{yourOktaDomain}/oauth2/default/v1/authorize for the Authorize URI

    3. Select code for the response type and Use PKCE

    4. Click Send Request to continue

  5. Set the access token as a TOKEN environment variable in a terminal window.

    TOKEN=eyJraWQiOiJYa2pXdjMzTDRBYU1ZSzNGM...

Build a Java REST API with Helidon

  1. Create a Helidon app with OAuth 2.0 support:

    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
    Tip
    You can also install the Helidon’s CLI and run helidon init.
  2. Add MicroProfile JWT support in pom.xml:

    <dependency>
        <groupId>io.helidon.microprofile.jwt</groupId>
        <artifactId>helidon-microprofile-jwt-auth</artifactId>
    </dependency>
  3. Add a HelloResource class that returns the user’s information: [h-hello]

    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() + "!";
        }
    }
  4. Add a HelloApplication class in src/main/java/com/okta/rest to register your resource and configure JWT authentication: [h-app]

    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<Class<?>> getClasses() {
            return Set.of(HelloResource.class);
        }
    }
  5. Add your Okta endpoints to src/main/resources/META-INF/microprofile-config.properties.

    mp.jwt.verify.issuer=https://{yourOktaDomain}/oauth2/default
    mp.jwt.verify.publickey.location=${mp.jwt.verify.issuer}/v1/keys

Run and Test Your Helidon REST API with HTTPie

  1. Start your app from your IDE or using a terminal:

    mvn package && java -jar ./target/helidon.jar
  2. Test your API with an access token.

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

Build a native Helidon app with GraalVM

  1. Compile your Helidon app into a native executable using the native-image profile:

    mvn package -Pnative-image
  2. Start your Helidon app:

    ./target/helidon
  3. Test your API with an access token.

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

Startup Time Comparison

  1. Run each image three times before recording the numbers, then each command five times

  2. Write each time down, add them up, and divide by five for the average. For example:

    Helidon: (45 + 44 + 45 + 39 + 43) / 5 = 43.2
    Micronaut: (17 + 19 + 19 + 20 + 15) / 5 = 18
    Quarkus: (25 + 18 + 20 + 19 + 21) / 5 = 20.6
    Spring Boot: (39 + 40 + 38 + 37 + 41) / 5 = 39
Table 1. Native Java startup times in milliseconds
Framework Command executed Milliseconds to start

Helidon

./helidon/target/helidon

43.2

Micronaut

./micronaut/target/app

18

Quarkus

./quarkus/target/quarkus-1.0.0-SNAPSHOT-runner

20.6

Spring Boot

./spring-boot/target/demo

39

Memory Usage Comparison

Test the memory usage in MB of each app using the command below. Make sure to send an HTTP request to each one before measuring.

ps -o pid,rss,command | grep --color <executable> | awk '{$2=int($2/1024)"M";}{ print;}'

Substitute <executable> as follows:

Table 2. Native Java memory used in megabytes
Framework Executable Megabytes before request Megabytes after request Megabytes after 5 requests

Helidon

helidon

79

97

131

Micronaut

app

43

58

69

Quarkus

quarkus

37

48

50

Spring Boot

demo

74

98

99

Important
If you disagree with these numbers and think X framework should be faster, I encourage you to clone the repo and run these tests yourself. If you get faster startup times for Helidon, do you get faster startup times for Micronaut and Quarkus too?

Secure Native Java with Helidon FTW!

⚡️ Create a secure REST API with Helidon: okta start helidon

🚀 Find this example’s code on GitHub: @oktadev/native-java-examples/helidon