Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その7 )( Error Prone を 2.3.4 → 2.4.0 へバージョンアップする )
概要
記事一覧はこちらです。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その6 )( PMD を 6.20.0 → 6.26.0 へバージョンアップする ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Error Prone を 2.3.4 → 2.4.0 へバージョンアップします。
参照したサイト・書籍
Command-line flags
https://errorprone.info/docs/flagsCriteria for new checks
https://errorprone.info/docs/criteria
目次
- build.gradle を変更する
- 警告の原因を取り除く
警告:[EmptyBlockTag] A block tag (@param, @return, @throws, @deprecated) has an empty description. Block tags without descriptions don't add much value for future readers of the code; consider removing the tag entirely or adding a description.
警告:[MissingSummary] A summary line is required on public/protected Javadocs.
警告:[InlineFormatString] Prefer to create format strings inline, instead of extracting them to a single-use constant
警告:[InvalidThrows] The documented method doesn't actually throw this checked exception.
警告:[JdkObsolete] StringBuffer performs synchronization that is usually unnecessary; prefer StringBuilder.
- 2.4.0 から追加された WARNING の check を有効にするには build.gradle に
options.errorprone.errorproneArgs.add("-Xep:<checkName>")
を記述する - メモ書き
手順
build.gradle を変更する
plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.3.2.RELEASE" id "io.spring.dependency-management" version "1.0.9.RELEASE" id "groovy" id "checkstyle" // id "com.github.spotbugs" version "3.0.0" id "pmd" id "net.ltgt.errorprone" version "1.2.1" id "com.gorylenko.gradle-git-properties" version "2.2.3" } .......... [compileJava, compileTestGroovy, compileTestJava]*.options*.encoding = "UTF-8" [compileJava, compileTestGroovy, compileTestJava]*.options*.compilerArgs = ["-Xlint:all,-options,-processing,-path"] tasks.withType(JavaCompile).configureEach { options.errorprone.disableWarningsInGeneratedCode = true } tasks.named("compileTestJava").configure { options.errorprone.enabled = false } .......... dependencies { def jdbcDriver = "org.postgresql:postgresql:42.2.14" def spockVersion = "1.3-groovy-2.5" def domaVersion = "2.26.0" def lombokVersion = "1.18.12" def errorproneVersion = "2.4.0" def powermockVersion = "2.0.7" def spotbugsVersion = "4.0.0-beta4" ..........
- plugins block の以下の点を変更します。
id "net.ltgt.errorprone" version "1.1.1"
→id "net.ltgt.errorprone" version "1.2.1"
- tbroyer / gradle-errorprone-plugin に記載されていた記述で、今回 build した時に自動生成されたコードに対しても Error Prone が警告を出したので
tasks.withType(JavaCompile).configureEach { options.errorprone.disableWarningsInGeneratedCode = true }
を追加します。 - dependencies block の以下の点を変更します。
def errorproneVersion = "2.3.4"
→def errorproneVersion = "2.4.0"
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると compileJava タスクで警告が 100個以上出ました(コンソールには 100個と出力されていますが警告が 100個以上あっても1度には 100個までしか出力されません)。
警告の原因を取り除く
警告:[EmptyBlockTag] A block tag (@param, @return, @throws, @deprecated) has an empty description. Block tags without descriptions don't add much value for future readers of the code; consider removing the tag entirely or adding a description.
Error Prone のマニュアルの EmptyBlockTag です。Javadoc で @param, @return, @throws, @deprecated の説明文を記述していないと警告が出るようになっていました。@throws の説明文を記述していなかったのが原因です。
@throws の説明文を追加します。
警告:[MissingSummary] A summary line is required on public/protected Javadocs.
Error Prone のマニュアルの MissingSummary です。public/protected の Javadoc で summary line を記述していないと警告が出るようになっていました。
summary line を記述します。
警告:[InlineFormatString] Prefer to create format strings inline, instead of extracting them to a single-use constant
Error Prone のマニュアルの InlineFormatString です。String.format で呼び出すフォーマット文字列を定数で定義していたのですが、inline で書くか helper メソッドを使用するよう警告が出ていました。正しい引数を渡しているかチェックしにくいので String.format とフォーマット文字列は近くに書くように、という指摘のようです。
今回は定数をやめて inline に変更します。
警告:[InvalidThrows] The documented method doesn't actually throw this checked exception.
Error Prone のマニュアルの InvalidThrows です。throws がないのに Javadoc に @throws を記述していたので警告が出ていました。
削除します。
警告:[JdkObsolete] StringBuffer performs synchronization that is usually unnecessary; prefer StringBuilder.
Error Prone のマニュアルの JdkObsolete です。指摘されたのは以下の箇所で、
HttpServletRequest#getRequestURL の戻り値の型が StringBuffer のためでした。
String 型を返す HttpServletRequest#getRequestURI に変更します。
2.4.0 から追加された WARNING の check を有効にするには build.gradle に options.errorprone.errorproneArgs.add("-Xep:<checkName>")
を記述する
https://github.com/google/error-prone/releases/tag/v2.4.0 を見ると new checks に追加された check が記述されていますが、CheckedExceptionNotThrown が検知できるのか試してみたいと思い、 ksbysample.webapp.lending.ErrorProneCheck クラスを作成して以下の内容を記述した後、
compileJava タスクを実行しても何も検知されませんでした。
Error Prone のマニュアルを見ると SerSeverity.WARNING の check については、
build.gradle に options.errorprone.errorproneArgs.add("-Xep:<checkName>")
の記述を追加しないと有効にならないからでした。
build.gradle に 'options.errorprone.errorproneArgs.add("-Xep:CheckedExceptionNotThrown")' を追加してから、
tasks.withType(JavaCompile).configureEach { options.errorprone.disableWarningsInGeneratedCode = true options.errorprone.errorproneArgs.add("-Xep:CheckedExceptionNotThrown") }
compileJava タスクを実行すると今度は 警告:[CheckedExceptionNotThrown] This method cannot throw a checked exception that it claims to. This may cause consumers of the API to incorrectly attempt to handle, or propagate, this exception.
のメッセージが出力されました。
メモ書き
これまで全然何もエラー・警告を出さなかったのに 2.4.0 にバージョンアップしたら急に警告が出るようになりました。しかも実装に関する警告よりも Javadoc の警告が出るようになったのが意外です。Checkstyle、PMD に加えて Error Prone も入れておけば Javadoc の記述漏れをかなり検知できるのではないでしょうか。
履歴
2020/08/20
初版発行。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その6 )( PMD を 6.20.0 → 6.26.0 へバージョンアップする )
概要
記事一覧はこちらです。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その5 )( Checkstyle を 8.28 → 8.35 へバージョンアップする ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- PMD を 6.20.0 → 6.26.0 へバージョンアップします。
参照したサイト・書籍
目次
手順
build.gradle を変更する
pmd { toolVersion = "6.26.0" sourceSets = [project.sourceSets.main] ignoreFailures = true consoleOutput = true ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml") ruleSets = [] }
toolVersion = "6.20.0"
→toolVersion = "6.26.0"
に変更します。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると pmdMain タスクで警告が出ました。
警告の原因を取り除く
The initializer for variable '...' is never used (overwritten on line ...)
生成されたレポートファイル build/reports/pmd/main.html をブラウザで開くと2箇所指摘されており、どちらも Problem には The initializer for variable '...' is never used (overwritten on line ...)
が表示されていました。
6.26.0 から追加された UnusedAssignment による警告でした。
- 2箇所は、変数宣言時に
= null
と初期値をセットしていたが、その後の処理で必ず値がセットされるので警告が出ていたのが原因でした。変数宣言時に初期値をセットしている部分を削除します。 - 1箇所はデータをロックするために select していた時に取得したデータを使用しないにもかかわらず変数にセットしていたのが原因でした。取得したデータを変数にセットしないように変更します。
変更後に clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると BUILD SUCCESSFUL が表示されました。
履歴
2020/08/15
初版発行。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その5 )( Checkstyle を 8.28 → 8.35 へバージョンアップする )
概要
記事一覧はこちらです。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その4 )( Release Notes を見て必要な箇所を変更する ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Checkstyle を 8.28 → 8.35 へバージョンアップします。
- 最新版の google_checks.xml の内容も反映します。
参照したサイト・書籍
checkstyle / checkstyle
https://github.com/checkstyle/checkstylecheckstyle/checkstyle - checkstyle/src/main/resources/google_checks.xml
https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml
目次
- build.gradle を変更する
- IntelliJ IDEA の CheckStyle-IDEA Plugin が使用する Checkstyle のバージョンを 8.34 に変更する
- 最新版の google_checks.xml から設定をコピーする
手順
build.gradle を変更する
checkstyle { configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml") toolVersion = "8.35" sourceSets = [project.sourceSets.main] }
toolVersion = "8.28"
→toolVersion = "8.35"
に変更します。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると BUILD SUCCESSFUL が表示されました。
IntelliJ IDEA の CheckStyle-IDEA Plugin が使用する Checkstyle のバージョンを 8.34 に変更する
CheckStyle-IDEA Plugin に指定できるバージョンが 8.34 までだったので 8.34 を指定します。
最新版の google_checks.xml から設定をコピーする
最新版の google_checks.xml から差分を反映します。。。が、2020/08/12 時点の google_checks.xml の差分を反映したところ checkstyleMain タスクでいくつかエラーが出て削除することがありました。
今回反映した内容を箇条書きで記述しておきます。
<module name="RightCurly">
の<property name="tokens">
の value に ENUM_DEF, INTERFACE_DEF を追加しました。<module name="SuppressionXpathSingleFilter">...</module>
を追加しました。<module name="WhitespaceAfter">...</module>
を追加しました。<module name="AbbreviationAsWordInName">
の<property name="tokens">
の value に PATTERN_VARIABLE_DEF を追加しました。<module name="NoWhitespaceBefore">
の<property name="tokens">
の value から ELLIPSIS を削除し LABELED_STAT を追加しました。
以下の変更は checkstyleMain タスク実行時にエラーが出たので削除しました。Java 14 の機能向けの定義のようです。つまり google_checks.xml には Java 14 向けの定義も記述されるので Java 11 で開発する場合にはそのままでは使えない(エラーが出たものは取り除く必要がある)ということでした。
<module name="EmptyLineSeparator">
の<property name="tokens">
の value に RECORD_DEF を追加。<module name="PatternVariableName">...</module>
の追加。<module name="AbbreviationAsWordInName">
の<property name="tokens">
の value に RECORD_DEF, RECORD_COMPONENT_DEF を追加。<module name="MethodParamPad">
の<property name="tokens">
の value に RECORD_DEF を追加。<module name="ParenPad">
の<property name="tokens">
の value に RECORD_DEF を追加。
変更後に clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると BUILD SUCCESSFUL が表示されました。
履歴
2020/08/13
初版発行。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その4 )( Release Notes を見て必要な箇所を変更する )
概要
記事一覧はこちらです。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その3 )( Spring Boot を 2.2.9 → 2.3.2 へバージョンアップする ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- 以下のドキュメントを見て必要な箇所を変更します。
参照したサイト・書籍
Spring BootのGraceful shutdownって内部でどうやって実現されているの?
https://speakerdeck.com/kawakawaryuryu/spring-bootfalsegraceful-shutdowntutenei-bu-dedouyatuteshi-xian-sareteirufalseSpring BootのGraceful shutdown処理が内部でどう呼ばれているかソースコードリーディングしてみた結果
https://qiita.com/kawakawaryuryu/items/bc92453f9c43d98c1a26Spring Boot 2.3 の Liveness & Readiness Probes 対応 について調べてみた
https://speakerdeck.com/otty375/spring-boot-2-dot-3-liveness-and-readiness-probesKubernetes Probes
https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-kubernetes-probesLiveness and Readiness Probes with Spring Boot
https://spring.io/blog/2020/03/25/liveness-and-readiness-probes-with-spring-bootLiveness and Readiness Probes in Spring Boot
https://www.baeldung.com/spring-liveness-readiness-probesKubernetes のヘルスチェック(Liveness Probe,Readiness Probe)を検証する
https://qiita.com/toshihirock/items/c7e94e70c1c9650488df
目次
手順
server.shutdown=graceful
を設定する
Graceful shutdown によると
設定ファイルに server.shutdown=graceful
を記述すれば Graceful shutdown をしてくれるようになったので、src/main/resources/application.properties に設定します。
.......... management.endpoint.health.show-details=always server.shutdown=graceful #spring.autoconfigure.exclude=com.integralblue.log4jdbc.spring.Log4jdbcAutoConfiguration spring.datasource.hikari.jdbc-url=jdbc:postgresql://localhost/ksbylending ..........
動作を確認するために src/main/java/ksbysample/webapp/lending/web/GracefulShutdownTestController.java を新規作成して以下の内容を記述します。http://localhost:8080/gracefulShutdownTest にアクセスすると 5分間 sleep してからレスポンスを返す Controller クラスです。Graceful shutdown が有効になっていれば、この URL にアクセスしてから Tomcat を停止しようとすると 30秒(spring.lifecycle.timeout-per-shutdown-phase のデフォルト値)待ってから停止するはず。
package ksbysample.webapp.lending.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * Spring Boot 2.3 から追加された Graceful shutdown の機能をテストするための Controller */ @Controller public class GracefulShutdownTestController { /** * アクセス後 5分 sleep してからレスポンスを返す * * @return "OK"の文字列 * @throws InterruptedException */ @GetMapping("/gracefulShutdownTest") @ResponseBody public String index() throws InterruptedException { Thread.sleep(60_000 * 5); return "OK"; } }
src/main/java/ksbysample/webapp/lending/config/WebSecurityConfig.java に .antMatchers("/gracefulShutdownTest/**").permitAll()
の記述を追加して、認証不要にします。
@Configuration public static class FormLoginWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 認証の対象外にしたいURLがある場合には、以下のような記述を追加します // 複数URLがある場合はantMatchersメソッドにカンマ区切りで対象URLを複数列挙します // .antMatchers("/country/**").permitAll() .......... .antMatchers("/sample/**").permitAll() .antMatchers("/gracefulShutdownTest/**").permitAll() .anyRequest().hasAnyRole("USER", "ADMIN", "APPROVER"); ..........
Tomcat を起動して Graceful shutdown の機能を試してみると、
- IntelliJ IDEA から起動した時は機能しません。すぐに Tomcat が停止します(停止は Navigation bar や Services Tool Window の Stop ボタンで行いました)。
- jar ファイルを作成してコマンドラインすると、/gracefulShutdownTest にアクセスして 5秒後に Ctrl+C を押す → 30秒何も起こらない →
バッチ ジョブを終了しますか (Y/N)?
が表示される、という動きになりました。Graceful shutdown が機能しています。
2020-08-09 20:50:50.080 INFO 23156 --- [SpringContextShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Waiting for workers to finish. 2020-08-09 20:50:50.709 INFO 23156 --- [SpringContextShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Successfully waited for workers to finish. 2020-08-09 20:50:50.714 INFO 23156 --- [SpringContextShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete 2020-08-09 20:51:20.717 INFO 23156 --- [SpringContextShutdownHook] o.s.c.support.DefaultLifecycleProcessor : Failed to shut down 1 bean with phase value 2147483647 within timeout of 30000ms: [webServerGracefulShutdown] 2020-08-09 20:51:20.740 INFO 23156 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown aborted with one or more requests still active .......... 2020-08-09 20:51:22.954 INFO 23156 --- [SpringContextShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Shutdown ignored - container is not active already 2020-08-09 20:51:22.955 INFO 23156 --- [SpringContextShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor' 2020-08-09 20:51:22.963 INFO 23156 --- [SpringContextShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2020-08-09 20:51:22.977 INFO 23156 --- [SpringContextShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. 2020-08-09 20:51:23.018 WARN 23156 --- [SpringContextShutdownHook] io.lettuce.core.RedisChannelHandler : Connection is already closed 2020-08-09 20:51:23.018 WARN 23156 --- [SpringContextShutdownHook] io.lettuce.core.RedisChannelHandler : Connection is already closed 2020-08-09 20:51:23.018 WARN 23156 --- [SpringContextShutdownHook] io.lettuce.core.RedisChannelHandler : Connection is already closed 2020-08-09 20:51:23.048 INFO 23156 --- [SpringContextShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 2020-08-09 20:51:23.049 WARN 23156 --- [SpringContextShutdownHook] io.lettuce.core.RedisChannelHandler : Connection is already closed
nssm.exe でサービスに登録して起動した時に Graceful shutdown したい場合、登録時に「Shutdown」タブで「Generate Control-C」だけをチェックして「Timeout」に
spring.lifecycle.timeout-per-shutdown-phase
に設定した時間より長い時間をセットする必要があります(デフォルトでは全てチェックされていて「Timeout」に 1500 がセットされている)。この設定にすると、サービス起動 → /gracefulShutdownTest にアクセスして 5秒後に「サービスの停止」リンククリック → 60秒何も起こらない(
spring.lifecycle.timeout-per-shutdown-phase
に設定された秒数ではなく nssm.exe で設定した Timeout の秒数) → サービスが停止する、という動きになりました。ログファイルを見ると Graceful shutdown が機能して Tomcat は 30秒後に停止していますが、サービスが停止するまでには nssm.exe で設定した Timeout の秒数を待つ必要があります(処理中のリクエストがなくてもnssm.exe で設定した Timeout の秒数を必ず待つようになります)。
2020-08-10 23:50:46.445 INFO 3384 --- [SpringContextShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Waiting for workers to finish. 2020-08-10 23:50:46.979 INFO 3384 --- [SpringContextShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Successfully waited for workers to finish. 2020-08-10 23:50:46.983 INFO 3384 --- [SpringContextShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete 2020-08-10 23:51:16.987 INFO 3384 --- [SpringContextShutdownHook] o.s.c.support.DefaultLifecycleProcessor : Failed to shut down 1 bean with phase value 2147483647 within timeout of 30000ms: [webServerGracefulShutdown] 2020-08-10 23:51:16.989 INFO 3384 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown aborted with one or more requests still active .......... 2020-08-10 23:51:19.272 INFO 3384 --- [SpringContextShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Shutdown ignored - container is not active already 2020-08-10 23:51:19.273 INFO 3384 --- [SpringContextShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor' 2020-08-10 23:51:19.283 INFO 3384 --- [SpringContextShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2020-08-10 23:51:19.297 INFO 3384 --- [SpringContextShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. 2020-08-10 23:51:19.357 INFO 3384 --- [SpringContextShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 2020-08-10 23:51:19.358 WARN 3384 --- [SpringContextShutdownHook] io.lettuce.core.RedisChannelHandler : Connection is already closed
- ローカルで Docker で Tomcat を起動した場合、
Commencing graceful shutdown.
のログが出力されましたので Graceful shutdown が機能しています。
2020-08-11 00:15:11.433 INFO 1 --- [extShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Waiting for workers to finish. 2020-08-11 00:15:12.174 INFO 1 --- [extShutdownHook] o.s.a.r.l.SimpleMessageListenerContainer : Successfully waited for workers to finish. 2020-08-11 00:15:12.180 INFO 1 --- [extShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
management.endpoint.health.probes.enabled=true
を設定する
Liveness and Readiness probes によると、アプリが実行中かどうか(liveness)、リクエストに応答できる準備が出来ているかどうか(readiness)を Actuator で取得できる機能が提供されたとのこと。Kubernetes 環境向けの機能なので、Kubernetes の Container probes の説明が分かりやすいです。
Kubernetes の環境で実行しないとあまり意味はなさそうですが(Kubernetes 環境だと自動で設定されるらしい)、面白そうなので設定してみます。
src/main/resources/application.properties を以下のように変更します。
.......... management.endpoint.health.show-details=always management.endpoint.health.probes.enabled=true management.endpoint.health.group.liveness.include=livenessStateProbeIndicator,cacheCheck management.endpoint.health.group.readiness.include=readinessStateProbeIndicator,cacheCheck server.shutdown=graceful ..........
- 以下の3行を追加します。
management.endpoint.health.probes.enabled=true
management.endpoint.health.group.liveness.include=livenessStateProbeIndicator,cacheCheck
management.endpoint.health.group.readiness.include=readinessStateProbeIndicator,cacheCheck
- Liveness and Readiness probes には
management.endpoint.health.probes.enabled=true
の記述しかないのですが、他の2つも設定しないと /actuator/health/liveness、/actuator/health/readiness にアクセスした時に 404 Not Found が返ってきました。
Tomcat を起動してから http://localhost:8080/actuator/health/liveness にアクセスすると 200 OK と以下の画像のレスポンスが返ってきました。
http://localhost:8080/actuator/health/readiness も 200 OK が返ってきます。
履歴
2020/08/12
初版発行。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その3 )( Spring Boot を 2.2.9 → 2.3.2 へバージョンアップする )
概要
記事一覧はこちらです。
- 今回の手順で確認できるのは以下の内容です。
- Spring Boot を 2.2.9 → 2.3.2 へバージョンアップします。
参照したサイト・書籍
目次
手順
Spring Initializr で 2.3.2 のプロジェクトを作成する
Spring Initializr で 2.3.2 のプロジェクトを作成して、生成された build.gradle を見て反映した方が良い点があるか確認します。
※リストの一番下の「PostgreSQL Driver」もチェックします。
以下の build.gradle が作成されました。
plugins { id 'org.springframework.boot' version '2.3.2.RELEASE' id 'io.spring.dependency-management' version '1.0.9.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-freemarker' implementation 'org.springframework.boot:spring-boot-starter-mail' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.session:spring-session-data-redis' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' testImplementation('org.springframework.boot:spring-boot-starter-test') { exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' } testImplementation 'org.springframework.security:spring-security-test' } test { useJUnitPlatform() }
以下の点を build.gradle に反映します。
- configurations block から以下の2行を削除します。
developmentOnly
runtimeClasspath.extendsFrom developmentOnly
build.gradle を変更する
buildscript { ext { group "ksbysample" version "2.3.2-RELEASE" } repositories { mavenCentral() maven { url "https://repo.spring.io/release/" } gradlePluginPortal() } } plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.3.2.RELEASE" id "io.spring.dependency-management" version "1.0.9.RELEASE" id "groovy" id "checkstyle" // id "com.github.spotbugs" version "3.0.0" id "pmd" id "net.ltgt.errorprone" version "1.1.1" id "com.gorylenko.gradle-git-properties" version "2.2.3" } .......... configurations { compileOnly.extendsFrom annotationProcessor // annotationProcessor と testAnnotationProcessor、compileOnly と testCompileOnly を併記不要にする testAnnotationProcessor.extendsFrom annotationProcessor testImplementation.extendsFrom compileOnly // for Doma 2 domaGenRuntime // for SpotBugs spotbugsStylesheets { transitive = false } } .......... dependencyManagement { imports { // mavenBom は以下の URL のものを使用する // https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.2.9.RELEASE/ // bomProperty に指定可能な property は以下の URL の BOM に記述がある // https://repo.spring.io/release/org/springframework/boot/spring-boot-dependencies/2.2.9.RELEASE/spring-boot-dependencies-2.2.9.RELEASE.pom mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) { // Spring Boot の BOM に定義されているバージョンから変更する場合には、ここに以下のように記述する // bomProperty "thymeleaf.version", "3.0.9.RELEASE" bomProperty "groovy.version", "2.5.12" } mavenBom("org.junit:junit-bom:5.6.2") } } dependencies { def jdbcDriver = "org.postgresql:postgresql:42.2.14" def spockVersion = "1.3-groovy-2.5" def domaVersion = "2.26.0" def lombokVersion = "1.18.12" def errorproneVersion = "2.3.4" def powermockVersion = "2.0.7" def spotbugsVersion = "4.0.0-beta4" // dependency-management-plugin によりバージョン番号が自動で設定されるもの // Appendix F. Dependency versions ( https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html ) 参照 implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-thymeleaf") implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity5") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-freemarker") implementation("org.springframework.boot:spring-boot-starter-mail") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-data-redis") implementation("org.springframework.boot:spring-boot-starter-amqp") implementation("org.springframework.boot:spring-boot-starter-actuator") developmentOnly("org.springframework.boot:spring-boot-devtools") compileOnly("org.springframework.boot:spring-boot-configuration-processor") implementation("org.springframework.session:spring-session-data-redis") implementation("org.springframework.retry:spring-retry") implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-xml") implementation("org.apache.commons:commons-lang3") implementation("org.codehaus.janino:janino") implementation("io.micrometer:micrometer-registry-prometheus") testImplementation("org.springframework.boot:spring-boot-starter-test") { exclude group: "org.junit.vintage", module: "junit-vintage-engine" } testImplementation("org.springframework.security:spring-security-test") testImplementation("org.yaml:snakeyaml") // dependency-management-plugin によりバージョン番号が自動で設定されないもの、あるいは最新バージョンを指定したいもの runtimeOnly("${jdbcDriver}") implementation("com.integralblue:log4jdbc-spring-boot-starter:2.0.0") implementation("org.simpleframework:simple-xml:2.7.1") implementation("com.univocity:univocity-parsers:2.8.4") implementation("com.google.guava:guava:29.0-jre") implementation("org.flywaydb:flyway-core:6.5.3") testImplementation("org.dbunit:dbunit:2.7.0") { exclude group: "postgresql", module: "postgresql" } testImplementation("com.icegreen:greenmail:1.5.14") testImplementation("org.assertj:assertj-core:3.16.1") testImplementation("com.jayway.jsonpath:json-path:2.4.0") testImplementation("org.jsoup:jsoup:1.13.1") testImplementation("cglib:cglib-nodep:3.3.0") testImplementation("org.spockframework:spock-core:${spockVersion}") testImplementation("org.spockframework:spock-spring:${spockVersion}") // for lombok // testAnnotationProcessor、testCompileOnly を併記しなくてよいよう configurations で設定している annotationProcessor("org.projectlombok:lombok:${lombokVersion}") compileOnly("org.projectlombok:lombok:${lombokVersion}") // for Doma annotationProcessor("org.seasar.doma:doma:${domaVersion}") implementation("org.seasar.doma:doma:${domaVersion}") domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}") domaGenRuntime("${jdbcDriver}") // for JUnit 5 // junit-jupiter で junit-jupiter-api, junit-jupiter-params, junit-jupiter-engine の3つが依存関係に追加される testImplementation("org.junit.jupiter:junit-jupiter") testRuntimeOnly("org.junit.platform:junit-platform-launcher") // for Error Prone ( http://errorprone.info/ ) errorprone("com.google.errorprone:error_prone_core:${errorproneVersion}") compileOnly("com.google.errorprone:error_prone_annotations:${errorproneVersion}") // PowerMock testImplementation("org.powermock:powermock-module-junit4:${powermockVersion}") testImplementation("org.powermock:powermock-api-mockito2:${powermockVersion}") // for SpotBugs // compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}") { // exclude group: "pull-parser", module: "pull-parser" // } // compileOnly("net.jcip:jcip-annotations:1.0") compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}") // testImplementation("com.google.code.findbugs:jsr305:3.0.2") // spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}") // spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.10.1") } ..........
Spring Boot 2.3.2 へのバージョンアップとして以下の点を変更します。
- buildscript block の以下の点を変更します。
version "2.2.9-RELEASE"
→version "2.3.2-RELEASE"
- plugins block の以下の点を変更します。
id "org.springframework.boot" version "2.2.9.RELEASE"
→id "org.springframework.boot" version "2.3.2.RELEASE"
- configurations block から以下の2行を削除します。
developmentOnly
runtimeClasspath.extendsFrom developmentOnly
各種ライブラリのバージョンアップとして以下の点を変更します。
- plugins block の以下の点を変更します。
id "com.gorylenko.gradle-git-properties" version "2.2.0"
→id "com.gorylenko.gradle-git-properties" version "2.2.3"
- dependencyManagement block の以下の点を変更します。
mavenBom("org.junit:junit-bom:5.5.2")
→mavenBom("org.junit:junit-bom:5.6.2")
- dependencies block の以下の点を変更します。
def jdbcDriver = "org.postgresql:postgresql:42.2.9"
→def jdbcDriver = "org.postgresql:postgresql:42.2.14"
def lombokVersion = "1.18.10"
→def lombokVersion = "1.18.12"
def powermockVersion = "2.0.4"
→def powermockVersion = "2.0.7"
implementation("com.google.guava:guava:28.1-jre")
→implementation("com.google.guava:guava:29.0-jre")
implementation("org.flywaydb:flyway-core:6.1.3")
→implementation("org.flywaydb:flyway-core:6.5.3")
testImplementation("org.dbunit:dbunit:2.6.0")
→testImplementation("org.dbunit:dbunit:2.7.0")
testImplementation("com.icegreen:greenmail:1.5.11")
→testImplementation("com.icegreen:greenmail:1.5.14")
testImplementation("org.assertj:assertj-core:3.14.0")
→testImplementation("org.assertj:assertj-core:3.16.1")
testImplementation("org.jsoup:jsoup:1.12.1")
→testImplementation("org.jsoup:jsoup:1.13.1")
- Doma は domaGen タスクを変更する必要があるので後でバージョンアップします。
build タスク実行時に出るエラーを修正する
clean タスク実行 → Rebuild Project 実行。。。でエラーが出ました。パッケージjavax.validationは存在しません
のエラーメッセージが出力されています。
Spring Boot 2.3 Release Notes の Validation Starter no longer included in web starters の記述に従い implementation("org.springframework.boot:spring-boot-starter-validation")
を追加します。
dependencies { .......... implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-validation")
再度 Rebuild Project 実行を実行すると、今度は以下の警告が出ます。
1つ目は org.springframework.boot.web.servlet.error.ErrorControllerのgetErrorPath()は推奨されません
で、ksbysample.webapp.lending.web.WebappErrorController クラスで getErrorPath メソッドを override していたのですが、
org.springframework.boot.web.servlet.error.ErrorController#getErrorPath メソッドを見ると Deprecated になっていました。エラーページの path は設定ファイルの server.error.path で設定することになったようです。
Spring Boot の Common Application properties のページを見ると server.error.path のデフォルト値は /error
で ksbysample.webapp.lending.web.WebappErrorController#getErrorPath メソッドが返す値と同じですので、override している ksbysample.webapp.lending.web.WebappErrorController#getErrorPath メソッドに @SuppressWarnings("deprecation")
を付与して警告が出ないようにします。
@SuppressWarnings("deprecation") @Override public String getErrorPath() { return "/error"; }
2つ目は org.junit.Assertの<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<? super T>)は推奨されません
で、これは JUnit 4 の assertThat メソッドを呼び出していたことが原因でした。AssertJ の assertThat に変更します。
再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。
履歴
2020/08/09
初版発行。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その2 )( Spring Boot を 2.2.2 → 2.2.9 へ、Gradle を 6.0.1 → 6.5.1 へバージョンアップする )
概要
記事一覧はこちらです。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その1 )( 概要 ) の続きです。
- 今回の手順で確認できるのは以下の内容です。
- Spring Boot のバージョンを 2.2 系の最新バージョンである 2.2.9 へ、Gradle のバージョンを 6.x 系の最新バージョンである 6.5.1 に上げて build できることを確認します。
- 今回は問題がなければライブラリはバージョンアップしません。
参照したサイト・書籍
目次
手順
2.3.x ブランチの作成
master から 2.3.x ブランチを、2.3.x から feature/135-issue ブランチを作成します。
Spring Boot を 2.2.2 → 2.2.9 にバージョンアップする
build.gradle の以下の点を変更します。
buildscript { ext { group "ksbysample" version "2.2.9-RELEASE" } repositories { mavenCentral() maven { url "https://repo.spring.io/release/" } gradlePluginPortal() } } plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.2.9.RELEASE" id "io.spring.dependency-management" version "1.0.9.RELEASE" id "groovy" id "checkstyle" id "com.github.spotbugs" version "3.0.0" id "pmd" id "net.ltgt.errorprone" version "1.1.1" id "com.gorylenko.gradle-git-properties" version "2.2.0" } ..........
- buildscript block の以下の点を変更します。
version "2.2.2-RELEASE"
→version "2.2.9-RELEASE"
- plugins block の以下の点を変更します。
id "org.springframework.boot" version "2.2.2.RELEASE"
→id "org.springframework.boot" version "2.2.9.RELEASE"
id "io.spring.dependency-management" version "1.0.8.RELEASE"
→id "io.spring.dependency-management" version "1.0.9.RELEASE"
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行。。。すると以下の画像のエラーが出ました。
Web で検索しても該当しそうな記事が見つかりません。
groovy の compile 時のエラーのようなので groovy のバージョンを確認したところ、2.2.2 の時は 2.5.8、2.2.9 の時は 2.5.13(https://mvnrepository.com/artifact/org.codehaus.groovy/groovy を見ると 2.5 系の最終バージョンの模様)でした。
build.gradle で groovy のバージョンを 2.5.12 にバージョンダウンすると Rebuild Project 実行時にエラーが出なくなりました。
dependencyManagement { imports { // mavenBom は以下の URL のものを使用する // https://repo.spring.io/release/org/springframework/boot/spring-boot-starter-parent/2.2.9.RELEASE/ // bomProperty に指定可能な property は以下の URL の BOM に記述がある // https://repo.spring.io/release/org/springframework/boot/spring-boot-dependencies/2.2.9.RELEASE/spring-boot-dependencies-2.2.9.RELEASE.pom mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) { // Spring Boot の BOM に定義されているバージョンから変更する場合には、ここに以下のように記述する // bomProperty "thymeleaf.version", "3.0.9.RELEASE" bomProperty "groovy.version", "2.5.12" } mavenBom("org.junit:junit-bom:5.5.2") } }
- dependencyManagement block に
bomProperty "groovy.version", "2.5.12"
を追加します。
build タスクを実行すると、今度は以下の画像のエラーが出ました。Caused by: org.dbunit.dataset.DataSetException Caused by: org.xml.sax.SAXNotSupportedException
で大量のエラーが発生しています。
Project Tool Window で src/test でコンテキストメニューを表示して「Run 'All Tests'」を選択してテストを実行し、もう少し詳しいエラーメッセージを見てみると、以下のエラーメッセージが出力されていました。
java.lang.RuntimeException: org.dbunit.dataset.DataSetException: not supported setting property http://xml.org/sax/properties/lexical-handler at ksbysample.common.test.extension.db.TestDataExtension.after(TestDataExtension.java:129) at ksbysample.common.test.extension.db.TestDataExtension.afterEach(TestDataExtension.java:75) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$11(TestMethodTestDescriptor.java:245) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$12(TestMethodTestDescriptor.java:256) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:256) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:255) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:244) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:141) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:69) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229) at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197) at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58) Caused by: org.dbunit.dataset.DataSetException: not supported setting property http://xml.org/sax/properties/lexical-handler at org.dbunit.dataset.xml.XmlProducer.buildException(XmlProducer.java:182) at org.dbunit.dataset.xml.FlatXmlProducer.produce(FlatXmlProducer.java:373) at org.dbunit.dataset.CachedDataSet.<init>(CachedDataSet.java:80) at org.dbunit.dataset.xml.FlatXmlDataSet.<init>(FlatXmlDataSet.java:110) at org.dbunit.dataset.xml.FlatXmlDataSetBuilder.buildInternal(FlatXmlDataSetBuilder.java:264) at org.dbunit.dataset.xml.FlatXmlDataSetBuilder.build(FlatXmlDataSetBuilder.java:111) at ksbysample.common.test.extension.db.TestDataExtension.restoreDb(TestDataExtension.java:207) at ksbysample.common.test.extension.db.TestDataExtension.after(TestDataExtension.java:126) ... 60 more Caused by: org.xml.sax.SAXNotSupportedException: not supported setting property http://xml.org/sax/properties/lexical-handler at org.gjt.xpp.sax2.Driver.setProperty(Driver.java:204) at org.dbunit.dataset.xml.FlatDtdProducer.setLexicalHandler(FlatDtdProducer.java:132) at org.dbunit.dataset.xml.FlatXmlProducer.produce(FlatXmlProducer.java:358) ... 66 more
build.gradle で testImplementation("org.dbunit:dbunit:2.6.0")
→ testImplementation("org.dbunit:dbunit:2.7.0")
にバージョンアップしても状況は変わりません(一旦 2.6.0 に戻しました)。
Web で調べると The SAX parser pull-parser conflicts with Tomcat SAX parser という Issue が見つかりました。同じエラーメッセージが出ていますが、pull-parser-2.jar を削除すると解消したとのこと。Error Parsing /index.xhtml: not supported setting property http://xml.org/sax/properties/lexical-handler の記事も見つけました。dom4j の optional なので外しても問題ないようです。
gradlew dependencies
を実行して pull-parser-2.jar に依存しているモジュールを探すと com.github.spotbugs:spotbugs:4.0.0-beta4
がヒットしました。
.......... +--- com.github.spotbugs:spotbugs:4.0.0-beta4 | +--- org.ow2.asm:asm:7.1 | +--- org.ow2.asm:asm-analysis:7.1 | | \--- org.ow2.asm:asm-tree:7.1 | | \--- org.ow2.asm:asm:7.1 | +--- org.ow2.asm:asm-commons:7.1 | | +--- org.ow2.asm:asm:7.1 | | +--- org.ow2.asm:asm-tree:7.1 (*) | | \--- org.ow2.asm:asm-analysis:7.1 (*) | +--- org.ow2.asm:asm-tree:7.1 (*) | +--- org.ow2.asm:asm-util:7.1 | | +--- org.ow2.asm:asm:7.1 | | +--- org.ow2.asm:asm-tree:7.1 (*) | | \--- org.ow2.asm:asm-analysis:7.1 (*) | +--- org.apache.bcel:bcel:6.3.1 | +--- net.jcip:jcip-annotations:1.0 | +--- org.dom4j:dom4j:2.1.1 -> 2.1.3 | | +--- jaxen:jaxen:1.1.6 -> 1.2.0 | | +--- javax.xml.stream:stax-api:1.0-2 | | +--- net.java.dev.msv:xsdlib:2013.6.1 | | | \--- relaxngDatatype:relaxngDatatype:20020414 | | +--- javax.xml.bind:jaxb-api:2.2.12 -> 2.3.1 | | | \--- javax.activation:javax.activation-api:1.2.0 | | +--- pull-parser:pull-parser:2 | | \--- xpp3:xpp3:1.1.4c | +--- jaxen:jaxen:1.1.6 -> 1.2.0 | +--- commons-lang:commons-lang:2.6 | +--- org.slf4j:slf4j-api:1.8.0-beta4 -> 1.7.30 | +--- net.sf.saxon:Saxon-HE:9.9.1-2 | | \--- com.ibm.icu:icu4j:63.1 | \--- com.github.spotbugs:spotbugs-annotations:4.0.0-beta4 | \--- com.google.code.findbugs:jsr305:3.0.2 ..........
build.gradle で com.github.spotbugs:spotbugs:4.0.0-beta4
の依存関係から pull-parser:pull-parser:2
を除外してみます。
dependencies { .......... // for SpotBugs compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}") { exclude group: "pull-parser", module: "pull-parser" } compileOnly("net.jcip:jcip-annotations:1.0") compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}") testImplementation("com.google.code.findbugs:jsr305:3.0.2") spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}") spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.10.1") }
exclude group: "pull-parser", module: "pull-parser"
を追加します。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新してから、再び clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると今度は無事 "BUILD SUCCESSFUL" のメッセージが出力されました。
Gradle を 6.0.1 → 6.5.1 にバージョンアップする
build.gradle の wrapper タスクの記述を以下のように変更します。
wrapper {
gradleVersion = "6.5.1"
distributionType = Wrapper.DistributionType.ALL
}
gradleVersion = "6.0.1"
→gradleVersion = "6.5.1"
に変更します。
コマンドプロンプトから gradlew wrapper --gradle-version 6.5.1
、gradlew --version
コマンドを実行します。
gradle/wrapper/gradle-wrapper.properties は以下の内容になります。
distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists
JVM を呼び出す時のメモリ割り当ての記述が元に戻るので、gradlew.bat 内の記述を set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
→ set DEFAULT_JVM_OPTS="-Xmx4096m"
に変更します(gradlew も同じような変更をします)。
Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します(少し時間がかかります)。
clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、spotbugsMain タスクでエラーになりました。'org.gradle.process.internal.worker.SingleRequestWorkerProcessBuilder org.gradle.process.internal.worker.WorkerProcessFactory.singleRequestWorker(java.lang.Class, java.lang.Class)'
というエラーメッセージが出力されています。
SpotBugs は後でバージョンアップする予定なので今回はコメントアウトすることにします。
build.gradle で SpotBugs の記述をコメントアウトします。 ただしソース内で SpotBug s のアノテーションを記述しているところがあるので compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}")
だけは残します。
.......... plugins { id "java" id "eclipse" id "idea" id "org.springframework.boot" version "2.2.9.RELEASE" id "io.spring.dependency-management" version "1.0.9.RELEASE" id "groovy" id "checkstyle" // id "com.github.spotbugs" version "3.0.0" id "pmd" id "net.ltgt.errorprone" version "1.1.1" id "com.gorylenko.gradle-git-properties" version "2.2.0" } .......... //spotbugs { // toolVersion = "4.0.0-beta4" // ignoreFailures = true // effort = "max" // spotbugsTest.enabled = false //} //tasks.withType(com.github.spotbugs.SpotBugsTask) { // reports { // xml.enabled = false // html.enabled = true // html.stylesheet = resources.text.fromArchiveEntry(configurations.spotbugsStylesheets, "color.xsl") // } //} .......... dependencies { .......... // for SpotBugs // compileOnly("com.github.spotbugs:spotbugs:${spotbugsVersion}") { // exclude group: "pull-parser", module: "pull-parser" // } // compileOnly("net.jcip:jcip-annotations:1.0") compileOnly("com.github.spotbugs:spotbugs-annotations:${spotbugsVersion}") // testImplementation("com.google.code.findbugs:jsr305:3.0.2") // spotbugsStylesheets("com.github.spotbugs:spotbugs:${spotbugsVersion}") // spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.10.1") }
再び clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると今度は無事 "BUILD SUCCESSFUL" のメッセージが出力されました。
履歴
2020/08/09
初版発行。
Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その1 )( 概要 )
概要
記事一覧はこちらです。
- 「Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る」で作成した Web アプリケーション ( ksbysample-webapp-lending ) の Spring Boot のバージョンを 2.2.2 → 2.3.x へバージョンアップします。
- 進め方は以下の方針とします。
- Git のブランチは 2.3.x を作成して、そちらで作業します。Spring Boot のバージョンと合わせます。
- Spring Boot のバージョンを 2.2 系の最新バージョンである 2.2.9 へ、Gradle のバージョンを 6.x 系の最新バージョンである 6.5.1 に上げて build できることを確認します。この時点ではライブラリはバージョンアップしません。
- Spring Boot のバージョン番号を 2.3.x にします。
- Spring Initializr で 2.3.x のプロジェクトを作成して、修正した方がよさそうな点があれば反映します。
- ライブラリは最新バージョンにアップデートします。ただし、この時点では checkstyle, spotbugs, pmd, Error Prone のバージョンは上げません。
- プロジェクトを build し直してエラーが出る点があれば修正し、まずはここまでで動くようにします。
- その後で 2.3 系ではこう書くべきという点があるか確認し、変更した方がよいところを変更します。
- checkstyle, spotbugs, pmd, Error Prone を1つずつ最新バージョンに上げます。変更した方がよいところがあれば変更します。
- docker-compose で使用している image を最新バージョンに上げます。
2.3 の Release Notes はこちらです。
Spring Boot 2.3 Release Notes
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes
履歴
2020/08/08
初版発行。