When Spring Boot 4 was announced, I did what I always do: dive into the release notes and assess what it means for our services. After the successful upgrade from Spring Boot 2.7 to 3.2 last year, I’m more aware of how disruptive major version upgrades can be. This time, I spent a few hours analyzing our main library repository to understand what changes are coming and, more importantly, which ones will require the most attention from our teams.
This is not the upgrade itself, just a preliminary analysis. My goal is to identify the biggest pain points early so we can plan better and avoid surprises once we start. I’ll focus on the changes that will have the most impact on our codebase and deployment process, not every detail in the release notes.
The one change that stands out, and frankly worries me, is Jackson 3. It’s a major version upgrade that will touch almost every service we have.
Jackson 3 Migration — The Big Challenge
The biggest and riskiest change is the upgrade of Jackson from 2.x to 3.x. If you’ve read my post about what we encountered upgrading from Spring Boot 3.2.5 to 3.3.1, you already know how disruptive Jackson changes can be. This upgrade is on a much larger scale.
Jackson is everywhere in our codebase. It handles all JSON serialization and deserialization for our APIs. This major version upgrade brings breaking changes that will ripple through our services and dependencies. What concerns me most is that Jackson is deeply nested in external libraries we use. We need to ensure all our dependencies are compatible with Jackson 3.x, which might require upgrading them too, creating a domino effect.
Package Name Changes
The package names have moved from com.fasterxml.jackson to tools.jackson. This is the biggest impact because we’ll need to update imports everywhere in our codebase. I’m also concerned with external dependencies that might still be using the old package names. That could cause classpath conflicts that are hard to debug.
Built-in Java Modules
Good news is that in Jackson 3.x, some modules are now built-in and we don’t need separate dependencies anymore. This actually helps offset some of the pain from the migration:
jackson-datatype-jsr310(for Java time types like LocalDateTime, ZonedDateTime) - now automaticjackson-datatype-jdk8(for Optional, OptionalInt, etc.) - now automaticjackson-module-parameter-names(auto-detection of constructor parameters) - now automatic
We can remove these dependencies once we migrate, which will simplify our dependency trees a bit. It’s a small win in what will otherwise be a large undertaking.
API Changes
There are several API changes that will require code updates:
ValueDeserializerchanged toJsonDeserializer. This impacts any custom deserializers we have.ObjectMappertoJsonMapper. Any custom ObjectMapper configurations need review.- Date/time serialization formats might differ, which means we need to test our REST APIs carefully
These changes aren’t just about updating method names. They can cause subtle bugs in serialization logic that might only surface under specific conditions. That’s why comprehensive testing will be essential.
Java 17 Baseline
We’re already running Java 21 across our platform, so this requirement doesn’t affect us directly. However, it’s worth noting that Spring 4 will drop support for Java versions below 17. If we have any legacy services still on Java 11, they’ll need to be upgraded first before attempting a Spring Boot 4 migration.
I don’t expect we have any services that old, but it’s worth auditing.
Tomcat 11 Upgrade
Tomcat is being upgraded from version 10 to version 11, which brings changes to the servlet API. Our REST endpoints and web filters could be affected if they interact with the servlet API directly.
Most of the changes should be handled automatically by Spring, but web functionality is critical and hard to test comprehensively in integration tests. This is another area where we’ll need thorough testing to ensure nothing breaks silently in production.
Other Dependency Updates
Besides Jackson and Tomcat, we’re also updating several other dependencies:
- Flyway: 10.20.1 → 11.11.0. This is our database migration tool. We’ll need to ensure our migration scripts still work and check if there are any behavior changes.
- Mockito: 5.14.2 → 5.20.0. Used in testing, should be mostly compatible but we should verify our test fixtures.
- Commons Lang3: 3.18.0 → 3.19.0. Utility library, low risk.
- Jakarta Persistence API: 3.1.0 → 3.2.0. Used for JPA and ORM operations. We should test our entity mappings to ensure they still work. If you have Spring Batch jobs, the Backwards compatible migration for Spring Batch 5 post covers related Jakarta Persistence changes.
- Jakarta XML Bind: 4.0.2. Used for XML processing in some of our bank connectors. This change could be risky if we’re doing complex XML transformations.
The danger with dependency updates is that they often interact with each other in unexpected ways. A minor version bump in one library can expose a bug in another that was previously masked.
Configuration Changes
There are some property changes we’ll need to review in our configuration files. Fortunately, I haven’t found anything critically breaking so far.
If we encounter any of these old properties in our application files, they’ll need updating:
spring.dao.exceptiontranslation.enabled→spring.persistence.exceptiontranslation.enabledmanagement.tracing.enabled→management.tracing.export.enabled
From what I’ve seen, our current configuration is already using the correct property names, so this might not be a major blocker. Still, we should audit all our property files across services to be sure. If your services use observability or tracing, you might also want to check out my post on getting observability working with Spring WebFlux as a reference for how these tracing configurations interact with reactive code.
What’s Next
This upgrade will be complex because of Jackson, but I’m confident we can handle it. We have good test coverage across unit, integration, and end-to-end tests, which will catch most issues before they reach production. As I learned from my previous Spring Boot upgrade, the key is keeping changes minimal and testing essential. We also have solid monitoring and SLOs in place, so if something does slip through, we’ll catch it quickly.
The key is to be methodical: update dependencies carefully, test thoroughly at each step, and be ready to troubleshoot when edge cases inevitably appear. Based on what I learned from the previous upgrade, I know that technical problems always have solutions. They just sometimes take longer to find than expected.
I’ll post more detailed migration guides as we start the upgrade process and encounter specific challenges. For now, this analysis is our roadmap for what to prepare for.
Cheers.