A Dive into the Spring Boot 3.2 Release: New Features and Enhancements

Chris Sathiya
6 min readDec 27, 2023

--

The latest release of Spring Boot, version 3.2, introduces a host of new features and enhancements that cater to improved developer experiences and expanded capabilities. In this article, we’ll explore the key highlights of this release, covering everything from its run time efficiency improvements to advancements in observability and Docker image building.

it emerges as a game-changer, revolutionizing the development landscape by focusing on three core pillars, apart from some major version upgrades.

  1. Runtime efficiency.
  2. Client support innovation.
  3. Observability enhancements.

Let’s jump into each aspect to understand how this release propels Spring Boot to new heights.

1. Runtime Efficiency

Incorporating support for Java 21 in this latest release brings forth a multitude of advantages, particularly leveraging the newest features from the JDK. Given that Spring applications are designed for prolonged and efficient processing, the JVM inherently exhibits a high degree of intelligence in managing such scenarios.

The JVM adeptly identifies areas of frequent and intense execution, facilitating compilation and subsequent optimization to enhance overall efficiency.

In today’s diverse landscape of application development, we encounter a wide range of needs. Some applications require low memory usage and quick startup times, while others, particularly those dealing with tasks like communicating with databases or HTTP services, prioritize scalability.

Java and Spring have adapted to meet the demands of various applications. Notably, in Spring Boot 3.2 brings support for Virtual Threads and Project CRaC (Coordinated Restore at Checkpoint), providing developers with additional tools to address different requirements.

1.1 Support for Virtual Threads

Okay! before talking about virtual threads, let’s understand what thread is, what changes can threads make in processing?

Threads can execute a set of instructions at a time, so you can get an idea, it will concurrently execute the instructions and give us the efficiency. Java supports multi-threading so it gives us the advantage that it can run multiple tasks at once. It means it uses the resources (cores of the CPU). In java each method is allocated for a particular thread and It’s a 1:1 mapping between java threads and OS threads.

But as you already know, Spring boot is a framework to implement server side mainly, so there will be many database calls or talking to other 3rd party services or talking to our own services. So these types of requests need to be stopped for waiting for the response from other services or databases. so these are considered as blocking operations. So there is a stop in the thread which is handling the blocking operation. So you may ask the question, is it scalable? Or can this be improved?

As experts suggest, there will be two solutions one is increasing resources memory or CPU (vertical scaling) and increasing numbers of servers (Horizontal scaling) another one is using asynchronous programming anyway of course there are some cons in this.

Now let’s understand about Virtual threads

what if we don’t block the actual threads and spawn millions of thread from the actual ones ? and assign the task to one of the spawned threads ? yes! that’s what the Java 21 provides us. This enables us to write blocking code without major worries about scalability.

Java 21’s virtual threads’ notes as per this one, a task is linked to an actual thread with virtual thread attached and if we need to perform a blocking operation, it will be shifted to the heap and once the task is completed it is then moved to waiting list for the actual thread it was linked.

1.2 Project CRaC

The CRaC (Coordinated Restore at Checkpoint) Project is focused on investigating ways to coordinate Java programs by creating snapshots or images (checkpointing) of a running Java instance. The purpose of these snapshots is to potentially address issues related to startup and warm-up times. Essentially, the project aims to develop a universal API that is agnostic to specific mechanisms, providing a standardized way to notify Java programs about checkpointing and restoration events.

The core objective is to establish a consistent method for Java applications to be aware of when they are being checkpointed or restored. In addition to this primary goal, the project involves exploring integration possibilities with existing checkpoint/restore mechanisms while also considering the development of new mechanisms. Furthermore, the research includes investigating changes to the Java Virtual Machine (JVM) and the Java Development Kit (JDK) to optimize the size of the created images and ensure their correctness.

In essence, CRaC seeks to enhance the efficiency and reliability of Java programs by introducing coordinated mechanisms for capturing and restoring their execution states.

2. Client support innovation

