Spring Bootを最新化した
0. 重い腰を上げてアップグレード
弊社、Yahooショッピングの受注処理を自動化しているんだが、Spring Bootのバージョンが2.2.0.RELEASEなのでそろそろバージョンアップせねば、ということで作業開始。
1. 2.2から2.3へ
2.2から2.3へは、Spring Boot 2.3 Release Notesを見ながら作業するわけだが、弊社の環境で必要な作業は
- Gradle 6.3以降への更新
- spring-boot-starter-validationの追加
- 設定パラメータの移行
だった。
Gradle 6.3以降への更新については、wrapperタスクを実行するだけなので簡単。
$ ./gradlew wrapper --gradle-version 6.3
次にspring-boot-starter-validationの依存追加は、spring-boot-starter-webから依存が外れるため。[出典]
ということなので依存をbuild.gradle
に加える。
implementation("org.springframework.boot:spring-boot-starter-validation")
設定パラメータの移行については、spring-boot-properties-migratorというヘルパーがあるので、そいつをいったん依存に追加して起動することで、移行先を教えてくれる。
移行が終了したら依存から削除しておくこと。
runtime("org.springframework.boot:spring-boot-properties-migrator")
ここまでできたら、build.gradle
のpluginブロックに書かれているバージョンを2.3に書き換えれば、Spring Boot 2.3になる。
以前1.4から2.0に移行したときのことを考えると、ずいぶん楽になった印象。
やってる最中で、今まで通っていたテストが通らなくなるという事案があったので、テストを修正。
そして、テストが通ったところでひとまず本番にデプロイ。
2. 2.3から2.4へ
ここからが本題。詳しくは2.4のリリースノート全文をご覧いただくとして、2.3から2.4では設定ファイルに大幅な修正が入っている。
Springにはプロファイル機能があり、テスト用、本番用と環境を切り替えることが容易になっているのは周知の事実だが、外部からのプロパティ指定や内部のデフォルト値上書きなどで時折(Spring Bootの)開発者が意図しない順序でプロパティが展開されるケースがあった、とのことで、2.4でそのあたりを大々的に改修したのだそう。出典をメモることができなかったが、「よくないのはわかっていたが、奇跡的にうまく動いていたので改修しようとしてもいろいろ反対があった」そうな。
ひとまず今すぐに移行できないような場合は、
spring.config.use-legacy-processing=true
を追加することで、今までと同じ挙動になる。のだが、ゆくゆくは削除されることは明白なので、新しい方式に作り直すことにした。
spring:
profiles:
active: develop1
settings:
param_a: "param_common"
---
spring:
profiles: develop1
settings:
param_b: "param_devel1"
---
spring:
profiles: develop2
settings:
param_b: "param_devel2"
みたいなapplication.yml
があったとして、これをspring.config.use-legacy-processing=true
なしで動かそうとすると、settings.param_bの値は常にparam_devel2になってしまう。
PoCプロジェクトを作って試してみたところ、
- 共通部分としていたデフォルト値の集合部分を、独立したプロファイルの断片に切り出す
- プロファイル固有部分を、上記同様独立したプロファイルの断片として切り出す
- 従来プロファイルとしていた部分をプロファイルグループ名にし、必要なプロファイルの断片をその中に入れていく
という作業が必要だった。
これを踏まえ先ほどのapplication.yml
を書き換えたのがこちら。
spring:
profiles:
active: develop1
group:
develop1: "devel1,common"
develop2: "devel2,common"
---
spring:
config:
activate:
on-profile: devel1
settings:
param_b: "param_devel1"
---
spring:
config:
activate:
on-profile: devel2
settings:
param_b: "param_devel2"
---
spring:
config:
activate:
on-profile: common
settings:
param_a: "param_common"
ひとまずこれができたところで、2.3の時と同様build.gradle
のpluginブロックに書かれているバージョンを2.4に書き換えれば、Spring Boot 2.4になる。
logback-spring.xml
で行っていた設定もapplication.yml
でできるようになっているけど、今回は割愛。
CIも通ったので、その足で本番デプロイ。
3. 2.4から2.5へ
こちらも難儀した。このバージョンではデータソースの初期化の順序とプロセスが整理されたのだが、恥ずかしながら自分が書いたとはいえ弊社のデータソース初期化まわりはこんな感じになっていた。
- バッチ -> 原則事前定義済みスキーマを使用、テストで使うインメモリH2の場合のみ
schema.sql
で初期化 - Web -> すでにスキーマがあることを前提とした内容のFlyWay管理
How To guideのInitialize a Database Using Basic SQL Scriptsによれば、schema.sql
とFlyWayのような高度なスキーマ管理機構を併用するのは推奨されなくなった。将来的に削除する方針でもあるそうなので、言い換えれば混ぜるな危険である。
ということなので、Webプロジェクトで使っていたFlyWayのバージョンマイグレーションの前に、既存のschema.sql
とdata.sql
が実行されるようsrc/test/resources/db/migration
以下にマイグレーションファイルを作成することで対応した。
幸い、本番のマイグレーションファイルのバージョン表記は1からの連番ではなく日時のシリアル値を使用していたおかげでこういうことができたのだが、バージョンの開始を1にしていたら大変なことになっていただろう。
また、テスト時は常にマイグレーションがかかるよう、
spring.flyway.baseline-on-migrate=false
を設定した。
一方、バッチにもその実行結果とフェーズを記録するテーブル群があるので、その初期化用設定をバッチのプロジェクトに入れていく。
spring:
batch:
jdbc:
initialize-schema: "embedded"
Spring Bootのチーム曰く、「今まで奇跡的に動いていた」そうで(またかよw)、今回そこに手を入れたことで今まで通っていたテストがフィクスチャー不足で動かなくなったので、不足分を補うようテストを修正した。
最後に、Gradleが6.8以上必須になったので、wrapperタスクでGradleのバージョンを上げるわけだが、新規にSpring Boot 2.5.1のプロジェクトを作るとGradle 7.0.3を使っていたので、せっかくなので現時点の最新安定版の7.1を指定した。
ここまでできたら、build.gradle
のpluginブロックに書かれているバージョンを2.5.1に書き換えれば、Spring Boot 2.5.1になる。
CIも通ったので、その足で本番デプロイ。
4. 最後に
application.yml
の移行が個人的に一番難しかったが、わかってしまえば設定を意味のある部品単位にできるので、むしろ整備性と部品の再利用がやりやすくなった、と思う。
最近のコメント