Repository navigation
Migrating Spring Boot
This document provides guidelines and tips for migrating a Spring Boot application from V3.5 to V4.0.
This update deprecates a few classes and changes the classpath of a few dependencies. Below are some key changes to be aware of:
The @NonNull annotation from the org.springframework.lang package has been deprecated in favor of using the jakarta.annotation.Nonnull annotation.
import org.springframework.lang.NonNull;
public void someMethod(@NonNull Argument argument) {
}As part of a change towards Jackson 3, the Jackson2ObjectMapperBuilder class from the org.springframework.http.converter.json.Jackson2ObjectMapperBuilder package has been deprecated. It is recommended to use the tools.jackson.databind.json.JsonMapper.Builder class instead.
Another recomended change is to migrate from ObjectMapper to JsonMapper.
Migrate from:
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return builder.build();
}To:
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.databind.json.JsonMapper.Builder;
public JsonMapper objectMapper(Builder builder) {
return builder
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.build();
}So far, I was unable to verify if the YML/Properties configuration to disable failure on empty beans still works, so I recommend explicitly disabling it as shown above. You can keep using the props configuration below if you want, but use it at your own risk:
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=falsespring:
jackson:
serialization:
FAIL_ON_EMPTY_BEANS: falseThe Actuator and Micrometer libraries have undergone significant changes in this version. Some classes and methods have been deprecated or removed. It is recommended to review the official migration guide for Actuator and Micrometer to ensure compatibility with the new version. Here is a small tip based on our templates and existing code:
Migrate from:
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;To:
import org.springframework.boot.micrometer.metrics.autoconfigure.MeterRegistryCustomizer;Spring security has also undergone some changes in this version. Spring Security 7 is almost the same as 6, but some small changes were introduced that could end up breaking our existing security configurations. Some classes and methods have been deprecated or removed. It is recommended to review the official migration guide for Spring Security to ensure compatibility with the new version. Here is a small tip based on our templates and existing code:
The ApiAuthorizationCustomizer class usually ends all routes with a .anyRequest().denyAll(); method, which is now considered a final instruction, meaning, this should terminate any api configuration. The problem with this is that even if you set this as your final instruction, Spring can and will introduce instructions afterwards, making your application bread. It is recommended to remove this instruction, as by default, any non-configured route will be denied access.
Another issue, at least for the initial releases of Spring Security 7, is that some of the reachability metadata is not correctly set, causing issues with native build. That will be covered on the Spring Native issues section.
The AuthorizationManager class changed one of its method signatures. Migrate from:
AuthorizationManager<RequestAuthorizationContext> manager = factory.gotRoleMatching(matcher);
AuthorizationDecision decision = manager.check(() -> null, context);To:
AuthorizationManager<RequestAuthorizationContext> manager = factory.gotRoleMatching(matcher);
AuthorizationResult decision = manager.authorize(() -> null, context);Spring Security 7 seems to be missing a few reachability metadata entries that are required for native builds. As a workaround, it is recommended to add the following reachability configuration to your reachability-metadata.json file. For more information, check the Spring Native issues section.
{
"reflection": [
{
"type": "org.springframework.security.config.annotation.web.builders.HttpSecurity",
"methods": [
{
"name": "headers",
"parameterTypes": [
"org.springframework.security.config.Customizer"
]
},
{
"name": "csrf",
"parameterTypes": [
"org.springframework.security.config.Customizer"
]
},
{
"name": "cors",
"parameterTypes": [
"org.springframework.security.config.Customizer"
]
},
{
"name": "authorizeHttpRequests",
"parameterTypes": [
"org.springframework.security.config.Customizer"
]
},
{
"name": "oauth2ResourceServer",
"parameterTypes": [
"org.springframework.security.config.Customizer"
]
}
]
}
]
}As can be seeing on the list of dependencies listed on the Spring Migration guide, a lot of libraries have gained their own test libraries. It is recommended to review the official migration guide for testing to ensure compatibility with the new version. Apart from that, it is advised to migrate some of the existing classpaths, as it got deprecated and migrated:
This dependency has been migrated to a new package. Update your imports accordingly:
From:
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import static org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrint.SYSTEM_OUT;To:
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import static org.springframework.boot.webmvc.test.autoconfigure.MockMvcPrint.SYSTEM_OUT;Spring Boot 4 has a stronger focus and support for GraalVM native images. However, there are still some issues that need to be addressed when building native images with Spring Boot 4. One of them is the new requirement for GraalVM 25.x, meaning that the base image used for native builds must be updated accordingly.
Migrate from:
FROM ghcr.io/graalvm/native-image-community:21.0.2 AS buildTo:
FROM ghcr.io/graalvm/native-image-community:25.0.1 AS buildThere is an issue with reachability metadata not being correctly set for some Spring Security classes, causing native builds to fail. As a workaround, it is recommended to add the following reachability configuration to your reachability-metadata.json file. This file should be added to the src/main/resources/META-INF/native-image/<your pom group>/<your pom artifact id>-additional-hints. As an example, assuming that you have this defined as your project definition inside your pom.xml:
<?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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ca.bc.gov</groupId>
<artifactId>some-app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>BC Gov Application name</name>
<description>This is a description of the BC Gov Application name project.</description>
</project>The file should be located at: src/main/resources/META-INF/native-image/ca.bc.gov/some-app-additional-hints/reachability-metadata.json. Even though the GraalVM documentation refers to the file location as src/main/resources/META-INF/native-image/ca.bc.gov/some-app/reachability-metadata.json, it is important to include suffix additional-hints at the end of the path, as Spring already adds some of its own reachability metadata, and if we don't include the suffix, it will override Spring's own file during build time.
If any extra reachability metadata is required, it will be mentioned on the specific sections of this documentation.
Some dependencies have been migrated to new packages. It is recommended to review the official migration guide for dependencies to ensure compatibility with the new version. We advise to remove as much as possible the explicit versioning of dependencies, as it is expected from Spring Boot to have been fixed already, in terms of CVE.
Here is a small tip based on our templates and existing code:
Some dependencies are not required, as they are usually already part of other dependencies being used already. It is recommended to remove the following dependencies if they are present in your pom.xml:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>We also removed the following plugin, as it is now part of the Spring Boot build process:
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>${hibernate.version}</version>
<executions>
<execution>
<id>enhance</id>
<goals>
<goal>enhance</goal>
</goals>
<configuration>
<enableLazyInitialization>true</enableLazyInitialization>
<enableDirtyTracking>true</enableDirtyTracking>
<enableAssociationManagement>true</enableAssociationManagement>
</configuration>
</execution>
</executions>
</plugin>To accomodate some of the changes on Spring Boot 4, it is recommended to add the following dependencies if they are not present in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-micrometer-tracing</artifactId>
</dependency>Migrate from:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.8</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>To:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>Migrate from:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>To:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>Flyway has its own Spring Boot starter now. It also has a test dependency that needs to be added for testing purposes.
Migrate from:
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>To:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway-test</artifactId>
<scope>test</scope>
</dependency>Migrate from:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>To:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security-oauth2-client-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security-oauth2-resource-server-test</artifactId>
<scope>test</scope>
</dependency>Migrate from:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>To:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-postgresql</artifactId>
<scope>test</scope>
</dependency>Spring Boot 4 has migrated some of its dependencies to new artifacts. It is recommended to update the following dependencies if they are present in your pom.xml, especially AOP, as it is required for some Spring features to work properly, such as tracing and metrics.
Also make sure to pay attention to the new test dependencies.
Migrate from:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>To:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aspectj</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aspectj-test</artifactId>
<scope>test</scope>
</dependency>This wiki documents NR Waste Plus for users and developers. Verify security and deployment guidance against the current application configuration before applying it elsewhere.
- Report an issue or ask a question in the GitHub repository.
- Follow the Contributing Guidelines to propose an update.
- Read the Code of Conduct.
Collection indexes support human browsing and machine retrieval. Keep both current when adding or moving wiki pages.
NR Waste Plus Wiki | GitHub Repository