// JAVA / SPRING BOOT / MIGRATION

Spring Boot 2.x to 3.x / Java 21 Migration: 8 Breaking Changes and the Production Verification Checklist

📅 April 24, 2025 ⏱ ~14 min read ✍ DataOne Tech Editorial
Spring Boot 2.x to 3.x / Java 21 Migration: 8 Breaking Changes and the Production Verification Checklist

Spring Boot 2.7 reached end-of-life in November 2023. Running enterprise systems without security patches is an unacceptable risk position for financial services operating under FSA supervision or ISMAP compliance. Spring Boot 2.x to 3.x is a migration, not a version bump. DataOne has completed this migration on multiple financial system projects. Here is the complete technical guide.

The Correct Migration Path: Never Skip Intermediate Steps

Step-by-step migration path:
1. Java 11 + Spring Boot 2.5.x → Java 11 + Spring Boot 2.7.x (resolve all deprecation warnings first)
2. Java 11 + Spring Boot 2.7.x → Java 17 + Spring Boot 2.7.x (JVM only)
3. Java 17 + Spring Boot 2.7.x → Java 17 + Spring Boot 3.x (framework migration)
4. Java 17 + Spring Boot 3.x → Java 21 + Spring Boot 3.2+ (Virtual Threads)
Skipping steps makes problem isolation extremely difficult.

Breaking Change 1: javax.* to jakarta.* Namespace (Largest Surface Area)

// Required import changes (IDE global replace works, but verify library versions) javax.persistence.* → jakarta.persistence.* javax.validation.* → jakarta.validation.* javax.servlet.* → jakarta.servlet.* javax.transaction.* → jakarta.transaction.* // Key library version requirements for jakarta compatibility: // Hibernate ORM: 6.x+ (4.x/5.x do NOT support jakarta) // QueryDSL: 5.0.0+ (requires jpa-apt jakarta edition) // SpringDoc OpenAPI: 2.x (springfox is abandoned, jakarta-incompatible) // MyBatis: 3.5.11+

Breaking Change 2: SecurityConfig Complete Rewrite

// Spring Boot 3.x ONLY — WebSecurityConfigurerAdapter is removed @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth .requestMatchers("/public/**").permitAll() .anyRequest().authenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); return http.build(); } }
Financial System Security Warning: The change from antMatchers() to requestMatchers() involves subtly different matching rules. A difference in trailing slash handling can cause unintended access grants. After migration, perform penetration testing equivalent security verification. Do not assume the migration was safe without explicit validation.

Java 21 Virtual Threads: Production ATM API Results

3.2x
Throughput increase
(1000 concurrent)
-68%
Memory usage
reduction
1 line
Spring Boot 3.2
enablement
// spring.threads.virtual.enabled=true is all that is needed in Spring Boot 3.2 // BUT: check for Pinning before production deployment // Run with: -Djdk.tracePinnedThreads=full and load test // Any output indicates Pinning — fix by replacing synchronized with ReentrantLock
DataOne's migration timeline across multiple financial projects: 3-5 days for mid-size applications (10-50k lines). Largest cost driver: third-party library jakarta compatibility verification. Build an inventory of all direct and transitive dependencies and their jakarta support status before starting.
⚠ Disclaimer: This article is for informational purposes only and does not constitute a guarantee or recommendation of any specific system, product, or service. Technical information is current as of the time of writing and may change due to software updates or regulatory changes. Actual implementation and design decisions should be made based on your organization's requirements, environment, and risk tolerance, with guidance from qualified professionals.
Talk to DataOne
Technical challenges, hiring, or system development — we are here to help.