かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その9 )( SpotBugs を 4.2.1 → 4.4.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その8 )( Error Prone を 2.5.1 → 2.9.0 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • SpotBugs を 4.1.1 → 4.4.0 へバージョンアップします。

参照したサイト・書籍

  1. SpotBugs
    https://spotbugs.github.io/

  2. spotbugs / spotbugs
    https://github.com/spotbugs/spotbugs

  3. spotbugs / spotbugs-gradle-plugin
    https://github.com/spotbugs/spotbugs-gradle-plugin

目次

  1. build.gradle を変更する

手順

build.gradle を変更する

plugins {
    id "java"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.5.4"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "groovy"
    id "checkstyle"
    id "com.github.spotbugs" version "4.7.3"
    id "pmd"
    id "net.ltgt.errorprone" version "2.0.2"
    id "com.gorylenko.gradle-git-properties" version "2.3.1"
    id "org.seasar.doma.codegen" version "1.4.1"
}
  • plugins block の以下の点を変更します。
    • id "com.github.spotbugs" version "4.6.1"id "com.github.spotbugs" version "4.7.3"
    • プラグインのバージョンを 4.7.3 にすることで SpotBugs のバージョンが 4.4.0 になります。SpotBugs version mapping 参照。

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると spotbugsMain タスクで 90 SpotBugs violations were found. See the report at: ... のメッセージが出力されました。

f:id:ksby:20210905170018p:plain

リンクをクリックしてレポートファイルを開いてみると「可変オブジェクトへの参照を返すことによって内部表現を暴露するかもしれないメソッド」「可変オブジェクトへの参照を取り込むことによって内部表現を暴露するかもしれないメソッド」の2種類の警告が出力されていましたが、コンストラクタインジェクションや getter メソッドを使用していると警告が出ているようで正直検知不要ですね。。。 excludeFilter を設定して検知されないようにします。

f:id:ksby:20210905170128p:plain f:id:ksby:20210905170247p:plain f:id:ksby:20210905170345p:plain f:id:ksby:20210905170439p:plain

最初に現在レポートファイルの定義を以下のように設定しているのですが、stylesheet = "color.xsl" を設定した今のレポートファイルでは Bug の code も pattern も出力してくれないことに気づいたので stylesheet = "color.xsl" を削除します。

spotbugsMain {
    reports {
        html {
            enabled = true
            stylesheet = "color.xsl"
        }
    }
}

spotbugsMain タスクだけ実行してレポートファイルを出力し直すと、今回警告が出た Bug の code は EI, EI2、pattern が EI_EXPOSE_REP, EI_EXPOSE_REP2 であることが分かります。

f:id:ksby:20210905174320p:plain f:id:ksby:20210905174405p:plain

config/spotbugs/exclude.xml を新規作成し、以下の内容を記述します。Bug は pattern で指定することにします。

<?xml version="1.0" encoding="UTF-8"?>
<FindBugsFilter
        xmlns="https://github.com/spotbugs/filter/3.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">
    <Match>
        <Bug pattern="EI_EXPOSE_REP,EI_EXPOSE_REP2"/>
    </Match>
</FindBugsFilter>

build.gradle の spotbugs block に excludeFilter = file("${rootProject.projectDir}/config/spotbugs/exclude.xml") を追加します。

spotbugs {
    toolVersion = "${spotbugs.toolVersion.get()}"
    ignoreFailures = true
    spotbugsTest.enabled = false
    excludeFilter = file("${rootProject.projectDir}/config/spotbugs/exclude.xml")
}
spotbugsMain {
    reports {
        html {
            enabled = true
        }
    }
}

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると警告は出力されず "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20210905210013p:plain

履歴

2021/09/05
初版発行。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その8 )( Error Prone を 2.5.1 → 2.9.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その7 )( PMD を 6.32.0 → 6.38.0 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Error Prone を 2.5.1 → 2.9.0 へバージョンアップします。

参照したサイト・書籍

  1. Error Prone
    https://errorprone.info/index

  2. tbroyer / gradle-errorprone-plugin
    https://github.com/tbroyer/gradle-errorprone-plugin

目次

  1. build.gradle を変更する
  2. エラーの原因を取り除く
    1. Return value of 'flatMap' must be used

手順

build.gradle を変更する

plugins {
    id "java"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.5.4"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "groovy"
    id "checkstyle"
    id "com.github.spotbugs" version "4.6.1"
    id "pmd"
    id "net.ltgt.errorprone" version "2.0.2"
    id "com.gorylenko.gradle-git-properties" version "2.3.1"
    id "org.seasar.doma.codegen" version "1.4.1"
}

..........

dependencies {
    def spockVersion = "2.0-groovy-3.0"
    def jdbcDriver = "org.postgresql:postgresql:42.2.23"
    def domaVersion = "2.47.1"
    def lombokVersion = "1.18.20"
    def errorproneVersion = "2.9.0"

    ..........
  • plugins block の以下の点を変更します。
    • id "net.ltgt.errorprone" version "1.3.0"id "net.ltgt.errorprone" version "2.0.2"
  • dependencies block の以下の点を変更します。
    • def errorproneVersion = "2.5.1"def errorproneVersion = "2.9.0"

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると compileJava タスクでエラーが 2個出ました。

f:id:ksby:20210904062403p:plain

エラーの原因を取り除く

Return value of 'flatMap' must be used

Error Prone の Bug Patterns の ReturnValueIgnored です。flatMap メソッドの戻り値を元のメソッドで使用していないことが原因でした。

f:id:ksby:20210904063254p:plain

エラーとなったメソッドでは if 文の代わりに Optional.flatMap メソッドを利用して処理を記述していて、戻り値を元のメソッドで使用する必要はないので、メソッドに @SuppressWarnings("ReturnValueIgnored") を付与してエラーにならないようにします。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20210904064136p:plain

履歴

2021/09/04
初版発行。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その7 )( PMD を 6.32.0 → 6.38.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その6 )( Release Notes を見て必要な箇所を変更する。。。ことがなさそうなので Checkstyle を 8.41 → 9.0 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • PMD を 6.32.0 → 6.38.0 へバージョンアップします。

参照したサイト・書籍

  1. PMD
    https://pmd.github.io/

目次

  1. build.gradle を変更する
  2. 警告の原因を取り除く
    1. Logger calls should be surrounded by log level guards.
    2. The constructor 'PagenationHelper(Page)' has a cognitive complexity of 15, current threshold is 15

手順

build.gradle を変更する

pmd {
    toolVersion = "6.38.0"
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    consoleOutput = true
    ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml")
    ruleSets = []
}
  • toolVersion = "6.32.0"toolVersion = "6.38.0" に変更します。

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると PMD で警告が出ました。

f:id:ksby:20210903064349p:plain

警告の原因を取り除く

警告は全部で 2種類、12箇所です。

f:id:ksby:20210903071233p:plain

Logger calls should be surrounded by log level guards.

Logger calls should be surrounded by log level guards. のリンクをクリックすると GuardLogStatement のページが開きました。

f:id:ksby:20210903071519p:plain

ログ出力時に isXxxEnabled メソッドでログレベルの有効性をチェックすべきという警告なのですが、実際に指摘された箇所を見ると info や error メソッドを呼び出してログを出力している箇所だったので isXxxEnabled メソッドを付けるのは避けたいかな。。。

今回は config/pmd/pmd-project-rulesets.xml に設定を追加して、trace, debug のログ出力だけこのチェックが実行されるようにします。

    <rule ref="category/java/bestpractices.xml">
        <!-- CommentRequired はここでは exclude し、下で別途定義する -->
        <exclude name="GuardLogStatement"/>
    </rule>
    <rule ref="category/java/bestpractices.xml/GuardLogStatement">
        <properties>
            <property name="logLevels" value="trace,debug"/>
            <property name="guardsMethods" value="isTraceEnabled,isDebugEnabled"/>
        </properties>
    </rule>

The constructor 'PagenationHelper(Page)' has a cognitive complexity of 15, current threshold is 15

The constructor 'PagenationHelper(Page)' has a cognitive complexity of 15, current threshold is 15 のリンクをクリックすると CognitiveComplexity のページが開きました。

f:id:ksby:20210903072647p:plain

src/main/java/ksbysample/webapp/lending/helper/page/PagenationHelper.java のメソッドが複雑なので警告が出ているのですが、今回はメソッドに @SuppressWarnings("PMD.CognitiveComplexity") を付与して警告が出ないようにします。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると無事 "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20210903211013p:plain

履歴

2021/09/03
初版発行。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その6 )( Release Notes を見て必要な箇所を変更する。。。ことがなさそうなので Checkstyle を 8.41 → 9.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その5 )( Spock を 1.3-groovy-2.5 → 2.0-groovy-3.0 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 以下のドキュメントを見て必要な箇所を変更します。。。と思ったのですが、今回は変更が必要なところがありませんでした。
    • ただし Secure Info Endpointexposing リンクへ飛んだ先の 6.2.3. Securing HTTP Endpoints を見たところ SecurityConfiguration クラスの実装方法が全然違う!と思ったのですが、Spring Security Reference の 16.3. Multiple HttpSecurity を読んで今のままで変更する必要はありませんでした。
    • Checkstyle を 8.41 → 9.0 へバージョンアップします。
    • 最新版の google_checks.xml の内容も反映します。

参照したサイト・書籍

  1. checkstyle / checkstyle
    https://github.com/checkstyle/checkstyle

  2. checkstyle/checkstyle - checkstyle/src/main/resources/google_checks.xml
    https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml

目次

  1. build.gradle を変更する
  2. 最新版の google_checks.xml から変更点を反映する
  3. IntelliJ IDEA の CheckStyle-IDEA Plugin が使用する Checkstyle のバージョンを 8.45 に変更する
  4. @SuppressWarnings("checkstyle:...") が効かないことに気づいたので SuppressWarningsFilter、SuppressWarningsHolder を追加する

手順

build.gradle を変更する

checkstyle {
    configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml")
    toolVersion = "9.0"
    sourceSets = [project.sourceSets.main]
}
  • toolVersion = "8.41"toolVersion = "9.0" に変更します。

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新した後、clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると checkstyleMain タスクで Unable to create Root Module: ... というエラーメッセージが出力されました。

f:id:ksby:20210903021227p:plain

先に最新版の google_checks.xml の変更点を反映して、解決しなければ調査することにします。

最新版の google_checks.xml から変更点を反映する

最新版の google_checks.xml から変更点を反映します。今回反映した内容を箇条書きで記述しておきます。

  • <module name="NoWhitespaceBeforeCaseDefaultColon"/> を追加しました(https://checkstyle.org/config_whitespace.html#NoWhitespaceBeforeCaseDefaultColon)。
  • <module name="OperatorWrap"><property name="tokens">valueTYPE_EXTENSION_AND を追加しました。
  • <module name="JavadocMethod"><property name="scope" value="public"/><property name="accessModifiers" value="public"/> に変更しました。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると BUILD SUCCESSFUL が表示されましたが、WARNING が1個出力されました。以下の点を変更します。

f:id:ksby:20210903025149p:plain

  • Javadoc コメントがありません。 [com.puppycrawl.tools.checkstyle.checks.javadoc.MissingJavadocMethodCheck]
    • 以前は WARNING が出なかった src/main/java/ksbysample/webapp/lending/values/validation/ValuesEnum.java の @interface List 内のメソッドの Javadoc コメントがない点を指摘してくれるようになったようです。Javadoc コメントを追加します。

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると WARNING が出なくなりました。

f:id:ksby:20210903030436p:plain

IntelliJ IDEA の CheckStyle-IDEA Plugin が使用する Checkstyle のバージョンを 8.45 に変更する

CheckStyle-IDEA Plugin に指定できるバージョンが 8.45 までだったので 8.45 を指定します。

f:id:ksby:20210903031222p:plain

@SuppressWarnings("checkstyle:...") が効かないことに気づいたので SuppressWarningsFilter、SuppressWarningsHolder を追加する

今の設定だと @SuppressWarnings("checkstyle:...") が効かないことに気づいたので config/checkstyle/google_checks.xml を以下のように変更します。

    ..........

    <module name="SuppressWarningsFilter"/>

    <module name="TreeWalker">
        <module name="SuppressWarningsHolder"/>
        <module name="OuterTypeFilename"/>
        ..........
  • 以下の2行を追加します。
    • <module name="SuppressWarningsFilter"/>
    • <module name="SuppressWarningsHolder"/>

履歴

2021/09/03
初版発行。
2021/09/08
* @SuppressWarnings("checkstyle:...") が効かないことに気づいたので SuppressWarningsFilter、SuppressWarningsHolder を追加する を追加しました。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その5 )( Spock を 1.3-groovy-2.5 → 2.0-groovy-3.0 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その4 )( Gradle を 6.9.1 → 7.2 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Spock を 1.3-groovy-2.5 → 2.0-groovy-3.0 へバージョンアップします。
    • Spock を 2系にバージョンアップすると JUnit 5 ベースになるので、PowerMock で作成している static method のテストを Mockito で書き直して PowerMock を依存関係から削除します。

参照したサイト・書籍

  1. Spock
    https://spockframework.org/

  2. Spock - Migration Guide
    https://spockframework.org/spock/docs/2.0/migration_guide.html

  3. Apache Groovy
    https://groovy-lang.org/index.html

  4. Groovy Language Documentation Version 3.0.8
    http://docs.groovy-lang.org/docs/groovy-3.0.8/html/documentation/

  5. Junit5 mock a static method
    https://stackoverflow.com/questions/52830441/junit5-mock-a-static-method

目次

  1. Spock を 1.3-groovy-2.5 → 2.0-groovy-3.0 へバージョンアップする
  2. PowerMock で作成している static method のテストを Mockito で書き直して PowerMock を依存関係から削除する
  3. @Unroll アノテーションを削除する

手順

Spock を 1.3-groovy-2.5 → 2.0-groovy-3.0 へバージョンアップする

build.gradle の以下の点を変更します。

dependencyManagement {
    imports {
        // bomProperty に指定可能な property は以下の URL の BOM に記述がある
        // https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/2.5.4/spring-boot-dependencies-2.5.4.pom
        mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) {
            // Spring Boot の BOM に定義されているバージョンから変更する場合には、ここに以下のように記述する
            // bomProperty "thymeleaf.version", "3.0.9.RELEASE"
        }
        mavenBom("org.junit:junit-bom:5.7.2")
    }
}

dependencies {
    def spockVersion = "2.0-groovy-3.0"
    ..........
}

..........

clean {
    doLast {
        rootProject.file("src/main/generated").deleteDir()
        rootProject.file("src/test/generated_tests").deleteDir()
    }
}

test {
    jvmArgs = jvmArgsForTask +
            jvmArgsAddOpens +
            ["-Dspring.profiles.active=unittest"]

    // for JUnit 5
    useJUnitPlatform()

    testLogging {
        afterSuite printTestCount
    }
}

..........
  • dependencyManagement block の以下の点を変更します。
    • bomProperty "groovy.version", "2.5.12" を削除します。これにより groovy のバージョンが 3.0.8 になります(Spring Boot 2.5.4 の Dependency Versionsorg.codehaus.groovy:groovy 参照)。
  • dependencies block の以下の点を変更します。
    • def spockVersion = "1.3-groovy-2.5"def spockVersion = "2.0-groovy-3.0"
  • テストが全て Junit 5 ベースになることにより testJUnit4AndSpock タスクが不要になるので、以下の記述を削除します。
    • task testJUnit4AndSpock(type: Test) { ... }
    • test.dependsOn testJUnit4AndSpock

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

clean タスク実行 → Rebuild Project 実行をすると、Groovyc: unable to resolve class groovy.sql.Sql というエラーが出力されました。

f:id:ksby:20210829170823p:plain

src/test/groovy/ksbysample/webapp/lending/SampleTest.groovy を見ると groovy.sql.Sql が赤く表示されており package が存在しないようです。

f:id:ksby:20210829170957p:plain

Groovy Language Documentation Version 3.0.8 を見ると 3.8. Interacting with a SQL database に groovy-sql module が必要であるとの記述がありました。 build.gradle の dependencies block に testImplementation("org.codehaus.groovy:groovy-sql") を追加します。

dependencies {
    ..........

    // dependency-management-plugin によりバージョン番号が自動で設定されるもの
    // Appendix F. Dependency versions ( https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html ) 参照
    ..........
    testImplementation("org.yaml:snakeyaml")
    testImplementation("org.codehaus.groovy:groovy-sql")

    ..........

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20210829172230p:plain

PowerMock で作成している static method のテストを Mockito で書き直して PowerMock を依存関係から削除する

src/test/groovy/ksbysample/webapp/lending/SampleHelperTest.groovy に記述した PowerMock で作成している static method のテストを、

package ksbysample.webapp.lending

import org.junit.Test
import org.junit.experimental.runners.Enclosed
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner
import spock.lang.Specification
import spock.lang.Unroll

import javax.crypto.NoSuchPaddingException

import static org.assertj.core.api.Assertions.assertThatExceptionOfType

@RunWith(Enclosed)
class SampleHelperTest {

    ..........

    @RunWith(PowerMockRunner)
    @PowerMockRunnerDelegate(SpringRunner)
    @SpringBootTest
    @PrepareForTest(BrowfishUtils)
    @PowerMockIgnore(["javax.management.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.dom.*"])
    static class 異常処理のテスト {

        @Autowired
        private SampleHelper sampleHelper

        @Test
        void "SampleHelper_encryptを呼ぶとRuntimeExceptionをthrowする"() {
            // setup:
            PowerMockito.mockStatic(BrowfishUtils)
            PowerMockito.when(BrowfishUtils.encrypt(Mockito.any()))
                    .thenThrow(new NoSuchPaddingException())

            // expect:
            assertThatExceptionOfType(RuntimeException).isThrownBy({
                sampleHelper.encrypt("test")
            })
        }

    }

}

以下のように変更します。

package ksbysample.webapp.lending

import org.junit.experimental.runners.Enclosed
import org.junit.jupiter.api.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification
import spock.lang.Unroll

import javax.crypto.NoSuchPaddingException

import static org.assertj.core.api.Assertions.assertThatThrownBy

@RunWith(Enclosed)
class SampleHelperTest {

    ..........

    @SpringBootTest
    static class 異常処理のテスト {

        @Autowired
        private SampleHelper sampleHelper

        @Test
        void "SampleHelper_encryptを呼ぶとRuntimeExceptionをthrowする"() {
            // setup:
            Mockito.mockStatic(BrowfishUtils)
            Mockito.when(BrowfishUtils.encrypt(Mockito.any()))
                    .thenThrow(new NoSuchPaddingException())

            // expect:
            assertThatThrownBy(() -> {
                sampleHelper.encrypt("test")
            }).isInstanceOf(RuntimeException)
        }

    }

}

Mockito で static method のテストを実装するには mockito-inline が必要なので、build.gradle の以下の点を変更します。

dependencies {
    ..........

    // dependency-management-plugin によりバージョン番号が自動で設定されるもの
    // Appendix F. Dependency versions ( https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-dependency-versions.html ) 参照
    ..........
    testImplementation("org.codehaus.groovy:groovy-sql")
    testImplementation("org.mockito:mockito-inline")
  • dependencies から以下の行を削除して PowerMock を依存関係から削除します。
    • def powermockVersion = "2.0.9"
    • testImplementation("org.powermock:powermock-module-junit4:${powermockVersion}")
    • testImplementation("org.powermock:powermock-api-mockito2:${powermockVersion}")
  • testImplementation("org.mockito:mockito-inline") を追加します。

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

変更したテストを実行すると無事成功しました。

f:id:ksby:20210829182824p:plain

@Unroll アノテーションを削除する

Spock の Migration GuideUnroll changes を読むと @Unroll アノテーションがなくても Data Driven テストが動作するようになったとのことなので、@Unroll アノテーションを削除します。

削除後に clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されて、テスト数も削除前と同じでした。

f:id:ksby:20210829211838p:plain

履歴

2021/08/29
初版発行。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その4 )( Gradle を 6.9.1 → 7.2 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その3 )( Spring Boot を 2.4.10 → 2.5.4 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Gradle を 6.9.1 → 7.2 へバージョンアップします。

参照したサイト・書籍

  1. Upgrading your build from Gradle 6.x to the latest
    https://docs.gradle.org/7.2/userguide/upgrading_version_6.html

  2. What's new in Gradle 7.0
    https://gradle.org/whats-new/gradle-7/

目次

  1. Gradle を 6.9.1 → 7.2 にバージョンアップする
  2. build 時のエラーを解消する
    1. bootJar タスクでエラーが発生する
    2. jar タスクでエラーが発生する
  3. build.gradle で Deprecated になった記述を修正する

手順

Gradle を 6.9.1 → 7.2 にバージョンアップする

build.gradle の wrapper タスクの記述を以下のように変更します。

wrapper {
    gradleVersion = "7.2"
    distributionType = Wrapper.DistributionType.ALL
}
  • gradleVersion = "6.9.1"gradleVersion = "7.2" に変更します。

コマンドプロンプトから gradlew wrapper --gradle-version=7.2gradlew --version コマンドを実行します。

f:id:ksby:20210825062251p:plain

gradle/wrapper/gradle-wrapper.properties は以下の内容になります。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新します。

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると bootJar タスクでエラーが発生しました。

f:id:ksby:20210825063131p:plain

build 時のエラーを解消する

bootJar タスクでエラーが発生する

以下のエラーメッセージが出力されていました。

Entry BOOT-INF/classes/META-INF/ksbysample/webapp/lending/dao/LendingAppDao/selectById.sql is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.2/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.

URL の先の Gradle 7.2 のマニュアルを見ると duplicatesStrategy というプロパティがあるとのこと。このプロジェクトではリソースを2重にコピーしても問題ないので、bootJar タスクに duplicatesStrategy = DuplicatesStrategy.INCLUDE を設定します。

..........
tasks.named("compileTestJava").configure {
    options.errorprone.enabled = false
}
bootJar {
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

..........

jar タスクでエラーが発生する

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、今度は jar タスクでエラーが発生しました。

f:id:ksby:20210825211823p:plain

jar タスクは不要なので(build/libs の下に ksbysample-webapp-lending-2.5.4.jar 以外に ksbysample-webapp-lending-2.5.4-plain.jar が生成されます)、Spring Boot 2.5 Release Notes の Gradle Default jar and war Tasks、及び Spring Boot Gradle Plugin Reference Guide の 4.3. Packaging Executable and Plain Archives を見て build.gradle で jar タスクを無効にします。

..........
bootJar {
    duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
jar {
    enabled = false
}

..........

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、今度は "BUILD SUCCESSFUL" のメッセージが出力されました。また以前は出力されていた Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. のメッセージが出力されなくなりました。

f:id:ksby:20210825213331p:plain

build.gradle で Deprecated になった記述を修正する

copyDomaResources タスク内の compileJava.destinationDir メソッドが Deprecated となっていたので、

f:id:ksby:20210825233605p:plain

into compileJava.destinationDirectory プロパティに変更します。

task copyDomaResources(type: Sync) {
    from sourceSets.main.resources.srcDirs
    into compileJava.destinationDirectory
    include "doma.compile.config"
    include "META-INF/**/*.sql"
    include "META-INF/**/*.script"
}
compileJava.dependsOn copyDomaResources

変更後に clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると、問題なく "BUILD SUCCESSFUL" のメッセージが出力されました。

最後に .gradle ディレクトリの下にバージョン番号のディレクトリがあるので、7.2 以外を削除します。

履歴

2021/08/26
初版発行。
2021/09/11
* 「参照したサイト・書籍」に What's new in Gradle 7.0 を追加しました。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その3 )( Spring Boot を 2.4.10 → 2.5.4 へバージョンアップする )

概要

記事一覧はこちらです。

Spring Boot 2.4.x の Web アプリを 2.5.x へバージョンアップする ( その2 )( Spring Boot を 2.4.3 → 2.4.10 へ、Gradle を 6.8.3 → 6.9.1 へバージョンアップする ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Spring Boot を 2.4.10 → 2.5.4 へバージョンアップします。
    • Spring Boot を 2.5.4 にバージョンアップすると Groovy も 3系にバージョンアップするのですが、今回は Spock のバージョンアップはしないので 2系のままにします。

参照したサイト・書籍

目次

  1. Spring Initializr で 2.5.4 のプロジェクトを作成する
  2. build.gradle を変更する

手順

Spring Initializr で 2.5.4 のプロジェクトを作成する

Spring Initializr で 2.5.4 のプロジェクトを作成して、生成された build.gradle を見て反映した方が良い点があるか確認します。

f:id:ksby:20210821221949p:plain f:id:ksby:20210821222258p:plain f:id:ksby:20210821222332p:plain f:id:ksby:20210821222432p:plain f:id:ksby:20210821222602p:plain

以下の build.gradle が作成されました。

plugins {
    id 'org.springframework.boot' version '2.5.4'
    id 'io.spring.dependency-management' version '1.0.11.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'
    implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
    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'
    testImplementation 'org.springframework.security:spring-security-test'
}

test {
    useJUnitPlatform()
}

今回は反映した方が良さそうな点はありませんでした。

build.gradle を変更する

buildscript {
    ext {
        group "ksbysample"
        version "2.5.4"
    }
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/release/" }
        gradlePluginPortal()
    }
    dependencies {
        // for doma-codegen-plugin
        classpath "org.postgresql:postgresql:42.2.23"
    }
}

plugins {
    id "java"
    id "eclipse"
    id "idea"
    id "org.springframework.boot" version "2.5.4"
    id "io.spring.dependency-management" version "1.0.11.RELEASE"
    id "groovy"
    id "checkstyle"
    id "com.github.spotbugs" version "4.6.1"
    id "pmd"
    id "net.ltgt.errorprone" version "1.3.0"
    id "com.gorylenko.gradle-git-properties" version "2.3.1"
    id "org.seasar.doma.codegen" version "1.4.1"
}

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

wrapper {
    gradleVersion = "6.9.1"
    distributionType = Wrapper.DistributionType.ALL
}

[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
        disable("SameNameButDifferent")
    }
}
tasks.named("compileTestJava").configure {
    options.errorprone.enabled = false
}

// for Doma 2
// Copy the resources referred by the Doma annotation processors to
// the destinationDir of the compileJava task
task copyDomaResources(type: Sync) {
    from sourceSets.main.resources.srcDirs
    into compileJava.destinationDir
    include "doma.compile.config"
    include "META-INF/**/*.sql"
    include "META-INF/**/*.script"
}
compileJava.dependsOn copyDomaResources

springBoot {
    buildInfo()
}

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

configurations {
    compileOnly.extendsFrom annotationProcessor

    // annotationProcessor と testAnnotationProcessor、compileOnly と testCompileOnly を併記不要にする
    testAnnotationProcessor.extendsFrom annotationProcessor
    testImplementation.extendsFrom compileOnly

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}

checkstyle {
    configFile = file("${rootProject.projectDir}/config/checkstyle/google_checks.xml")
    toolVersion = "8.41"
    sourceSets = [project.sourceSets.main]
}

spotbugs {
    toolVersion = "${spotbugs.toolVersion.get()}"
    ignoreFailures = true
    spotbugsTest.enabled = false
}
spotbugsMain {
    reports {
        html {
            enabled = true
            stylesheet = "color.xsl"
        }
    }
}

pmd {
    toolVersion = "6.32.0"
    sourceSets = [project.sourceSets.main]
    ignoreFailures = true
    consoleOutput = true
    ruleSetFiles = rootProject.files("/config/pmd/pmd-project-rulesets.xml")
    ruleSets = []
}

repositories {
    mavenCentral()
}

dependencyManagement {
    imports {
        // bomProperty に指定可能な property は以下の URL の BOM に記述がある
        // https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/2.5.4/spring-boot-dependencies-2.5.4.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.7.2")
    }
}

dependencies {
    def spockVersion = "1.3-groovy-2.5"
    def jdbcDriver = "org.postgresql:postgresql:42.2.23"
    def domaVersion = "2.47.1"
    def lombokVersion = "1.18.20"
    def errorproneVersion = "2.5.1"
    def powermockVersion = "2.0.9"

    // 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-validation")
    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")
    annotationProcessor("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")
    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.9.1")
    implementation("com.google.guava:guava:30.1.1-jre")
    implementation("org.flywaydb:flyway-core:7.14.0")
    testImplementation("org.dbunit:dbunit:2.7.2") {
        exclude group: "postgresql", module: "postgresql"
    }
    testImplementation("com.icegreen:greenmail:1.6.5")
    testImplementation("org.assertj:assertj-core:3.20.2")
    testImplementation("com.jayway.jsonpath:json-path:2.6.0")
    testImplementation("org.jsoup:jsoup:1.14.2")
    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
    implementation("org.seasar.doma:doma-core:${domaVersion}")
    implementation("org.seasar.doma:doma-slf4j:${domaVersion}")
    annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}")

    // 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
    spotbugs(configurations.spotbugsPlugins.dependencies)
    annotationProcessor("com.github.spotbugs:spotbugs-annotations:${spotbugs.toolVersion.get()}")
    spotbugsPlugins("com.h3xstream.findsecbugs:findsecbugs-plugin:1.11.0")
}

..........

Spring Boot 2.5.4 へのバージョンアップとして以下の点を変更します。

  • buildscript block の以下の点を変更します。
    • version "2.4.10"version "2.5.4"
  • plugins block の以下の点を変更します。
    • id "org.springframework.boot" version "2.4.10"id "org.springframework.boot" version "2.5.4"

各種ライブラリのバージョンアップとして以下の点を変更します。

  • buildscript block の以下の点を変更します。
    • classpath "org.postgresql:postgresql:42.2.19"classpath "org.postgresql:postgresql:42.2.23"
  • plugins block の以下の点を変更します。
    • id "com.gorylenko.gradle-git-properties" version "2.2.4"id "com.gorylenko.gradle-git-properties" version "2.3.1"
    • id "org.seasar.doma.codegen" version "1.2.1"id "org.seasar.doma.codegen" version "1.4.1"
  • dependencyManagement block の以下の点を変更します。
    • mavenBom("org.junit:junit-bom:5.7.1")mavenBom("org.junit:junit-bom:5.7.2")
  • dependencies block の以下の点を変更します。
    • def jdbcDriver = "org.postgresql:postgresql:42.2.19"def jdbcDriver = "org.postgresql:postgresql:42.2.23"
    • def domaVersion = "2.45.0"def domaVersion = "2.47.1"
    • def lombokVersion = "1.18.18"def lombokVersion = "1.18.20"
    • implementation("com.google.guava:guava:30.1-jre")implementation("com.google.guava:guava:30.1.1-jre")
    • implementation("org.flywaydb:flyway-core:7.5.4")implementation("org.flywaydb:flyway-core:7.14.0")
    • testImplementation("org.dbunit:dbunit:2.7.0")testImplementation("org.dbunit:dbunit:2.7.2")
    • testImplementation("com.icegreen:greenmail:1.6.2")testImplementation("com.icegreen:greenmail:1.6.5")
    • testImplementation("org.assertj:assertj-core:3.19.0")testImplementation("org.assertj:assertj-core:3.20.2")
    • testImplementation("com.jayway.jsonpath:json-path:2.5.0")testImplementation("com.jayway.jsonpath:json-path:2.6.0")
    • testImplementation("org.jsoup:jsoup:1.13.1")testImplementation("org.jsoup:jsoup:1.14.2")

clean タスク実行 → Rebuild Project 実行すると以下のエラーメッセージが表示されました。

f:id:ksby:20210822225356p:plain

ErrorController インターフェースを実装しているクラスで getErrorPath メソッドをオーバーライドしている箇所で、2.4系にバージョンアップした時には @SuppressWarnings("deprecation") を付けて警告が出ないようにしていたのですが、2.5 でメソッドが削除されたので削除します。

f:id:ksby:20210822231148p:plain

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージが出力されました。

f:id:ksby:20210822231101p:plain

履歴

2021/08/22
初版発行。