Spring Boot 2 to Spring Boot 3 Migration Tutorial

Watch on YouTube

Spring Boot 2 to 3 Migration Guide

Migration overview: Spring Boot 3 requires Java 17, Spring Framework 6, Jakarta EE namespaces, compatible dependencies, and updated security and observability configuration.

1. Java Version Requirement

Spring Boot 2 and Spring Boot 3 Java version comparison
Java version support comparison
Spring Boot 2Spring 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

Spring Boot 2 javax and Spring Boot 3 jakarta package comparison
Jakarta EE namespace 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 2Spring Boot 3
javax.persistence.*jakarta.persistence.*
javax.validation.*jakarta.validation.*
javax.servlet.*jakarta.servlet.*
javax.annotation.*jakarta.annotation.*

3. Spring Framework Version

Spring Framework 5 and Spring Framework 6 comparison for Spring Boot migration
Spring Framework 5 to 6 upgrade
Spring Boot 2Spring 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

Hibernate 5 and Hibernate 6 comparison for Spring Boot 2 to 3 migration
Hibernate and JPA compatibility changes
Spring Boot 2Spring 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 Security configuration changes from Spring Boot 2 to Spring Boot 3
Spring Security configuration 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 Actuator and metrics comparison for Spring Boot 2 to 3
Actuator and metrics improvements

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 Cloud Sleuth and Micrometer Tracing comparison for Spring Boot migration
Tracing and observability migration

Spring Boot 2 applications often use Spring Cloud Sleuth. Spring Boot 3 uses Micrometer Tracing and the Micrometer Observation API.

Spring Boot 2Spring 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 and Spring Boot 3 native image and AOT support comparison
Native image and AOT support
Spring Boot 2Spring 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.

Common error: ClassNotFoundException: javax.servlet.Filter

Solution: 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

  1. Upgrade Java version to 17.
  2. Upgrade Spring Boot version to 3.x.
  3. Replace javax.* imports with jakarta.*.
  4. Upgrade Spring Security configuration.
  5. Replace WebSecurityConfigurerAdapter.
  6. Upgrade Hibernate and JPA dependencies.
  7. Update third-party libraries.
  8. Check Actuator and tracing configuration.
  9. Replace Spring Cloud Sleuth with Micrometer Tracing.
  10. Run all unit and integration tests.
  11. Fix deprecated APIs.
  12. Validate application properties.
  13. 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.

Back to Spring Boot Course

Continue learning