かんがるーさんの日記

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

Spring Boot 2.2.x の Web アプリを 2.3.x へバージョンアップする ( その15 )( Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする+domaGen タスクを doma-codegen-plugin を利用したものに作り直す )

概要

記事一覧はこちらです。

その14 ( Docker コンテナの image をバージョンアップする、Spring Boot Statistics のデータが表示されていない Panel を修正する+Dashboard に JVM (Micrometer) を追加する ) の続きです。

参照したサイト・書籍

  1. Doma 2 - User Documentation - Building an application - Build with Gradle
    https://doma.readthedocs.io/en/latest/build/?highlight=org.seasar.doma%3Adoma#build-with-gradle

  2. domaframework / doma-codegen-plugin
    https://github.com/domaframework/doma-codegen-plugin

  3. Doma入門 - ログライブラリにSLF4Jを使う
    https://qiita.com/nakamura-to/items/0f8195c45eb3630a8daf

  4. domaframework / getting-started
    https://github.com/domaframework/getting-started

  5. Doma入門
    https://qiita.com/nakamura-to/items/deaff05ba530317f3cf8

目次

  1. Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする
  2. domaGen タスクを doma-codegen-plugin を利用したものに作り直す
  3. clean タスク実行 → Rebuild Project 実行 → build タスクを実行する
  4. 警告:[MissingSummary] A summary line is required on public/protected Javadocs. の警告が出力されないようにする

手順

Doma 2 を 2.26.0 → 2.44.3 へバージョンアップする

https://doma.readthedocs.io/en/latest/build/?highlight=org.seasar.doma%3Adoma#build-with-gradle に従い build.gradle の以下の点を変更します。また Doma入門 - ログライブラリにSLF4Jを使うDoma 2 が SLF4J に対応したとの記事を読みました。org.seasar.doma:doma-slf4j を追加することにします。

..........

dependencies {
    def jdbcDriver = "org.postgresql:postgresql:42.2.14"
    def spockVersion = "1.3-groovy-2.5"
    def domaVersion = "2.44.3"
    def lombokVersion = "1.18.12"
    def errorproneVersion = "2.4.0"
    def powermockVersion = "2.0.7"
    def spotbugsVersion = "4.1.1"

    ..........

    // for Doma
    implementation("org.seasar.doma:doma-core:${domaVersion}")
    implementation("org.seasar.doma:doma-slf4j:${domaVersion}")
    annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}")
    domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")
    domaGenRuntime("${jdbcDriver}")
  • dependencies block の以下の点を変更します。
    • def domaVersion = "2.26.0"def domaVersion = "2.44.3" に変更します。
    • implementation("org.seasar.doma:doma:${domaVersion}")implementation("org.seasar.doma:doma-core:${domaVersion}") に変更します。
    • implementation("org.seasar.doma:doma-slf4j:${domaVersion}") を追加します。
    • annotationProcessor("org.seasar.doma:doma:${domaVersion}")annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}") に変更します。

domaGen タスクを doma-codegen-plugin を利用したものに作り直す

build.gradle を以下のように変更します。

buildscript {
    ..........
    dependencies {
        // for doma-codegen-plugin
        classpath "org.postgresql:postgresql:42.2.14"
    }
}

plugins {
    ..........
    id "com.gorylenko.gradle-git-properties" version "2.2.3"
    id "org.seasar.doma.codegen" version "1.2.1"
}

..........

configurations {
    compileOnly.extendsFrom annotationProcessor

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

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}

..........

