Spring Boot 2.x のプロジェクトを 3.x に上げようとしたら、コンパイルエラーが大量に出て途方に暮れた経験はありませんか。

Spring Boot 2.7.x の OSS サポートは 2023 年末で終了しており、セキュリティパッチも止まっています。移行は避けられないのですが、3.x では破壊的変更が多く、手順を知らないと作業がすぐ止まってしまいます。

この記事では javax→jakarta 置換SecurityFilterChain への移行spring.factories 廃止 という 3 つの主要な変更点に絞って対処法を整理します。末尾のチェックリストをそのまま作業シートとして使ってください。

Spring Boot 3.x で何が変わったか

主な破壊的変更は次の 3 点です。

  • javax→jakarta パッケージ名変更(Java EE から Jakarta EE 9 への移管)
  • WebSecurityConfigurerAdapter 廃止(SecurityFilterChain への強制移行)
  • spring.factories 廃止(AutoConfiguration 登録方式の変更)

それに加えて、Spring Boot 3.x は Java 17 以上 が必須です。Java 8・11 のままでは起動すらできません。

一括移行か段階的移行かはテストカバレッジとプロジェクト規模で判断しましょう。テストが薄い大規模プロジェクトであれば、フィーチャーブランチで移行を進めながら main への取り込みを段階的に行う方が安全です。

移行前の準備

まず build.gradle の Spring Boot バージョンと Java バージョンを変更します。

plugins {
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
    id 'java'
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

変更後に ./gradlew dependencies を実行して、互換性のないサードパーティライブラリがないか確認しましょう。古いバージョンの mapstructquerydslspringfox などは Jakarta EE 非対応のものが多いので要注意です。

javax → jakarta パッケージ名変更

Spring Boot 3.x は Jakarta EE 9 ベースなので、javax.* のインポートを jakarta.* に置換する必要があります。主な対象はこちらです。

  • javax.servlet.*jakarta.servlet.*
  • javax.persistence.*jakarta.persistence.*
  • javax.validation.*jakarta.validation.*
  • javax.annotation.*jakarta.annotation.*

注意点としてjavax.sql.*javax.crypto.*javax.net.* は Jakarta EE の対象外なので置換不要です。誤って置換するとコンパイルエラーになります。

コマンドラインで一括置換する場合

find src -name "*.java" | xargs sed -i \
  -e 's/javax\.servlet/jakarta.servlet/g' \
  -e 's/javax\.persistence/jakarta.persistence/g' \
  -e 's/javax\.validation/jakarta.validation/g' \
  -e 's/javax\.annotation/jakarta.annotation/g'

IntelliJ IDEA を使っている場合は「Edit > Find > Replace in Files」で正規表現 javax\.(servlet|persistence|validation|annotation)jakarta.$1 に置換する方が手軽です。置換後は必ずビルドを走らせて残漏れがないか確認してください。

SecurityFilterChain への移行

Spring Security 6.x では WebSecurityConfigurerAdapter が完全に削除されました。2.x のコードをそのままビルドするとコンパイルエラーになります。

Before(2.x)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin();
    }
}

After(3.x)

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(Customizer.withDefaults());
        return http.build();
    }
}

変更点をまとめると次の通りです。

  • extends WebSecurityConfigurerAdapter を削除して @Bean メソッドに変更
  • authorizeRequests()authorizeHttpRequests()
  • antMatchers()requestMatchers()
  • ラムダ DSL が標準になり .and() チェーンは不要

UserDetailsServicePasswordEncoder は以前と同じく @Bean で定義すれば OK です。Basic 認証の実装パターンは Spring Boot Security Basic認証の実装、JWT 認証は JWT認証の実装 を参照してください。

spring.factories 廃止

独自の AutoConfiguration や starter を作っていた場合、登録方式が変わっています。

Before(spring.factories)

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.example.MyAutoConfiguration

After(.imports ファイル)

# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.MyAutoConfiguration

新しいファイルパスは META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports で、クラス名を 1 行ずつ列挙するだけです。AutoConfiguration の仕組みの詳細は Spring Boot AutoConfiguration の仕組み で解説しています。

Java 17 対応の確認ポイント

Java 17 ではモジュールシステムによるカプセル化が強化されており、リフレクションで内部クラスにアクセスしていたライブラリが動かないことがあります。Spring Boot 3.x 対応の依存バージョンであれば --add-opens はほぼ不要になっているので、古い JVM オプションが残っている場合は削除して動作確認しましょう。sun.* パッケージを直接使っている箇所はコンパイルエラーになるので、標準 API への置き換えが必要です。

移行後の動作確認

移行が完了したら次の順序で確認します。

  1. ./gradlew build でコンパイル・テスト通過を確認
  2. アプリを起動して actuator/healthUP を返すか確認
  3. 主要エンドポイントにスモークテストを実施
  4. MockMvc を使ったテストで Security 設定まわりを見直す

@SpringBootTest@WebMvcTest は基本的にそのまま動作しますが、Security の設定変更に合わせてテストの認証設定も確認してください。

移行チェックリスト

事前準備

  • Java 17 以上への移行確認
  • build.gradle の Spring Boot バージョンを 3.x に変更
  • ./gradlew dependencies で依存ライブラリの互換性を確認

javax→jakarta 置換

  • javax.servletjavax.persistencejavax.validationjavax.annotation を置換
  • javax.sqljavax.crypto は置換していないか確認(置換不要)
  • ビルド成功を確認

Spring Security 移行

  • WebSecurityConfigurerAdapter の継承をすべて SecurityFilterChain @Bean に変更
  • authorizeRequests()authorizeHttpRequests()antMatchers()requestMatchers() に変更

spring.factories 廃止対応

  • META-INF/spring.factoriesEnableAutoConfiguration エントリを .imports ファイルに移行

動作確認

  • ビルド成功・テスト通過
  • アプリ起動・actuator/healthUP

まとめ

Spring Boot 3.x への移行は量が多く見えますが、javax→jakarta・SecurityFilterChain・spring.factories の 3 点を押さえれば大半のエラーは解消できます。移行ブランチを切って一項目ずつ片付けていくと、思ったより早く終わりますよ。

環境ごとの設定管理には Spring Boot Profiles の活用 も参考にしてみてください。