Spring Boot 2 to Spring Boot 3 Migration Tutorial
Watch on YouTubeSpring Boot 2 to 3 Migration Guide
1. Java Version Requirement

| Spring Boot 2 | Spring Boot 3 |
|---|---|
| Supports Java 8, 11, or 17 depending on the version. | Requires Java 17 minimum. |
| Older projects can run on Java 8 or 11. | Uses Java 17 features and modern JVM support. |
Configure Java 17 in Maven, CI, Docker, and production:
<properties>
<java.version>17</java.version>
</properties>
2. Jakarta EE Migration

This is the biggest change. Spring Boot 2 uses javax.* packages from Java EE, while Spring Boot 3 uses jakarta.* packages from Jakarta EE 10.
// Spring Boot 2
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.validation.constraints.NotBlank;
// Spring Boot 3
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotBlank;
| Spring Boot 2 | Spring Boot 3 |
|---|---|
javax.persistence.* | jakarta.persistence.* |
javax.validation.* | jakarta.validation.* |
javax.servlet.* | jakarta.servlet.* |
javax.annotation.* | jakarta.annotation.* |
3. Spring Framework Version

| Spring Boot 2 | Spring Boot 3 |
|---|---|
| Uses Spring Framework 5. | Uses Spring Framework 6. |
| Supports older Java versions. | Built for Java 17 and newer. |
| Less native image focus. | Better AOT and native image support. |
4. Hibernate Version

| Spring Boot 2 | Spring Boot 3 |
|---|---|
Hibernate 5.x and javax.persistence. | Hibernate 6.x and jakarta.persistence. |
| Older query handling. | Improved SQL generation and type system. |
Update entities and review queries, dialects, identifiers, and custom Hibernate types:
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Double salary;
}
5. Security Changes

Spring Boot 2 commonly used WebSecurityConfigurerAdapter. In Spring Boot 3, it is removed and security is configured with a SecurityFilterChain bean.
// Spring Boot 2
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated();
}
}
// Spring Boot 3
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/public/**").permitAll()
.anyRequest().authenticated());
return http.build();
}
}
Important changes: authorizeRequests() becomes authorizeHttpRequests(); antMatchers() becomes requestMatchers(); and WebSecurityConfigurerAdapter is removed.
6. Actuator Endpoint Changes

Spring Boot 3 improves Actuator metrics and observability support through Micrometer. Add the Actuator starter and expose only the endpoints you need.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management.endpoints.web.exposure.include=health,info,metrics,prometheus
7. Observability and Tracing

Spring Boot 2 applications often use Spring Cloud Sleuth. Spring Boot 3 uses Micrometer Tracing and the Micrometer Observation API.
| Spring Boot 2 | Spring Boot 3 |
|---|---|
| Spring Cloud Sleuth. | Micrometer Tracing. |
| Sleuth-managed trace and span IDs. | Micrometer Observation API. |
| Older tracing model. | Modern observability model. |
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
8. Native Image and AOT Support

| Spring Boot 2 | Spring Boot 3 |
|---|---|
| Limited native support. | Strong AOT and GraalVM native support. |
| Slower startup and higher memory usage compared with native. | Faster startup and lower memory usage are possible. |
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
</plugin>
Spring Boot 3 native images are useful for serverless applications, AWS Lambda, Kubernetes scale-to-zero applications, and fast-startup microservices.
9. Configuration Property Binding
Spring Boot 3 has stricter configuration binding. Invalid or mismatched configuration can fail faster, helping catch issues early.
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private int timeout;
// getters and setters
}
app.name=order-service
app.timeout=30
10. REST API Example Difference
The controller structure can remain the same; the key migration is the validation import.
// Spring Boot 2
import javax.validation.Valid;
// Spring Boot 3
import jakarta.validation.Valid;
@RestController
@RequestMapping("/employees")
public class EmployeeController {
@PostMapping
public Employee createEmployee(@Valid @RequestBody Employee employee) {
return employee;
}
}
11. Servlet API Change
// Spring Boot 2
import javax.servlet.http.HttpServletRequest;
// Spring Boot 3
import jakarta.servlet.http.HttpServletRequest;
Example interceptor in Spring Boot 3:
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
public class RequestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String correlationId = request.getHeader("X-Correlation-ID");
System.out.println("Correlation ID: " + correlationId);
return true;
}
}
12. Dependency Compatibility
Spring Boot 3 requires compatible third-party libraries. Old libraries that still depend on javax.* may fail at startup or runtime.
ClassNotFoundException: javax.servlet.FilterSolution: upgrade the dependency to a version that supports jakarta.*, then run the dependency tree and application startup tests again.
13. Testing Changes
Spring Boot 3 uses newer versions of JUnit, Mockito, Spring Test, and Jakarta APIs. Run unit, slice, integration, security, persistence, and full application startup tests.
@SpringBootTest
class EmployeeServiceTest {
@Autowired
private EmployeeService employeeService;
@Test
void testCreateEmployee() {
Employee employee = new Employee();
employee.setName("Anand");
Employee saved = employeeService.save(employee);
assertNotNull(saved);
}
}
Migration Checklist: Spring Boot 2 to Spring Boot 3
- Upgrade Java version to 17.
- Upgrade Spring Boot version to 3.x.
- Replace
javax.*imports withjakarta.*. - Upgrade Spring Security configuration.
- Replace
WebSecurityConfigurerAdapter. - Upgrade Hibernate and JPA dependencies.
- Update third-party libraries.
- Check Actuator and tracing configuration.
- Replace Spring Cloud Sleuth with Micrometer Tracing.
- Run all unit and integration tests.
- Fix deprecated APIs.
- Validate application properties.
- Test Docker and Kubernetes deployment.
Spring Boot 2 to 3 Migration FAQs
What is the biggest Spring Boot 2 to 3 change?
The Jakarta EE namespace migration from javax.* to jakarta.*, together with the Java 17 requirement, affects application code and dependencies.
Can I migrate directly to Spring Boot 3?
Use the latest suitable Spring Boot 2.7 release first, resolve deprecations, then upgrade the parent or BOM to Spring Boot 3.
Why does a third-party library fail after migration?
It may still reference Java EE javax.* classes. Upgrade it to a Jakarta-compatible version instead of changing third-party code blindly.
Continue learning