// for doma-codegen-plugin
// まず変更が必要なもの
def rootPackageName = "ksbysample.webapp.lending"
def rootPackagePath = "src/main/java/ksbysample/webapp/lending"
def dbUrl = "jdbc:postgresql://localhost/ksbylending"
def dbUser = "ksbylending_user"
def dbPassword = "xxxxxxxx"
def dbTableNamePattern = ".*"
//def dbTableNamePattern = "user_info"
// おそらく変更不要なもの
def packageEntityPath = rootPackagePath + "/entity"
def packageDaoPath = rootPackagePath + "/dao"
def importOfComponentAndAutowiredDomaConfig = "${rootPackageName}.util.doma.ComponentAndAutowiredDomaConfig"
def workPath = "work"
def workEntityPath = "${workPath}/entity"
def workDaoPath = "${workPath}/dao"
task domaGen(group: "doma code generation") {
    // このタスク自体は何もしない。実行する時の起点用タスクとして作成している。
}
task beforeDomaCodeGen {
    doLast {
        // 作業用ディレクトリを削除する
        delete "${workPath}"

        // 現在の dao, entity パッケージのバックアップを取得する
        copy() {
            from "${packageDaoPath}"
            into "${workDaoPath}/org"
        }
        copy() {
            from "${packageEntityPath}"
            into "${workEntityPath}/org"
        }

        // dao, entity パッケージを削除する
        delete "${packageDaoPath}"
        delete "${packageEntityPath}"
    }
}
domaCodeGen {
    db {
        url = "${dbUrl}"
        user = "${dbUser}"
        password = "${dbPassword}"
        tableNamePattern = "${dbTableNamePattern}"
        ignoredTableNamePattern = "flyway_schema_history|SPRING_SESSION.*"
        entity {
            packageName = "${rootPackageName}.entity"
            useListener = false
            useMappedSuperclass = false
        }
        dao {
            packageName = "${rootPackageName}.dao"
        }
    }
}
task afterDomaCodeGen {
    doLast {
        // 生成された Entity クラスを作業用ディレクトリにコピーし、
        // @SuppressWarnings({"PMD.TooManyFields"}) アノテーションを付加する
        copy() {
            from "${packageEntityPath}"
            into "${workEntityPath}/replace"
            filter {
                line ->
                    line.replaceAll('@Entity', '@SuppressWarnings({"PMD.TooManyFields"})\n@Entity')
            }
        }

        // 生成された Dao インターフェースからバックアップにあるクラスを削除する
        // ※生成済の Dao インターフェースを再生成したい場合には事前に削除すること!
        for (workDaoFile in new File("${workDaoPath}/org").listFiles()) {
            def packageDaoFile = new File("${packageDaoPath}/${workDaoFile.name}")
            if (packageDaoFile.exists()) {
                packageDaoFile.delete()
            }
        }

        // 生成された Dao インターフェースを作業用ディレクトリにコピーし、
        // @ComponentAndAutowiredDomaConfig アノテーションを付加し、
        // Javadoc の @param に説明文を追加する
        copy() {
            from "${packageDaoPath}"
            into "${workDaoPath}/replace"
            filter {
                line ->
                    line.replaceAll('import org.seasar.doma.Dao;', "import ${importOfComponentAndAutowiredDomaConfig};\nimport org.seasar.doma.Dao;")
                            .replaceAll('@Dao', '@Dao\n@ComponentAndAutowiredDomaConfig')
                            .replaceAll('@param (\\S+)$', '@param $1 $1')
            }
        }

        // 元々 dao, entity パッケージ内にあったファイルを元に戻す
        copy() {
            from "${workDaoPath}/org"
            into "${packageDaoPath}"
        }
        copy() {
            from "${workEntityPath}/org"
            into "${packageEntityPath}"
        }

        // @ComponentAndAutowiredDomaConfig アノテーションを付加した Dao インターフェースを
        // dao パッケージへ戻す
        copy() {
            from "${workDaoPath}/replace"
            into "${packageDaoPath}"
        }

        // @SuppressWarnings({"PMD.TooManyFields"}) アノテーションを付加した Entity クラスを
        // entity パッケージへ戻す
        copy() {
            from "${workEntityPath}/replace"
            into "${packageEntityPath}"
        }

        // 作業用ディレクトリを削除する
        delete "${workPath}"
    }
}
// beforeDomaCodeGen --> domaCodeGenDbEntity --> domaCodeGenDbDao --> domaGen --> afterDomaCodeGen
domaCodeGenDbEntity.dependsOn beforeDomaCodeGen
domaCodeGenDbDao.dependsOn domaCodeGenDbEntity
domaGen.dependsOn domaCodeGenDbDao
domaGen.finalizedBy afterDomaCodeGen

