Upgrading from Spring Boot 3 to Spring Boot 4 - Minor issues
A quick Spring Boot 4 migration diary: moved packages, split deps, and stricter tests.
With the new release of Spring AI 2.0 I have no more excuse to migrate one of my biggest pet projects from Spring Boot 3.5.0 + AI 1.0 to Spring Boot 4.1.0 + AI 2.0.
The base framework changes from Spring 6.2 to Spring framework 7.0.
Every major update brings some benefits and potential issues, with this migration from SB 3.5 to 4 I encountered some minor issues. My pet project is not an enterprise application, the security level is not complex like a Spring Security + SSO with MS Entra + external access that usually creates a lot of headaches, but the application is quite big and comparable to some enterprise applications.
The official migration guide can be found here:
List of the issues and remediations
Swagger dependency
I use a lot of Swagger annotations to document the API, these are not automatically imported anymore. To avoid a build error like io.swagger.v3.oas.annotations.media.Schema not found you need to import the library manually in your pom.xml
<!-- OpenAPI / Swagger annotations used by ActivityRunDto -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>3.0.3</version>
</dependency>AI tool import
The package org.springframework.ai.tool.annotation does not exist the dependency needs to be imported explicitly
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-model</artifactId>
</dependency>Ai Client
Another dependency has been moved out: package org.springframework.ai.chat.client does not exist, it can be easily fixed:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-client-chat</artifactId>
</dependency>Security Auto Configuration:
The build had failed with this error: package org.springframework.boot.autoconfigure.security.servlet does not exist this is not a major issue, in fact I was excluding this Spring feature : @SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class}) . With the new version is enough to remove the exclusion.
UriComponentsBuilder
Cannot find symbol fromHttpUrl

This problem is self-explanatory and a quick refactoring solved the problem. Spring simply changed the method name from fromHttpUrl to fromUriString
RestResponseException
Cannot find symbol getRawStatusCode
Another minor issue, a quick refactoring to getStatusCode fixed the issue.

@WebMvcTest
Yes I have tests in pet projects too, usually is the best method to learn the intricacies of the Spring framework.
Errors: package org.springframework.boot.test.autoconfigure.web.servlet does not exist. @WebMvcTestand @AutoConfigureMockMvcare gone, but luckily not too distant. The annotations moved from
org.springframework.boot.test.autoconfigure.web.servletto
org.springframework.boot.webmvc.test.autoconfigurethis requires to import into the pom:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>This required an 'Invalidate Caches ...' in my IntelliJ instance to work correctly ... ☹️ ... still nothing compared with a project using Gradle.
WebMvcTest ... part 2
Spring Boot 4 is more strict in some checks and many tests failed, requiring some code rewrite.StructuredAuthenticationEntryPoint needs a real Jackson bean to render the 401 JSON body, @EnableCaching means a CacheManager must exist in the test context.
Cache
A component required a bean of type 'org.springframework.cache.CacheManager' that could not be found.
My project is using a backend cache to improve the performance of the recurring requests. Spring Boot 4 is more modular and moved the CacheManagerin a dedicated starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>Jackson 2 to Jackson 3 upgrade
Spring upgraded the Jackson dependency, this created some issues because I had a direct import of jackson-databindin the pom. Spring was expecting Jackson 3 objects but was receiving still objects with the old version.
I had to remove the explicit dependency:
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>... and replace import com.fasterxml.jackson.databind.ObjectMapper;with import tools.jackson.databind.ObjectMapper;
Next step, code upgrade
The upgrade adds more features to the AI library and allows to introduce @JSpecify for the null management. I'll write a dedicated post with the changes.