-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Spring Boot 4.0 Migration Guide
This document is meant to help you migrate your application to Spring Boot 4.0.
|
Note
|
This is a preview draft of the migration guide. It will be completed when Spring Boot 4.0.0 is released. |
Before you start the upgrade, make sure to upgrade to the latest available 3.5.x version.
This will make sure that you are building against the most recent dependencies of that line.
Please take time to review any calls you might be making to deprecated methods as these will be removed in Spring Boot 4.0.
The move to Spring Boot 4 will upgrade a number of dependencies and might require work on your end.
You can review dependency management for 3.5.x with dependency management for 4.0.x to asses how your project is affected.
Spring Boot 4.0 requires Java 17 or later. Using the latest LTS release of Java is encouraged.
Spring Boot applications can also be developed using Kotlin where v2.2 or later must be used.
If you’re using GraalVM’s native-image, v25 or later must be used.
If you manage dependencies directly, you also need to ensure that you use Spring Framework 7.x.
Once you have reviewed the state of your project and its dependencies, upgrade to the latest maintenance release of Spring Boot 4.0.
The features have been removed from this release and are no longer available
Spring Boot 4 is based on Jakarta EE 11 and we don’t yet have a suitable Jersey release to consume. Jersey 4 will support EE 11, but its release schedule is uncertain. Jersey also has not yet published a timeline for when Jackson 3 will be supported.
Given the above, we’ve decided to remove support for Jersey, for the time being at least. Reinstating support can be considered once there’s a Jersey GA that supports Jakarta EE 11.
Spring Boot 4 requires a Servlet 6.1 baseline, with which Undertow is not yet compatible. As a result, Undertow support is dropped, including the Undertow starter and the ability to use Undertow as an embedded server.
We do not recommend deploying Spring Boot 4.0 applications to a non-Servlet 6.1 compliant container.
Following the decision of removing reactor support in Spring Pulsar, Spring Boot no longer manages the reactive Pulsar client. Auto-configuration for Spring Pulsar Reactive has been removed as well.
Support for embedded launch scripts, used to create "fully executable" jar files, has been removed. The support was specific to Unix-like operating systems and had a number of limitations, most notably conflicting with the recommendations for efficient deployments. If you still require similar functionality, we recommend looking at alternatives such as Gradle’s application plugin.
You can still create uber jars with Spring Boot’s build plugins and run them using java -jar.
Spring Session Hazelcast is now under the leadership of the Hazelcast team. As such, direct support for Spring Session Hazelcast has been removed from Spring Boot itself.
Spring Session MongoDB is now under the leadership of the MongoDB team. As such, direct support for Spring Session Hazelcast has been removed from Spring Boot itself.
Spring Boot’s Spock integration has been removed as Spock does not yet support Groovy 5.
Spring Boot 4.0 has a new modular design and now ships smaller focused modules rather than several large jars. If your application uses Spring Boot “starter” POMs, most of your dependencies should be correct and your application will work as before.
You may, however, face issues if you use a technology that previously had no “starter” POM. You will also need to make dependency modifications if your current application doesn’t use Spring Boot “starter” POMs.
The following table shows the “starter” POM you should be using to support a specific technology:
| Technology | Main Dependency | Test Dependency |
|---|---|---|
Core Starters |
||
AspectJ |
|
|
Cloud Foundry Support |
|
|
Jakarta Validation |
|
|
Kotlin Serialization |
|
|
Reactor |
|
|
Web Server Starters |
||
Jetty |
|
none |
Reactor Netty |
|
none |
Tomcat |
|
none |
Web Client Starters |
||
Spring’s Imperative |
|
|
Spring’s Reactive |
|
|
Web Starters |
||
Spring GraphQL |
|
|
Spring HATEOAS |
|
|
Spring Session Data Redis |
|
|
Spring Session JDBC |
|
|
Spring Web MVC |
|
|
Spring WebFlux |
|
|
Spring Webservices |
|
|
Database Starters |
||
Cassandra |
|
|
Couchbase |
|
|
Elasticsearch |
|
|
Flyway |
|
|
JDBC |
|
|
jOOQ |
|
|
Liquibase |
|
|
LDAP |
|
|
MongoDB |
|
|
Neo4J |
|
|
R2DBC |
|
|
Spring Data Starters |
||
Spring Data Cassandra |
|
|
Spring Data Couchbase |
|
|
Spring Data Elasticsearch |
|
|
Spring Data JDBC |
|
|
Spring Data JPA (using Hibernate) |
|
|
Spring Data LDAP |
|
|
Spring Data MongoDB |
|
|
Spring Data Neo4J |
|
|
Spring Data R2DBC |
|
|
Spring Data Redis |
|
|
Spring Data REST |
|
|
IO Starters |
||
Hazelcast |
|
|
|
|
|
Quartz |
|
|
SendGrid |
|
|
Spring Caching Support |
|
|
Spring Batch (with JDBC) |
|
|
Spring Batch (without JDBC) |
|
|
JSON Starters |
||
GSON |
|
|
Jackson |
|
|
JSONB |
|
|
Messaging Starters |
||
ActiveMQ |
|
|
Artemis |
|
|
JMS |
|
|
RSocket |
|
|
Spring AMQP |
|
|
Spring Integration |
|
|
Spring for Apache Kafka |
|
|
Spring for Apache Pulsar |
|
|
Websockets |
|
|
Security Starters |
||
Spring Security |
|
|
Spring Security OAuth Authorization Server |
|
|
Spring Security OAuth Client |
|
|
Spring Security OAuth Resource Server |
|
|
Spring Security SAML |
|
|
Templating Starters |
||
Freemarker |
|
|
Groovy Templates |
|
|
Mustache |
|
|
Thymeleaf |
|
|
Production-Ready Starters |
||
Actuator |
|
|
OpenTelemetry |
|
|
Zipkin |
|
|
If you prefer to not use “starter” POMs, you can instead declare direct module dependencies:
| Technology | Main Dependency | Test Dependency |
|---|---|---|
Core Modules |
||
Cloud Foundry Support |
|
none |
Jakarta Validation |
|
none |
Kotlin Serialization |
|
none |
Reactor |
|
none |
Web Server Modules |
||
Jetty |
|
none |
Reactor Netty |
|
none |
Tomcat |
|
none |
Web Client Modules |
||
Spring’s Imperative |
|
|
Spring’s Reactive |
|
|
Web Modules |
||
Spring GraphQL |
|
|
Spring HATEOAS |
|
none |
Spring Session Data Redis |
|
none |
Spring Session JDBC |
|
none |
Spring Web MVC |
|
|
Spring WebFlux |
|
|
Spring Webservices |
|
|
Database Modules |
||
Cassandra |
|
none |
Couchbase |
|
none |
Elasticsearch |
|
none |
Flyway |
|
none |
JDBC |
|
|
jOOQ |
|
|
Liquibase |
|
none |
LDAP |
|
none |
MongoDB |
|
none |
Neo4J |
|
none |
R2DBC |
|
none |
Spring Data Modules |
||
Spring Data Cassandra |
|
|
Spring Data Couchbase |
|
|
Spring Data Elasticsearch |
|
|
Spring Data JDBC |
|
|
Spring Data JPA (using Hibernate) |
|
|
Spring Data LDAP |
|
|
Spring Data MongoDB |
|
|
Spring Data Neo4J |
|
|
Spring Data R2DBC |
|
|
Spring Data Redis |
|
|
Spring Data REST |
|
none |
IO Modules |
||
Hazelcast |
|
none |
|
none |
|
Quartz |
|
none |
SendGrid |
|
none |
Spring Caching Support |
|
|
Spring Batch (with JDBC) |
|
none |
Spring Batch (without JDBC) |
|
none |
JSON Modules |
||
GSON |
|
none |
Jackson |
|
none |
JSONB |
|
none |
Messaging Modules |
||
ActiveMQ |
|
none |
Artemis |
|
none |
JMS |
|
none |
RSocket |
|
|
Spring AMQP |
|
none |
Spring Integration |
|
none |
Spring for Apache Kafka |
|
none |
Spring for Apache Pulsar |
|
none |
Websockets |
|
none |
Security Modules |
||
Spring Security |
|
|
Spring Security OAuth Authorization Server |
|
none |
Spring Security OAuth Client |
|
none |
Spring Security OAuth Resource Server |
|
none |
Spring Security SAML |
|
none |
Templating Modules |
||
Freemarker |
|
none |
Groovy Templates |
|
none |
Mustache |
|
none |
Thymeleaf |
|
none |
Production-Ready Modules |
||
OpenTelemetry |
|
none |
Zipkin |
|
none |
If you’re upgrading an existing application and just want to get running quickly, you can use "Classic Starter POMs". The classic starters provide all modules, but exclude all of their transitive dependencies.
This provides a setup very similar to the previous generation of Spring Boot where all auto-configuration classes are available.
To use the classic starters, update your build as follows:
| Previous Starter | Classic Equivelent |
|---|---|
|
|
|
|
|
Note
|
We recommend that you eventually migrate your application away from using the classic starters. |
Serveral starter POMs have been renamed to provide better alignment with their corresponding module. The older starters remain, but should be considered deprecated and will be removed in a future release.
You should update your POM as follows:
| Deprecated Starter | Replacement |
|---|---|
|
|
|
|
|
|
|
|
|
|
The modularization also has an impact on the package structure of the project.
Each module now starts with a dedicated org.springframework.boot.<module>.
Depending on the scope of the module, it can contain APIs, auto-configurations, actuator-related support, etc.
Spring Boot 4.0 adds JSpecify nullability annotations. If you are using a null checker in your build or using Kotlin, this could lead to compilation failures because of now nullable or non-nullable types.
The default Charset for Logback has been harmonized with the behavior of Log4j2.
By default, the charset of a log file is UTF-8.
For console log, we use the Console#charset() if it is available, otherwise we use UTF-8.
The BootstrapRegistry and related classes have moved from org.springframework.boot to org.springframework.boot.bootstrap.
The EnvironmentPostProcessor interface has also moved from org.springframework.boot.env to org.springframework.boot.
If you have deep integrations with Spring Boot you may need to update both your code and your spring.factories files.
|
Note
|
The deprecated form of the EnvironmentPostProcessor is still available in Spring Boot 4.0, but will be removed at a later date.
|
The PropertyMapper class no longer calls adapter or predicate methods by default when the source value is null.
This has removed the need for the alwaysApplyingNotNull() method which has been removed.
If you need to perform a mapping even for null values you can use the new always() method.
For example,
map.from(source::method).to(destination::method);Will not call destination.method(…) if source.method() returns null.
Where as:
map.from(source::method).always().to(destination::method);Will call destination.method(null) if source.method() returns null.
If you use the PropertyMapper, you might want to review commit 239f384ac0 which shows how Spring Boot itself adapted to the new API.
Optional dependencies are no longer included in uber jars.
If you need them, you can use the configuration setting <includeOptional>true</includeOptional>.
To clarify the scope of spring-boot-starter-aop, it has been renamed to spring-boot-starter-aspectj.
If you have added the starter explicitly in your application, please review if you actually need it before using the replacement.
If your application does not use AspectJ, typically an annotation in the org.aspectj.lang.annotation package, you probably do not need the starter at all.
With the portfolio moving from Spring Retry to new core features of Spring Framework, dependency management for Spring Retry has been removed.
If your application still relies on Spring Retry, an explicit version is now required. Please consider moving your use of Spring Retry to Spring Framework.
Spring Authorization Server is now part of Spring Security. Explicit dependency management has been removed in favor of what’s already provided by Spring Security.
As a result, you can no longer override the version of Spring Authorization Server using the spring-authorization-server.version property.
If you need to do this going forward, use spring-security.version.
The classic uber-jar loader has been removed from this release. You should remove any loader implementation configuration from your build file.
For maven this means removing the following:
<loaderImplementation>CLASSIC</loaderImplementation>For Gradle, it will be lines similar to:
loaderImplementation = org.springframework.boot.loader.tools.LoaderImplementation.CLASSICSpring Boot now uses Jackson 3 as its preferred JSON library.
Jackson 3 uses new group IDs and package names with com.fasterxml.jackson becoming tools.jackson.
An exception to this is the jackson-annotations module which continues to use the com.fasterxml.jackson.core group ID and com.fasterxml.jackson.annotation package.
To learn more about the changes in Jackson 3, refer to the Jackson wiki.
For libraries that require Jackson 2, dependency management for Jackson 2 remains and a Jackson 2 ObjectMapper can be used alongside Boot’s auto-configuration for Jackson 3 if needed.
A number of classes have been renamed for consistency with Jackson 3:
-
JsonObjectSerializertoObjectValueSerializer. -
JsonValueDeserializertoObjectValueDeserializer. -
Jackson2ObjectMapperBuilderCustomizertoJsonMapperBuilderCustomizer.
@JsonComponent, @JsonMixin, and related supporting classes have been renamed to clarify that they are specific to Jackson and are not, necessarily, limited to JSON.
@JsonComponent is now @JacksonComponent and @JsonMixin is now @JacksonMixin.
Supporting classes have been renamed in the same manner replacing Json with Jackson.
The JSON-specific spring.jackson.read.* and spring.jackson.write.* properties have moved beneath spring.jackson.json.read and spring.jackson.json.write respectively.
To help with migrating from Jackson 2 to Jackson 3, the spring.jackson.use-jackson2-defaults property has been introduced.
When set to true, the auto-configured JsonMapper will have defaults that align as closely as possible with those of Jackson 2 in Spring Boot 3.x.
We strongly recommend trying to adopt Jackson 3 if at all possible, however, if you are unable to do so Spring Boot 4.0 also provides a spring-boot-jackson2 module.
This module ships in a deprecated form and will be removed in a future release.
It’s intended as a stop-gap for users that need more time to migrate to Jackson 3.
To use the Jackson 2 module you can add the following dependency to your Maven POM:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jackson2</artifactId>
</dependency>Or if you use Gradle:
implementation("org.springframework.boot:spring-boot-jackson2")Jackson 2 properties are available under spring.jackson2.
These are equivelent to the spring.jackson properties provided by Spring Boot 3.5.
Actuator endpoint parameters no longer can use org.springframework.lang.Nullable to declare that a parameter is optional.
If you are using this annotation, you should migrate to org.jspecify.annotations.Nullable.
If you use PathRequest#toStaticResources, please be advised that this release adds a location to /fonts/**.
With no change on your end, this path will have the same security settings as what you had previously configured.
If you don’t want that location to be included, you can exclude it like any other location:
pathRequest.toStaticResources().atCommonLocations().excluding(StaticResourceLocation.FONTS);The properties for Spring Session Data Redis have been renamed to reflect the dependencies on Spring Data Redis.
Properties that previously began with spring.session.redis now begin with spring.session.data.redis. Similarly, properties that previously began with spring.session.mongodb now begin with spring.session.data.mongodb.
This release deprecates Spring Boot’s HttpMessageConverters because Spring Framework improved the converter configuration in the traditional stack.
HttpMessageConverters had several issues, including the fact that it conflates client and server converters.
If your application declares a custom org.springframework.boot.http.converter.autoconfigure.HttpMessageConverters bean, this is still supported but the type itself is deprecated. Instead, your application can declare one or more ClientHttpMessageConvertersCustomizer and ServerHttpMessageConvertersCustomizer that will let you customize converters in a flexible way.
In response to changes in Elasticsearch, auto-configuration for the now-deprecated low-level Elasticsearch RestClient has been replaced with auto-configuration for the new Rest5Client.
If you were using Spring Boot’s RestClientBuilderCustomizer to customize the client, you must now use Rest5ClientBuilderCustomizer instead.
As part of the changes in Elasticsearch, the client code has been consolidated in the co.elastic.clients:elasticsearch-java module, including built-in sniffer support.
The org.elasticsearch.client:elasticsearch-rest-client and org.elasticsearch.client:elasticsearch-rest-client-sniffer modules are no longer required and Spring Boot’s dependency management for them has been removed.
Support for the higher-level ElasticsearchClient and the Spring Data Elasticsearch-provided ReactiveElasticsearchClient remains.
It has been updated to use the new low-level client.
A new spring-boot-persistence module has been created to house general persistence-related code and properties.
Users of @EntityScan should adapt their imports to org.springframework.boot.persistence.autoconfigure.EntityScan.
The spring.dao.exceptiontranslation.enabled property is no longer supported.
Please use spring.persistence.exceptiontranslation.enabled instead.
Some properties for configuring MongoDB have been updated so that their names reflect whether or not Spring Data MongoDB is required.
Many properties whose names previously began with spring.data.mongodb now begin with spring.mongodb:
-
spring.mongodb.additional-hosts -
spring.mongodb.authentication-database -
spring.mongodb.database -
spring.mongodb.host -
spring.mongodb.password -
spring.mongodb.port -
spring.mongodb.protocol -
spring.mongodb.replica-set-name -
spring.mongodb.representation.uuid -
spring.mongodb.ssl.bundle -
spring.mongodb.ssl.enabled -
spring.mongodb.uri -
spring.mongodb.username
Additionally, management-related properties have been renamed to use mongodb rather than mongo in their names:
-
management.health.mongodb.enabled -
management.metrics.mongodb.command.enabled -
management.metrics.mongodb.connectionpool.enabled
The following properties that require Spring Data MongoDB are unchanged:
-
spring.data.mongodb.auto-index-creation -
spring.data.mongodb.field-naming-strategy -
spring.data.mongodb.gridfs.bucket -
spring.data.mongodb.gridfs.database -
spring.data.mongodb.repositories.type
Spring Data MongoDB no longer provide defaults for UUID and BigInteger/BigDecimal representations.
This aligns with the driver recommendation to not favor a particular representation for UUID or BigInteger/BigDecimal to avoid representation changes caused by upgrades to a newer Spring Data version.
An explicit configuration is expected and the representations can be set using the spring.mongodb.representation.uuid and spring.data.mongodb.representation.big-decimal properties, respectively.
Spring Boot’s StreamBuilderFactoryBeanCustomizer has been removed in favor of Spring Kafka’s StreamsBuilderFactoryBeanConfigurer.
When migrating to the new configurer, be aware that it implements Ordered with a default value of 0.
Spring Kafka has moved its retry capabilities from Spring Retry to Spring Framework.
As a result, spring.kafka.retry.topic.backoff.random has been removed in favor of spring.kafka.retry.topic.backoff.jitter.
The latter provides more flexibility over the former. See the documentation for more details.
Spring AMQP has moved its retry capabilities from Spring Retry to Spring Framework.
Spring Boot offers a customization hook-point for retry features used by the RetryTemplate and message listeners.
To make it more explicit, two dedicated customizers have been introduced: RabbitTemplateRetrySettingsCustomizer, and RabbitListenerRetrySettingsCustomizer.
If you were using RabbitRetryTemplateCustomizer to customize the retry settings according to a target, you will need to migrate to either of those interfaces.
The MockitoTestExecutionListener deprecated in Spring Boot 3.4 has been removed in this release.
This might catch a few users out since the listener was only indirectly used and so deprecation warnings were easy to miss.
If you find your @Mock or @Captor annotated fields aren’t working as expected, you should use MockitoExtension from Mockito itself.
Using the @SpringBootTest annotation will no longer provide any MockMVC support.
If you want to use MockMVC in your tests you should now add an @AutoConfigureMockMvc annotation to the test class.
Using the @SpringBootTest annotation will no longer provide any WebClient or TestRestTemplate beans.
If you want to use a WebTestClient you should now add an @AutoConfigureWebTestClient annotation to the test class.
If you want to use a TestRestTemplate you should add an @AutoConfigureTestRestTemplate annotation to the test class.
In addition, you might want to consider replacing any use of TestRestTemplate with the new RestTestClient class.
To configure this, add an @AutoConfigureRestTestClient annotation to the test class.
In the event of a compilation failure in your tests for TestRestTemplate, add a test-scoped dependency on org.springframework.boot:spring-boot-resttestclient.
The package holding that class will also need to be updated to org.springframework.boot.resttestclient.TestRestTemplate.
The @PropertyMapping annotation has been relocated from the org.springframework.boot.test.autoconfigure.properties package to org.springframework.boot.test.context.
In addition, the skip attribute now takes org.springframework.boot.test.context.PropertyMapping.Skip rather than org.springframework.boot.test.autoconfigure.properties.Skip.