..........
  • buildscript block に dependencies { classpath "org.postgresql:postgresql:42.2.14" } を追加します。
  • plugins block に id "org.seasar.doma.codegen" version "1.2.1" を追加します。
  • configurations block から domaGenRuntime を削除します。
  • dependencies block から以下の2行を削除します。
    • domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")
    • domaGenRuntime("${jdbcDriver}")
  • // for doma-codegen-plugindomaGen.finalizedBy afterDomaCodeGen の部分を追加します。
    • 実現したい内容は以下の点でした。
      • Entity クラス、Dao インターフェースは doma-codegen-plugin で既存のテーブルから生成する。
      • 生成された Entity クラス には @SuppressWarnings({"PMD.TooManyFields"}) を追加する。
      • 生成された Dao インターフェースには @ComponentAndAutowiredDomaConfig とその import 文を追加する。
    • Spring Boot + npm + Geb で入力フォームを作ってテストする ( その91 )( Doma 2 を 2.28.0 → 2.34.0 へバージョンアップする+domaGen タスクを doma-codegen-plugin を利用したものに作り直す ) で1度変更版を作成しましたが、domaGen タスクを何度も実行すると Enttiy クラスの @SuppressWarnings({"PMD.TooManyFields"}) や Dao インターフェースの @ComponentAndAutowiredDomaConfig が何度も追加されるという問題があることに今回見直していて気づきました。
    • そこで以下のように修正しています。
      • Dao インターフェースだけでなく Entity クラスもバックアップを取得する。
      • doma-codegen-plugin のタスク実行前に dao、entity パッケージを丸ごと削除する(dbTableNamePattern 変数に設定したテーブルの Dao インターフェース、Entity クラスだけが dao、entity パッケージに作成されるようにする)。
      • 既に生成したことがある Dao インターフェースの再生成は禁止したいので、afterDomaCodeGen タスク内でバックアップに存在する Dao インターフェースは dao パッケージから削除する。

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

今回改修した domaGen タスクでは dao、entity パッケージの下には何も変更が入っていない状態で、

f:id:ksby:20201223231110p:plain

domaGen タスクを実行しても、

f:id:ksby:20201223231239p:plain

dao、entity パッケージの下には何も変更はありません(色の付いたクラス、インターフェースがありません)。

f:id:ksby:20201223231336p:plain

user_info テーブルに test_column カラムを追加してから、

f:id:ksby:20201223231920p:plain

domaGen タスクを実行すると、

f:id:ksby:20201223232327p:plain

Dao インターフェースはそのままで UserInfo Entity クラスだけに変更が入ります。

f:id:ksby:20201223232814p:plain

clean タスク実行 → Rebuild Project 実行 → build タスクを実行する

clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると "BUILD SUCCESSFUL" のメッセージは出力されたのですが、警告:[MissingSummary] A summary line is required on public/protected Javadocs. (see http://google.github.io/styleguide/javaguide.html#s7.2-summary-fragment) という警告メッセージも出力されました。compileJava タスクで出力されているので Error Prone が出力しているようです。

f:id:ksby:20201223234656p:plain

警告:[MissingSummary] A summary line is required on public/protected Javadocs. の警告が出力されないようにする

今回変更しているのは build.gradle と Entity クラス(上には記述していませんが domaGen タスクで作り直しています)で、http://google.github.io/styleguide/javaguide.html#s7.2-summary-fragment を見たところ、Entity クラスのクラスコメントが空だったことが原因でした。

f:id:ksby:20201223235314p:plain

??? を書いておくことにします。

再度 clean タスク実行 → Rebuild Project 実行 → build タスクを実行すると今度は警告メッセージは出力されませんでした。

f:id:ksby:20201224000205p:plain

履歴

2020/12/24
初版発行。