Spring Framework is a popular open source enterprise framework for creating standalone, production-grade applications that run on the Java Virtual Machine (JVM). And Spring Boot is a tool that makes it faster and easier to develop web applications and microservices using the Spring framework. As Spring Boot continues to evolve, developers must keep up with the latest upgrades and changes.
Recently, Spring Boot announced the release of version 3.2.x, which brings a number of new features, bug fixes, and enhancements. This is a good news given that support for Spring Boot 2.7.x version has ended on November 18, 2023. Very important and mandatory attention is used to upgrade Spring Boot applications to the latest 3.x version.
Therefore, in this article, we will discuss how to migrate from Spring Boot 2.x to 3.x, as well as the advantages of upgrading and the potential difficulties developers may encounter during the process.
Contents
- 1 Upgrade guide
- 1.1 1. Upgrade JDK 17
- 1.2 2. Upgrade to Spring Boot 3
- 1.3 3. Configuration attribute migration
- 1.4 4. Upgrade to Jakarta EE
- 1.5 5. Adjust @ConstructorBindingannotations
- 1.6 6. URL matching changes for Spring MVC and WebFlux
- 1.7 7. Apache HttpClient in RestTemplate
- 1.8 8. Upgrade Spring Security
- 1.9 9. Spring Kafka template upgrade
- 1.10 10. Spring Doc OpenAPI upgrade
Upgrade guide
1. Upgrade JDK 17
Spring Boot 3.0 requires Java 17 as a minimum version.
If you are currently using Java 8 or Java 11, you need to upgrade your JDK before migrating to Spring Boot.
2. Upgrade to Spring Boot 3
After reviewing the status of the project and its dependencies, upgrade to the latest maintenance release of Spring Boot 3.0.
We will use Spring Boot 3.2.0 for the upgrade.
Open the project’s pom.xml
and update the Spring Boot version as shown below.
< parent > < groupId > org.springframework.boot </ groupId > < artifactId > spring-boot-starter-parent </ artifactId > < version > 3.2.0 </ version > </ parent >
3. Configuration attribute migration
In Spring Boot 3.0, some configuration properties were renamed/removed and developers need to update them accordingly application.properties/application.yml
.
To help you achieve this, Spring Boot provides a spring-boot-properties-migrator
module.
pom.xml
We can add the migrator by adding the following to Maven :
< dependency > < groupId > org.springframework.boot </ groupId > < artifactId > spring-boot-properties-migrator </ artifactId > < scope > runtime </ scope > </ dependency >
4. Upgrade to Jakarta EE
Since Java EE has been changed to Jakarta EE, all dependency APIs of Spring Boot 3.x have also been upgraded from Java EE to Jakarta EE.
Simply put, you need to javax
replace all imports with jakarta
. details as follows:
javax .persistence.* -> jakarta.persistence.* javax .validation.* -> jakarta.validation.* javax .servlet.* -> jakarta.servlet.* javax .annotation.* -> jakarta.annotation.* javax . transaction.* -> jakarta.transaction.*
5. Adjust @ConstructorBinding
annotations
@ConstructorBinding
It is no longer needed at @ConfigurationProperties
the type level of the class and should be removed.
When a class or record has multiple constructors, it can still be used on the constructor to indicate which constructor should be used for property binding.
6. URL matching changes for Spring MVC and WebFlux
Starting with Spring Framework 6.0, the trailing slash matching configuration option has been deprecated and its default value is set to false.
This means that previously, the following controller would match GET /health
andGET /health/
@RestController public class HealthController { @GetMapping("/health") public String health () { return "Application is Working" ; } } @RestController public class HealthController { @GetMapping("/health") public Mono<String> health () { return Mono.just( "Application is Working" ); } }
7. Apache HttpClient in RestTemplate
Support for Apache HttpClient was removed in Spring Framework 6.0 and is now org.apache.httpcomponents.client5:httpclient5
replaced by (note: this dependency has a different groupId).
If you notice problems with HTTP client behavior, you RestTemplate
may fall back to the JDK client.
org.apache.httpcomponents:httpclient
Can be transitively passed by other dependencies, so your application may depend on this dependency without declaring it.
Here is an example after migration RestTemplate
:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate () { final SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactoryBuilder.create() .build(); final PoolingHttpClientConnectionManager manager = PoolingHttpClientConnectionManagerBuilder.create() .setSSLSocketFactory(sslConnectionSocketFactory) .build(); final CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(manager) .build(); final HttpComponentsClientHttpRequestFactory componentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory (); componentsClientHttpRequestFactory.setHttpClient(closeableHttpClient); final RestTemplate restTemplate = new RestTemplate (componentsClientHttpRequestFactory); return restTemplate; } }
8. Upgrade Spring Security
Spring Boot 3.0 has been upgraded to Spring Security 6.0.
Therefore, WebSecurityConfigurerAdapter
it has been deprecated. Spring encourages users to move to component-based security configuration.
To demonstrate the new configuration style, we use the Spring Security lambda DSL and methods HttpSecurity#authorizeHttpRequests
to define our authorization rules.
Here is WebSecurityConfigurerAdapter
an example configuration using HTTP Basic, which secures all endpoints:
@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure (HttpSecurity http) throws Exception { http .authorizeHttpRequests((authz) -> authz .anyRequest().authenticated() ) .httpBasic(withDefaults()); } }
Going forward, the recommended approach is to register a SecurityFilterChain
bean:
@Configuration public class SecurityConfiguration { @Bean public SecurityFilterChain filterChain (HttpSecurity http) throws Exception { http .authorizeHttpRequests((authz) -> authz .anyRequest().authenticated() ) .httpBasic(withDefaults()); return http.build(); } }
9. Spring Kafka template upgrade
KafkaTemplate
The method now returns CompleteableFuture
instead ListenableFuture
, which has been deprecated.
ListenableFuture
Kafka template in Spring Boot 2.x with :
private RoutingKafkaTemplate routingKafkaTemplate; public void send () { ListenableFuture<SendResult<Object,Object>> future = routingKafkaTemplate.send( "Message" , "topic" ); future.addCallback( new ListenableFutureCallback <>() { @Override public void onFailure (Throwable ex) { log.error(ex); } @Override public void onSuccess (SendResult<Object, Object> result) { log.info( "success" ); } }); }
CompletableFuture
Kafka template in Spring Boot 3.x with :
private RoutingKafkaTemplate routingKafkaTemplate; public void send () { CompletableFuture<SendResult<Object, Object>> future = routingKafkaTemplate.send( "Message" , "topic" ); future.thenAccept(log::info) .exceptionally(exception -> { log.error(exception); return null ; }); }
10. Spring Doc OpenAPI upgrade
springdoc-openapi
Used to automatically generate API documentation for Spring Boot projects.
springdoc-openapi
works by inspecting the application at runtime to infer API semantics based on spring configuration, class structure, and various annotations.
For spring-boot 3 support, make sure to use springdoc-openapi v2.
Spring Doc OpenAPI upgrade of WebMVC project
For WebMVC projects, you need to pom.xml
include the following dependencies in the . file.
< dependency > < groupId > org.springdoc </ groupId > < artifactId > springdoc-openapi-starter-webmvc-ui </ artifactId > < version > 2.3.0 </ version > </ dependency >
Spring Doc OpenAPI upgrade for WebFlux project
For WebFlux projects, you need to pom.xml
include the following dependencies in the . file.
< dependency > < groupId > org.springdoc </ groupId > < artifactId > springdoc-openapi-starter-webflux-ui </ artifactId > < version > 2.3.0 </ version > </ dependency >