🆙

Spring Boot 2.7.x から 3.0.x へのアップデート

2023/06/04に公開

概要

現在開発中のプロジェクトの Spring Boot のバージョンを 2.7.x から 3.0.x にアップデートしました。バージョンアップする上ではまったポイントや大きな変更点をまとめましたので参考になればと思います。主要なライブラリのバージョンアップの詳細は以下の通りです。

ライブラリ from to
Spirng Boot 2.7.1 3.0.1
Spirng Framework 5.3.23 6.0.3
Spirng Security 5.7.2 6.0.1
Spirng Batch 4.3.6 5.0.0

JJUG CCC 2023 Spring の登壇資料

本記事は JJUG CCC 2023 Spring の登壇内容を書き起こしたものになります。登壇資料はこちらをご覧ください。

Spring Boot サポート期間

サポート期間は 2.7.x が 2023/11/18 に対して、3.0.x は 2023/11/24 とほぼ変わりません。ただ有償サポートにしても2年ほどしかサポートされないので、なるべく最新バージョンに追従できるといいでしょう。
https://spring.pleiades.io/projects/spring-boot#support

Java バージョン

Spring Boot 3.0 から Java 17 以上で利用可能になります。今回のプロジェクトでは最初から Java 17 を採用していたので特に対応不要でした。

Gradle バージョン

今回のプロジェクトではビルドツールは Gradle を使用しています。Gradle のバージョンも 7.5 以上か 8.x にバージョンアップしておきましょう。

アップデート対応

Spring Framework

Jakarta EE 9/10 対応

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#jakarta-ee
Jakarta EE 10 のサポートに伴って、Java EE 8 のパッケージ名を変更する必要があります。
javax.servlet:javax.servlet-apijakarta.servlet:jakarta.servlet-api

Trailing Slash のオプションが非推奨

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#spring-mvc-and-webflux-url-matching-changes
Trailing Slash のオプションが非推奨になり /some/greeting//some/greeting は別のパスとしてみなされるようになりました。これにより画面が表示できないケースがあり、Controller のパスを一部修正しました。
https://github.com/spring-projects/spring-framework/issues/28552
Trailing Slash が非推奨になった背景としては、上記の issue でリクエストマッピングが曖昧であることやそれによるセキュリティの脆弱性が指摘されています。例えば、/resources/resources/** で権限を分けたい場合に、/resources/resources/ のパスを区別してあげる必要があります。

Spring Security

明示的なアクセス許可

https://docs.spring.io/spring-security/reference/5.8/migration/servlet/authorization.html#_ensure_that_all_requests_have_defined_authorization_rules
Spring Security の Configuration クラスで定義されていないパスが permitted から deny になりました。設定されてなかったパスを追加しました。

フィルター適用対象の dispatch type の変更

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#dispatch-types
すべての dispatch type (request, async, error, forward, include) がフィルターの適用対象になりました。これにより AuthenticationFailureHandler の実装で forward を利用していたため、フォワード先でもフィルターが適用されてしまい無限ループが発生していました。
dispatch type は application.properties で設定できるので、ひとまず 5.x 系と同等の設定に戻すことで対応しました。

spring.security.filter.dispatcher-types=request,async,error

SecurityContextRepository のデフォルト実装の変更

https://docs.spring.io/spring-security/reference/servlet/authentication/persistence.html#securitycontextrepository
SecurityContextRepository のデフォルト実装が DelegatingSecurityContextRepository になりました。これにより2段階認証用の AbstractAuthenticationProcessingFilter を継承した認証フィルターにおいて、セッションの永続化ができていなかったため2段階認証に成功しても未認証のままになってしまっていました。そのため、認証フィルターのコンストラクタで DelegatingSecurityContextRepository を SecurityContextRepository として設定することで対応しました。

setSecurityContextRepository(new DelegatingSecurityContextRepository(
    new RequestAttributeSecurityContextRepository(),
    new HttpSessionSecurityContextRepository()
));

Spring Batch

@EnableBatchProcessing が非推奨

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide#enablebatchprocessing-is-now-discouraged
以前までは @EnableBatchProcessing のアノテーションを付与することで Spring Boot の AutoConfiguration を有効にできていましたが、アノテーションが不要になりました。@EnableBatchProcessing のアノテーションが付与された Bean か、DefaultBatchConfiguration を継承した Bean を用意することで、AutoConfiguration を利用せずより柔軟にバッチ設定することができるようになりました。

JobBuilderFactory, StepBuilderFactory が非推奨

https://github.com/spring-projects/spring-batch/wiki/Spring-Batch-5.0-Migration-Guide#jobbuilderfactory-and-stepbuilderfactory-bean-exposureconfiguration
また JobBuilderFactory, StepBuilderFactory が非推奨になりました。代わりに JobBuilder, StepBuilder を利用するように修正しました。

Spring Batch 4.x
@Bean
public Job myJob(Step step) {
    return this.jobBuilderFactory.get("myJob")
	.start(step)
	.build();
}

@Bean
public Step myStep() {
    return this.stepBuilderFactory.get("myStep")
        .tasklet(myTasklet)
	.build();
}
Spring Batch 5.x
@Bean
public Job myJob(JobRepository jobRepository, Step step) {
    return new JobBuilder("myJob", jobRepository)
	.start(step)
	.build();
}

@Bean
public Step myStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    return new StepBuilder("myStep", jobRepository)
	.tasklet(myTasklet, transactionManager)
	.build();
}

3rdパーティーライブラリのアップデート

Datadog APM の Agent が未サポートだった

アプリケーションのパフォーマンス管理で Datadog APM を利用していましたが、Spring Boot のバージョンアップしたことで起動オプションとして設定していた Agent の影響でアプリケーションが正常に起動できなくなってしまいました。現在は 3.x もサポートされましたが、それまでの間は Datadog APM を利用できなくなってしまったので、3rdパーティーライブラリのアップデート状況もしっかりと確認しておきましょう。
https://github.com/DataDog/dd-trace-java/pull/4605

番外編

Gradle の VersionCatalog 対応

今回のSpringBootバージョンアップ対応を機に他のライブラリについてもバージョンアップをしようと思い、マルチプロジェクトでそれぞれ定義していたバージョン情報を VersionCatalog を利用することで libs.versions.toml ファイルで一元管理できるようにしました。また GitHub の Renovate で自動でアップデート情報を拾ってPRを作成してくれるようにもなり、バージョン管理周りが格段によくなりました。
https://docs.gradle.org/current/userguide/platforms.html

Spring Boot Migrator

Spring Boot のアップデートツールがあるようですが、Gradle 未対応だったため今回は使うことはできませんでした。Gradle がサポートされたら次回のバージョンアップで試してみたいと思います。
https://github.com/spring-projects-experimental/spring-boot-migrator

Red Frasco

Discussion