Spring boot has simplified its communications with external services and databases, by providing APIs, this includes database calls and external service communications by using Web Client or Rest Template. (Web Client is used to write non-blocking calls where as Rest Template is used to write blocking calls). In this version Spring Boot has introduced JDBC Client and Rest Client, two new client supports.

2.1 RestClient Support

The release introduces support for the new RestClient interface, offering a functional style blocking HTTP API with a design similar to WebClient. It encourages developers to consider RestClient as an alternative to RestTemplate, emphasizing the need for a fresh approach.

example of using RestClient

@Service
public class ExampleService {

private final RestClient restClient;

public ExampleService(RestClient.Builder builder) {
this.restClient = builder
.baseUrl("<https://example_base_url.com/>")
.build();
}

public Collection<Example> findAll() {
return restClient.get()
.uri("/example")
.retrieve()
.body(new ParameterizedTypeReference<>(){});
}

public ResponseEntity<Example> findById(Long id) {
return restClient.get()
.uri("/example/{id}", id)
.retrieve()
.toEntity(Post.class);
}

}

please note, In spring boot 3, there was Http Interface Client introduced, we can define Http calls in an interface to omit boiler plate codes, earlier this was based on Web Client but now with this release this is based on Rest Client.

2.2 Support for JDBC Client

The JDBC template is a useful abstraction for simplifying interactions with databases. However, when creating basic CRUD services that involve creating, reading, updating, and deleting resources, the The use of JDBC templates may involve unnecessary complexity. This verbosity arises from dealing with intricate details like row mappers and mapping columns to fields.

Despite its complexities, the JDBC template provides developers with complete control over SQL, a feature highly appreciated by developers. To address the challenges posed by these complexities, Spring Boot 3.2 introduces the JDBC client. This new addition presents a fluent API that is easy to understand and read. One notable advantage is its automatic configuration, simplifying the process of obtaining an instance without unnecessary complications.

Let’s illustrate this with an example. Consider a Repository class that includes CRUD methods for reading and persisting data to a database. In this example, the JDBC Client instance is injected using constructor injection, contributing to enhanced code readability through the use of the fluent API.

@Repository
public class PostRepository {

private final JdbcClient jdbcClient;

public PostRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}

public List<Example> findAll() {
return jdbcClient.sql("SELECT * FROM example")
.query(Example.class)
.list();
}

public Optional<Example> findById(String id) {
return jdbcClient.sql("SELECT * FROM Example WHERE id = :id")
.param("id", id)
.query(Example.class)
.optional();
}

public void create(Example example) {
jdbcClient.sql("INSERT INTO Example(id, data) values(?,?)")
.params(List.of(example.id(), example.Data()))
.update();
}


public void delete(String id) {
jdbcClient.sql("delete from Example where id = :id")
.param("id", id)
.update();
}

}

3. Observability enhancements.

In Spring Boot 3.0, a significant enhancement was the introduction of a unified Observation API, originally employed internally by the framework and now accessible to developers. This API enables the instrumentation of applications, allowing the execution of various actions for each instrumentation, such as emitting log messages, starting and stopping timers, incrementing counters, and signaling errors.

Previously, to incorporate metrics and tracing, developers had to instrument their applications twice, leading to potential code redundancy and discouraging the implementation of observation. However, with Spring Boot 3.2, Micrometer’s annotations like @Timed, @Counted, @NewSpan, @ContinueSpan, and @Observed can now be utilized directly. These annotations are auto-configured if AspectJ is included in the classpath, achieved by adding the spring-boot-starter-aop dependency to the project. This streamlined approach simplifies the observation process and eliminates the need for manual configuration, making it more convenient for developers.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Conclusion

Hope you have understood what the Spring boot 3.2 offers us, it included runtime efficiency with virtual threads support and CraC project then it introduced two new client abstractions such as Rest Client and JDBC client and it simplified and enhanced the observability too.

--

--

Chris Sathiya

Software Engineer | Learner | Java | Spring boot | Docker | Database