
The Journey from Java 8 to 17
Upgrading the Direct Carrier Billing Platform from JDK 8 + Spring Boot 2 to JDK 17 + Spring Boot 3, with AI-assisted tests as a safety net
To fix vulnerabilities reported by Checkmarx and WhiteSource, the Direct Carrier Billing Platform was upgraded from JDK 8 + Spring Boot 2 to JDK 17 + Spring Boot 3 in one step. Before upgrading, AI was used to fill in unit tests, to list every API and to write test cases for each. AI generated automated test scripts for APIs that can be called repeatedly or rolled back, manual testing covered the APIs that cannot be rolled back, and the regression test passed in full after release.
- Role
- Requirements Analysis, Architecture Design, Development, Testing
- Tech
- JDK 17Spring Boot 3Spring SecurityJakarta EEDockerCheckmarxWhiteSourceJUnitAI-assisted Testing
The Problem
The Direct Carrier Billing Platform connects several billing systems and exposes APIs to external vendors. Checkmarx and WhiteSource scans kept listing vulnerabilities in older dependencies, and a real fix meant moving to versions that are still supported.
This was a major-version upgrade touching the JDK, Spring Boot and Spring Security. Because external vendors call the platform, behaviour must not change after the upgrade, so the tests were built first and the upgrade came after.
What Had to Change
The upgrade required three main kinds of change:
- javax.* → jakarta.*
- Spring Boot 3 is built on Jakarta EE, so javax packages across the code had to be moved to jakarta.
- Spring Security configuration
- Spring Security 6 removes WebSecurityConfigurerAdapter in favour of a SecurityFilterChain bean, and the authorization syntax changes with it.
- Dockerfile
- The base image moves to JDK 17, with the matching build and start-up settings adjusted.
Rewrite Example
Taking the Spring Security configuration as an example, the old style extends WebSecurityConfigurerAdapter, the new style registers a SecurityFilterChain, and the packages move from javax to jakarta.
Spring Boot 2
import javax.servlet.http.HttpServletRequest;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated();
}
}Spring Boot 3
import jakarta.servlet.http.HttpServletRequest;
@Configuration
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated());
return http.build();
}
}Illustrative code. Paths and class names are made up.
Testing Strategy
The risk in an upgrade is behaviour changing silently. Tests were therefore built first as a safety net, then the JDK and Spring Boot were upgraded together, with AI used to cut down the time spent writing tests.
- 01
Fill in unit tests
AI first wrote unit tests for the existing code, so logic changes after the upgrade would surface quickly.
- 02
List every API
AI listed all of the system's APIs and wrote test cases for each one.
- 03
Automated scripts
For APIs that can be called repeatedly or rolled back, AI generated automated test scripts.
- 04
Manual testing
APIs that cannot be rolled back are not suited to repeated automated runs, so they were covered by manual testing.
- 05
Upgrade together
The JDK and Spring Boot were upgraded at the same time, with the three kinds of change above, and tests confirmed the behaviour was unchanged.
- 06
Post-release check
A regression test was run after release and passed in full.
Outcome
- >Completed and released the JDK 17 + Spring Boot 3 upgrade, and the post-release regression test passed in full.
- >Moving to supported versions was the main way of fixing the Checkmarx and WhiteSource findings.
- >Left behind unit tests and automated API test scripts that can be reused in future upgrades and maintenance.