Spring Boot 4.0 with JDK 21 and Virtual Threads: Boosting Performance

Spring Boot 4.0 introduces a milestone upgrade that requires JDK 21, switches to jakarta.* packages, offers first‑class virtual‑thread support, a built‑in declarative HTTP client, native retry annotations, API versioning, and modular auto‑configuration, all aimed at higher cloud‑native performance.

Senior Xiao Ying
Senior Xiao Ying
Senior Xiao Ying
Spring Boot 4.0 with JDK 21 and Virtual Threads: Boosting Performance

Spring Boot 4.0 is a milestone release that pushes Java development toward cloud‑native, null‑safety, and high performance.

1. Environment Upgrade: Embrace JDK 21 and Jakarta EE 11

JDK Requirement : JDK 21 or higher (JDK 21 LTS recommended). Running on JDK 17 is possible but virtual‑thread features need JDK 21+.

Namespace Change : The old javax.* packages are fully replaced by jakarta.*. For example, import javax.servlet.http.HttpServletRequest; must become import jakarta.servlet.http.HttpServletRequest;.

Servlet Container : Requires Tomcat 11+ or Jetty 12.1+.

2. Performance Core: Virtual Threads in Practice

Spring Boot 4.0 provides first‑class support for virtual threads. When enabled, each web request is handled by a lightweight virtual thread, allowing thousands of concurrent connections.

Configuration (application.yml) :

spring:
  threads:
    virtual:
      enabled: true  # Enables virtual threads for Tomcat thread pool
  task:
    scheduling:
      virtual: true  # Enables virtual threads for scheduled tasks

Patch Note : Virtual threads are not fully compatible with the synchronized lock. If performance does not improve, replace synchronized with ReentrantLock:

// ❌ Avoid synchronized
public synchronized void oldMethod() { ... }

// ✅ Use ReentrantLock
private final Lock lock = new ReentrantLock();
public void newMethod() {
    lock.lock();
    try {
        // business logic
    } finally {
        lock.unlock();
    }
}

3. New Feature: Declarative HTTP Client

The traditional RestTemplate boilerplate is replaced by a built‑in declarative client using the @HttpExchange annotation, similar to Spring Cloud OpenFeign.

Example Interface (fetching posts from JSONPlaceholder):

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.service.annotation.GetExchange;
import org.springframework.web.service.annotation.HttpExchange;
import java.util.List;

@HttpExchange(url = "https://jsonplaceholder.typicode.com")
public interface JsonPlaceholderService {
    @GetExchange("/posts")
    List<Post> getPosts();

    @GetExchange("/posts/{id}")
    Post getPostById(@PathVariable Long id);
}

Configuration (Java) :

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;

@Configuration
public class AppConfig {
    @Bean
    public JsonPlaceholderService jsonPlaceholderService() {
        WebClient client = WebClient.builder()
            .baseUrl("https://jsonplaceholder.typicode.com")
            .build();
        HttpServiceProxyFactory factory = HttpServiceProxyFactory
            .builder(WebClientAdapter.forClient(client))
            .build();
        return factory.createClient(JsonPlaceholderService.class);
    }
}

Usage in a service:

@Service
public class MyService {
    private final JsonPlaceholderService apiService;
    public MyService(JsonPlaceholderService apiService) {
        this.apiService = apiService;
    }
    public void run() {
        Post post = apiService.getPostById(1L);
        System.out.println(post.getTitle());
    }
}

4. Resilience Boost: Built‑in Retry Mechanism

Previously, retry required the spring-retry dependency. Spring Boot 4.0 now includes the @Retryable annotation in spring-core.

Retry Example :

import org.springframework.context.annotation.Configuration;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;

@Configuration
@EnableRetry
public class ResilientConfig { /* ... */ }

@Service
public class PaymentService {
    @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2))
    public void callRemoteApi() {
        System.out.println("Attempting remote API call...");
        throw new RuntimeException("Network timeout");
    }
}

5. Essential Skill: API Version Control

Spring Boot 4.0 natively supports API versioning, allowing version differentiation via request headers, parameters, or media types without custom URL changes.

Controller Example :

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/user")
public class UserController {
    @RequestMapping(value = "/info", version = "v1")
    public String getInfoV1() {
        return "{\"name\": \"old version user\"}";
    }

    @RequestMapping(value = "/info", version = "v2")
    public String getInfoV2() {
        return "{\"name\": \"new version user\", \"email\": \"[email protected]\"}";
    }
}

Version strategy can be defined in application.yml:

spring:
  mvc:
    apiversion:
      enabled: true
      # header: API-VERSION=v2
      # or 'parameter' / 'media-type'
      default-version: v1

6. Modular Auto‑Configuration

Earlier auto‑configuration was heavyweight and slowed GraalVM native image generation. Spring Boot 4.0 splits auto‑configuration into fine‑grained modules, speeding startup and simplifying custom starter development.

Impact : No code‑style changes for developers, but project startup becomes faster and custom starters are clearer.

7. Starter Project Setup (Pitfalls Guide)

When creating a new Spring Boot 4.0 project, the pom.xml must follow these rules:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- Parent must be Spring Boot 4.0.0 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.0.0-M1</version> <!-- use M1 or SNAPSHOT before final release -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-4-demo</name>
    <properties>
        <java.version>21</java.version> <!-- must be 21+ -->
    </properties>
    <dependencies>
        <!-- Web starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Observability starter (new in 4.0) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-opentelemetry</artifactId>
        </dependency>
        <!-- Test starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>4.0.0-M1</version>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots><enabled>false</enabled></snapshots>
        </repository>
    </repositories>
</project>
Spring Boot 4.0 diagram
Spring Boot 4.0 diagram
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

api-versioningSpring Bootretryvirtual-threadsJDK 21Declarative HTTP ClientModular Auto-Configuration
Senior Xiao Ying
Written by

Senior Xiao Ying

Dedicated to sharing Java backend technical experience and original tutorials, offering career transition advice and resume editing. Recognized as a rising star in CSDN's Java backend community and ranked Top 3 in the 2022 New Star Program for Java backend.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.