Blogg
Här finns tekniska artiklar, presentationer och nyheter om arkitektur och systemutveckling. Håll dig uppdaterad, följ oss på LinkedIn
Här finns tekniska artiklar, presentationer och nyheter om arkitektur och systemutveckling. Håll dig uppdaterad, följ oss på LinkedIn
With Spring Boot 3.2 and Spring Framework 6.1, we get support for some really exciting new features like Java 21, including Virtual threads, and shorter startup times using Coordinated Restore at Checkpoint (CRaC). In this blog post, I will use the source code in the 3rd edition of my book on building microservices with Spring Boot and describe how to upgrade it to Spring Boot 3.2 and Java 21.
The blog post is divided into the following sections:
To access the source code of the book that is updated to Spring Boot 3.2, run the following commands:
git clone https://github.com/PacktPublishing/Microservices-with-Spring-Boot-and-Spring-Cloud-Third-Edition.git
cd Microservices-with-Spring-Boot-and-Spring-Cloud-Third-Edition
git checkout SB3.2
This blog post describes how to upgrade the source code from Spring Boot 3.1. If you want to learn about how the source code was upgraded from Spring Boot 3.0, the version used in the book, to Spring Boot 3.1, see the blog post Upgrade to Spring Boot 3.1.
You can find the changes applied to upgrade the source code to Spring Boot 3.2 by comparing two folders that contain a clone of the Git-repo, one with the SB3.1
branch checked out and one with the SB3.2
branch checked out.
Let’s start by looking at the changes applied to the source code.
To upgrade the source code from Spring Boot 3.1, the following steps have been performed:
gradle.build
Dockerfile
gradle-wrapper.properties
Dockerfile
Each step is described in detail in the subsections below.
gradle.build
The following dependencies have been upgraded in the gradle.build
files:
Dependency | Before | After |
---|---|---|
Java | 17 | 21 |
Spring Boot | 3.1.4 | 3.2.3 |
Spring Cloud | 2022.0.4 | 2023.0.1 |
Spring Dep Mgm plugin | 1.1.3 | 1.1.4 |
springdoc-openapi | 2.1.0 | 2.3.0 |
GraalVM Native plugin | 0.9.27 | 0.9.28 |
Resilience4j | 2.0.2 | 2.2.0 |
MapStruct | 1.5.3 | 1.5.5 |
Note: The GraalVM Native plugin only concerns Chapter 23, Native-Complied Java Microservices.
In the SB3.1
branch for Spring Boot 3.1, these dependencies look as the following in the build.gradle
files:
plugins {
id 'org.springframework.boot' version '3.1.4'
id 'io.spring.dependency-management' version '1.1.3'
id 'org.graalvm.buildtools.native' version '0.9.27'
id 'java'
}
sourceCompatibility = '17'
ext {
springCloudVersion = "2022.0.4"
resilience4jVersion = "2.0.2"
mapstructVersion = "1.5.3.Final"
}
dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.1.0'
In the SB3.2
branch for Spring Boot 3.2, the dependencies look like:
plugins {
id 'org.springframework.boot' version '3.2.3'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.graalvm.buildtools.native' version '0.9.28'
id 'java'
}
sourceCompatibility = '21'
ext {
springCloudVersion = '2023.0.1'
resilience4jVersion = '2.2.0'
mapstructVersion = '1.5.5.Final'
}
dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webflux-ui:2.3.0'
Dockerfile
Each microservice’s Dockerfile
has been updated to use Java 21 in runtime. As previously, Adoptium’s open source based build of OpenJDK, Eclipse Temurin is used. For more information, see https://adoptium.net/temurin.
In the SB3.1
branch for Spring Boot 3.1, Java 17 is used:
FROM eclipse-temurin:17.0.5_8-jre-focal as builder
...
FROM eclipse-temurin:17.0.5_8-jre-focal
In the SB3.2
branch for Spring Boot 3.2, Java 21 is used:
FROM eclipse-temurin:21.0.1_12-jre-jammy as builder
...
FROM eclipse-temurin:21.0.1_12-jre-jammy
gradle-wrapper.properties
To support Java 21, the Gradle version has to be version 8.5 or newer. For more information, see Gradle 8.5 Release Notes, full Java 21 support.
The file gradle/wrapper/gradle-wrapper.properties
has been updated to specify that Gradle version 8.7 shall be used.
In the SB3.1
branch for Spring Boot 3.1, it looks like:
distributionUrl=https://services.gradle.org/distributions/gradle-7.6-bin.zip
In the SB3.2
branch for Spring Boot 3.2, it looks like:
distributionUrl=https://services.gradle.org/distributions/gradle-8.7-bin.zip
Dockerfile
Since Spring Boot 3 no longer supports Java 8, Spring Boot’s “Uber Jar” loading mechanism has been rewritten in Spring Boot 3.2. For more information, see Spring Boot 3.2 Release Notes, nested jar support.
The new implementation is expected to replace the previous one transparently. However, an update of the source code is required in one case. In the Dockerfile
’s ENTRYPOINT
, the new launcher class (the main class) has to be specified.
In the SB3.1
branch for Spring Boot 3.1, the entry point looks like:
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
In the SB3.2
branch for Spring Boot 3.2, the entry point looks like:
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
A couple of bugs were revealed while testing GrallVM’s native compiler with Spring Boot 3.2 in Chapter 23. The workarounds applied for each bug are described below.
Hibernate v6.4.4 does not work when native compiled
From the Spring Boot 3.2.3 release notes, we can read:
⚠️ Noteworthy
This release upgrades to Hibernate 6.4.4.Final. While it contains a number of valuable bug fixes, it does not work correctly in a native image. If you are using GraalVM, Hibernate should be temporarily downgraded to 6.4.2.Final using the hibernate.version property.
This affects the Review microservice only. To apply the workaround by downgrading Hibernate to v6.4.2, the following line has been added to its build.gradle
file:
ext['hibernate.version'] = '6.4.2.Final'
A native compile hint is required for org.springframework.messaging.Message
The Product Composite microservice can’t be native compiled using Spring Boot 3.2 unless an annotation hint is used to add reflection metadata for the class org.springframework.messaging.Message
. The Message
- class is added to the already existing @RegisterReflectionForBinding
annotation in the ProductCompositeServiceApplication
- class. It looks like:
@RegisterReflectionForBinding({ ..., Message.class})
public class ProductCompositeServiceApplication {
The CLI tool SDKMAN!
is used to install a GraalVM-based JDK for Java 21. See Chapter 23 for instructions on how to install it.
The JDK is installed with the following command:
sdk install java 21.0.2-graalce
To ensure that the correct JDK is used when compiling the Java source code, run the following command before compiling:
sdk use java 21.0.2-graalce
This completes the walkthrough of the changes required; let’s wrap this blog post with a short recap on how to run the end-to-end tests to verify that everything works as expected with Spring Boot 3.2 and Java 21.
To try out the source code with Spring Boot 3.2 and Java 21, first ensure that Docker Desktop
, git
, jq
, curl
are installed. For installation instructions, see Chapters 21 and 22. Then perform the following steps:
git clone https://github.com/PacktPublishing/Microservices-with-Spring-Boot-and-Spring-Cloud-Third-Edition.git
cd Microservices-with-Spring-Boot-and-Spring-Cloud-Third-Edition
git checkout SB3.2
sdk use java 21.0.2-graalce
cd ChapterNN # NN = 04 to 23
./gradlew build
docker compose build
docker compose up -d
./test-em-all.bash
Note: Replace
ChapterNN
withChapter04
-Chapter23
depending on what chapter you want to test.
Look for a final log message that says:
End, all tests OK...
Wrap up the tests by tearing down the microservice landscape with the command:
docker compose down
For testing the source code changes with Kubernetes, Istio, and the EFK Stack, see instructions in chapters 17 - 20 for setting up the Kubernetes cluster. For building native images with the source code changes, see instructions in Chapter 23, Native-Complied Java Microservices.
In this blog post, we have seen how to upgrade the source code in the book to Spring Boot 3.2 and Java 21 and use the end-to-end test script, test-em-all.bash
to verify that everything works as expected.
In the next blog posts, I will describe how to use the new features supported by Spring Boot 3.2, such as Virtual threads in Java 21, and how to achieve shorter startup times using Coordinated Restore at Checkpoint (CRaC).