Spring Boot 2.7 to 3.3 on a European bank project: what actually broke (it was not just javax)
6 weeks, 41 modules, 1 very nervous client, and a checklist you can steal
Contents
Our client, a mid-size bank in Europe, got a finding from their security team: Spring Boot 2.7, open source support ended in November 2023, upgrade. So our team of 7 in Pune got the job. 41 Maven modules, Oracle database, a partner integration in Frankfurt, and a change advisory board that meets once a week. Here is what broke, in the order we found it.
0. Java 17 first, separately
Boot 3 needs Java 17. We moved from 11 to 17 while still on Boot 2.7, as its own release. If something breaks you know whether it was the JDK or Spring. One variable at a time, bhau.
1. javax to jakarta
The famous one, and honestly the easiest, because OpenRewrite does it for you:
mvn -U org.openrewrite.maven:rewrite-maven-plugin:run \
-Drewrite.recipeArtifactCoordinates=org.openrewrite.recipe:rewrite-spring:RELEASE \
-Drewrite.activeRecipes=org.openrewrite.java.spring.boot3.UpgradeSpringBoot_3_3
It rewrote imports, properties and dependency versions across all modules. Review the diff, but it saved us maybe two weeks.
2. Spring Security 6
WebSecurityConfigurerAdapter is gone. antMatchers is gone. Everything is a SecurityFilterChain bean with the lambda DSL:
@Bean
SecurityFilterChain api(HttpSecurity http) throws Exception {
return http
.securityMatcher("/api/**")
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/health").permitAll()
.requestMatchers(HttpMethod.POST, "/api/payments/**").hasRole("PAYMENTS")
.anyRequest().authenticated())
.oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))
.csrf(csrf -> csrf.disable())
.build();
}
We had 6 security configs across modules. Rewriting them was easy. Proving to the bank's security team that the new rules were identical to the old ones took longer than the code. We wrote a test per endpoint per role. Worth it.
3. Trailing slash, the one that reached production
Spring Framework 6 no longer matches /api/accounts/ to a mapping for /api/accounts. Trailing slash matching is off by default. Our tests all called the URLs without a slash. The partner in Frankfurt called them with a slash. First morning after go-live, 404s. We added explicit mappings for the partner routes the same day and a redirect filter later. Read the migration guide fully, not only the first page. Lesson learnt the hard way.
4. Hibernate 6 sequences, the one we caught in UAT
With GenerationType.AUTO, Hibernate 6 expects a sequence per entity (account_seq and so on) instead of the single hibernate_sequence. On Oracle: ORA-02289: sequence does not exist on every insert. One property brings back the old behaviour while you plan a proper fix:
spring.jpa.properties.hibernate.id.db_structure_naming_strategy=legacy
Also check allocationSize against the INCREMENT BY of your existing sequences. A mismatch there gives you duplicate keys or startup errors depending on the version.
5. Tracing
Spring Cloud Sleuth does not support Boot 3. Micrometer Tracing replaces it. The log correlation fields changed format and the bank's Splunk dashboards went blank. Nobody's code broke, but the ops team's mood did. Tell your ops team before, not after.
6. The helper nobody uses
Add spring-boot-properties-migrator as a runtime dependency during the upgrade. On startup it prints every property that was renamed or removed. Remove it again after, people forget it in production.
Numbers
6 weeks, 41 modules, 1 production issue (trailing slash, fixed same day), 1 UAT issue (sequences). The client sent a thank you mail to our onsite coordinator, which in service company terms is basically a national award.
And no, this is not "just a config change". It is a config change in 41 modules with a CAB, a security sign-off and a partner in another country. Koi doubt ho toh comment karo, as Rohit bhai says.
Written by
Omkar Joshi
Java/Spring dev, 6 yrs, service company, Pune. Yes I write real code. Yes it goes to production. Yes for a bank in Europe. No I will not apologise.
Get the best of #legacy-code-archaeology weekly
One email each Monday with the most useful posts. No spam; unsubscribe in one click.
Comments
Sign in to join the conversation.
Sign in to comment