Spring Boot 3 is a pretty big leap from Spring Boot 2, and it’s not just a minor version bump. The core of the change is a shift to Java 17 as the baseline and a complete upgrade to Jakarta EE 9, which means a lot of package name changes that will break your existing code.

Let’s see how this looks in practice. Imagine you have a simple Spring Boot 2 application with a controller.

// Spring Boot 2
package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        return "Hello from Spring Boot 2!";
    }
}

Now, to make this work in Spring Boot 3, you’ll need to update the imports to reflect the Jakarta EE namespace.

// Spring Boot 3
package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        return "Hello from Spring Boot 3!";
    }
}

Notice the subtle but critical change: javax.servlet is out, and jakarta.servlet is in. This applies to many other Java EE APIs as well.

The primary motivation behind Spring Boot 3’s upgrade is to align with the wider Java ecosystem’s move to Jakarta EE 9 and to leverage the features of Java 17. Jakarta EE 9 introduced a standardized namespace for its APIs, moving from javax.* to jakarta.*. This was a significant undertaking for the Jakarta EE project and, by extension, for frameworks like Spring that depend on these APIs. Java 17 brings performance improvements, new language features, and essential security updates.

Here’s a breakdown of the key areas you’ll encounter when migrating:

Java 17 Baseline

Spring Boot 3 requires Java 17 or later. If your project is still on Java 8 or 11, you’ll need to upgrade your JDK first. This isn’t just a configuration change; it means your code must be compatible with Java 17’s features and any deprecated APIs that have been removed.

Diagnosis: Check your pom.xml (Maven) or build.gradle (Gradle) for the Java version. Maven:

<properties>
    <java.version>17</java.version>
</properties>

Gradle:

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

Fix: Update your build configuration to target Java 17. Ensure your JDK installation is also version 17 or higher.

Jakarta EE 9 Namespace Migration

This is the most pervasive breaking change. All javax.* imports related to Java EE specifications (like Servlet, JPA, Bean Validation) must be changed to jakarta.*.

Diagnosis: Spring Boot 3 will fail to compile or run with ClassNotFoundException or NoClassDefFoundError for classes that previously resided in javax.* packages. IDEs will highlight these import errors. Fix: Manually update imports or use IDE refactoring tools. For example, change: import javax.servlet.http.HttpServletRequest; to import jakarta.servlet.http.HttpServletRequest;

Spring Framework 6

Spring Boot 3 is built on Spring Framework 6. This version also brings its own set of breaking changes, including the removal of deprecated classes and methods, and changes in the way certain configurations are handled. A notable change is the removal of spring-context-support’s StandardServletEnvironment for WebFlux, which is now handled by WebFluxApplicationContext.

Diagnosis: Look for compilation errors related to Spring classes or runtime errors indicating missing beans or incorrect configurations. Fix: Consult the Spring Framework 6 migration guide for specific API changes. Often, this involves updating method calls or replacing deprecated classes with their newer equivalents. For instance, if you were using org.springframework.web.context.support.StandardServletEnvironment, you might need to adjust your application context configuration.

Spring Security 6

Spring Security has also undergone significant changes. Many configuration classes and methods have been deprecated or removed, particularly around lambda DSLs and the way security rules are defined. The WebSecurityConfigurerAdapter is now deprecated, and you should use SecurityFilterChain beans instead.

Diagnosis: Failures in authentication or authorization, NoSuchMethodError, or compilation errors related to Spring Security configuration. Fix: Migrate your security configuration to use SecurityFilterChain beans. Example (Spring Boot 2 style, deprecated):

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/public").permitAll()
            .anyRequest().authenticated()
            .and().formLogin();
    }
}

Example (Spring Boot 3 style):

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authz -> authz
                .requestMatchers("/public").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin();
        return http.build();
    }
}

Dependency Management

Many third-party libraries that integrate with Spring or Java EE have released new versions to be compatible with Spring Boot 3 and Jakarta EE 9. You’ll need to update these dependencies.

Diagnosis: Compilation errors or runtime exceptions caused by incompatible versions of libraries like Hibernate, Jackson, or various persistence providers. Fix: Update your dependencies in pom.xml or build.gradle to their latest versions that support Spring Boot 3/Jakarta EE 9. For example, ensure you’re using Hibernate 6.x, Jackson 2.13+, etc.

Configuration Property Changes

Some configuration properties have been renamed or removed. Spring Boot 3 provides a spring-boot-properties-migrator module that can help identify these changes.

Diagnosis: Application fails to start with BindException or IllegalArgumentException indicating unknown or invalid properties. Fix: Add the spring-boot-properties-migrator dependency to your project. Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-properties-migrator</artifactId>
    <scope>runtime</scope>
</dependency>

When the application starts, it will log any deprecated or removed properties. Update your application.properties or application.yml accordingly. For example, spring.jpa.hibernate.naming-strategy might have changed.

Deprecated Features and APIs

Beyond the explicit namespace and framework changes, many smaller APIs and features that were deprecated in Spring Boot 2 have been removed in Spring Boot 3.

Diagnosis: Compilation errors pointing to specific method calls or class instantiations marked as deprecated in earlier versions. Fix: Review the Spring Boot 2 and Spring Framework 5 release notes for deprecated items and update your code to use the recommended alternatives.

The next hurdle you’ll likely face after successfully migrating to Spring Boot 3 is dealing with the implications of using Java 17’s newer features and potential performance tuning related to the updated Spring Framework 6 and its reactive components.

Want structured learning?

Take the full Spring-boot course →