Start a Java REST API with Spring Boot

In this tutorial, I’ll show you how to create a secure REST API and native image with Spring Boot. 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 Helidon.

This tutorial is also available as a screencast.

Prerequisites:

The brackets at the end of some steps indicate the IntelliJ Live Templates I used in the video. 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.1.0.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...

Start a Spring Boot Java REST API

  1. Create a Spring Boot app with OAuth 2.0 support:

    https start.spring.io/starter.zip \
      bootVersion==2.6.7 \
      dependencies==web,oauth2-resource-server,native \
      packageName==com.okta.rest \
      name==spring-boot \
      type==maven-project \
      baseDir==spring-boot | tar -xzvf -
  2. Modify pom.xml to use tomcat-embed-programmatic instead of the default Tomcat.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-core</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.apache.tomcat.embed</groupId>
                <artifactId>tomcat-embed-websocket</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.experimental</groupId>
        <artifactId>tomcat-embed-programmatic</artifactId>
        <version>${tomcat.version}</version>
    </dependency>
  3. Add a HelloController class that returns the user’s information: [sb-hello]

    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() + "!";
        }
    }
  4. Configure the app to be an OAuth 2.0 resource server by adding the issuer to application.properties.

    spring.security.oauth2.resourceserver.jwt.issuer-uri=https://{yourOktaDomain}/oauth2/default
  5. Add a SecurityConfiguration class to configure JWT authentication: [securityconfig]

    package com.okta.rest;
    
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
    
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests(request -> request.anyRequest().authenticated())
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
        }
    }

Run and test your Spring Boot REST API with HTTPie

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

    ./mvnw spring-boot:run
  2. Test your API with an access token.

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

Build a native Spring Boot App

  1. Compile your Spring Boot app into a native executable using the native profile:

    ./mvnw package -Pnative
    To build a native app and a Docker container, use the Spring Boot Maven plugin and ./mvnw spring-boot:build-image.
  2. Start your Spring Boot app:

    ./target/demo
  3. Test it with HTTPie and an access token:

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

Startup time comparison

I compared startup times between frameworks by running each image three times before recording the numbers. Then, I ran each app five more times and averaged the results. I gathered these numbers on a 2019 MacBook Pro with an SSD, 2.4 GHz 8-Core Intel Core i9 processor, and 64 GB of RAM.

Versions used: Quarkus 2.9.0, Micronaut 3.4.3, Helidon 2.5.0, and Spring Boot 2.6.7 with Spring Native 0.11.5.

Memory usage comparison

I tested the memory usage (in megabytes) of each app using the command below. I ran it right after I started the app, after a single authenticated request, and after five authenticated requests.

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

The chart below shows the memory usage after five requests.

What about the MacBook Pro M1 Max?

My MacBook Pro (16-inch, 2021) with Apple M1 Max builds much faster, apps startup 2x faster, but they use more memory.

Comparing Native Java REST API Frameworks Live Stream

I missed Devoxx France this year, but I’m still doing my presentation! I’ll be live-streaming Comparing Native Java REST API Frameworks on June 7, 2022 at 6:00 MDT (14:00 CEST). Join me or watch the recorded version below!

Secure Native Java with Spring Boot FTW!

⚡️ Create a secure REST API with Spring Boot:

okta start spring-boot
okta start spring-boot -b webflux

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

Matt Raible is a well-known figure in the Java community and has been building web applications for most of his adult life. For over 20 years, he has helped developers learn and adopt open source frameworks and use them effectively. He's a web developer, Java Champion, and Developer Advocate at Okta. Matt has been a speaker at many conferences worldwide, including Devnexus, Devoxx Belgium, Devoxx France, Jfokus, and JavaOne. He is the author of The Angular Mini-Book, The JHipster Mini-Book, Spring Live, and contributed to Pro JSP. He is frequent contributor to open source and a member of the JHipster development team. You can find him online @mraible and raibledesigns.com.

Okta Developer Blog Comment Policy

We welcome relevant and respectful comments. Off-topic comments may be removed.