かんがるーさんの日記

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

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その91 )( Doma 2 を 2.28.0 → 2.34.0 へバージョンアップする+domaGen タスクを doma-codegen-plugin を利用したものに作り直す )

概要

記事一覧はこちらです。

Spring Boot + npm + Geb で入力フォームを作ってテストする ( その90 )( Checkstyle を 8.19 → 8.32 へ、SpotBugs を 1.6.9 → 4.0.2 へ、PMD を 6.13.0 → 6.23.0 へ、error-prone を 2.3.3 → 2.3.4 へバージョンアップする ) の続きです。

終わったと思いましたが、domaGen タスクが動作しなかったので Doma 2 を最新バージョンまで上げていませんでした。最新バージョンに上げて domaGen タスクが動くようにします。

  • 今回の手順で確認できるのは以下の内容です。
    • Doma 2 を 2.28.0 → 2.34.0 へバージョンアップします。
    • 2.29.0 以降現行の domaGen タスクが動かなくなったので doma-codegen-plugin を利用したものに変更します。

参照したサイト・書籍

  1. 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

目次

  1. Doma 2 を 2.28.0 → 2.34.0 へバージョンアップする
  2. domaGen タスクを doma-codegen-plugin を利用したものに変更する

手順

Doma 2 を 2.28.0 → 2.34.0 へバージョンアップする

https://doma.readthedocs.io/en/latest/build/?highlight=org.seasar.doma%3Adoma#build-with-gradle に従い build.gradle の以下の点を変更します。この時点では Doma-Gen に関する設定は変更しません(build 時にエラーにはならないため)

dependencies {
    ..........
    def domaVersion = "2.34.0"
    ..........

    // for Doma
    implementation("org.seasar.doma:doma-core:${domaVersion}")
    annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}")
    domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")
    domaGenRuntime("com.h2database:h2:1.4.200")

    ..........
}
  • def domaVersion = "2.28.0"def domaVersion = "2.34.0" に変更します。
  • implementation("org.seasar.doma:doma:${domaVersion}")implementation("org.seasar.doma:doma-core:${domaVersion}") に変更します。
  • annotationProcessor("org.seasar.doma:doma:${domaVersion}")annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}") に変更します。

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

clean タスク実行 → Rebuild Project 実行 → build タスク実行をすると BUILD SUCCESSFUL が表示されます。

f:id:ksby:20200513223551p:plain

gebTest タスクも特に問題なく BUILD SUCCESSFUL が表示されました。

f:id:ksby:20200513225040p:plain

ただし domaGen タスクを実行すると Could not resolve all files for configuration ':domaGenRuntime'. のエラーメッセージが表示されて実行できません。

f:id:ksby:20200513225306p:plain

以前 Doma-Gen メンテナンス終了のアナウンスが出ていましたが、2.29.0 からなくなったようです。

domaGen タスクを doma-codegen-plugin を利用したものに変更する

doma-codegen-plugin がリリースされていますので、それを利用した方法に変更します。build.gradle を以下のように変更します。

buildscript {
    ..........
    dependencies {
        // for doma-codegen-plugin
        classpath "com.h2database:h2:1.4.200"
    }
}

plugins {
    ..........
    id "org.seasar.doma.codegen" version "0.0.2"
}

..........

configurations {
    developmentOnly
    runtimeClasspath {
        extendsFrom developmentOnly
    }

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

    // for SpotBugs
    spotbugsStylesheets { transitive = false }
}

..........

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

    // for Doma
    implementation("org.seasar.doma:doma-core:${domaVersion}")
    annotationProcessor("org.seasar.doma:doma-processor:${domaVersion}")

    ..........
}

..........

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

        // 現在の Dao インターフェースのバックアップを取得する
        copy() {
            from "${daoPackagePath}"
            into "${workDaoDirPath}/org"
        }
    }
}
domaCodeGen {
    db {
        url = "${dbUrl}"
        user = "${dbUser}"
        password = "${dbPassword}"
        tableNamePattern = "${dbTableNamePattern}"
        ignoredTableNamePattern = "flyway_schema_history|SPRING_SESSION.*"
        entity {
            packageName = "${rootPackageName}.entity"
            useListener = false
        }
        dao {
            overwrite = true
            packageName = "${rootPackageName}.dao"
        }
    }
}
task afterDomaCodeGen {
    doLast {
        // 生成された Entity クラスを作業用ディレクトリにコピーし、
        // @SuppressWarnings({"PMD.TooManyFields"}) アノテーションを付加する
        copy() {
            from "${entityPackagePath}"
            into "${workEntityDirPath}/replace"
            filter {
                line ->
                    line.replaceAll('@Entity', '@SuppressWarnings({"PMD.TooManyFields"})\n@Entity')
            }
        }

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

        // 生成された Dao インターフェースを作業用ディレクトリにコピーし、
        // @ComponentAndAutowiredDomaConfig アノテーションを付加し、
        // Javadoc の @param に説明文を追加する
        copy() {
            from "${daoPackagePath}"
            into "${workDaoDirPath}/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')
            }
        }

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

        // 元々 dao パッケージ内にあったファイルを元に戻す
        copy() {
            from "${workDaoDirPath}/org"
            into "${daoPackagePath}"
        }

        // 作業用ディレクトリを削除する
        delete "${workDirPath}"
    }
}
// 内部で domaCodeGenDbDao.dependsOn domaCodeGenDbEntity になっている
domaCodeGenDbEntity.dependsOn beforeDomaCodeGen
domaGen.dependsOn domaCodeGenDbDao
domaGen.finalizedBy afterDomaCodeGen
  • buildscript block に dependencies { classpath "com.h2database:h2:1.4.200" } を追加します。
  • plugins block に id "org.seasar.doma.codegen" version "0.0.2" を追加します。
  • configurations block から domaGenRuntime を削除します。
  • dependencies block から以下の行を削除します。
    • domaGenRuntime("org.seasar.doma:doma-gen:${domaVersion}")
    • domaGenRuntime("com.h2database:h2:1.4.200")
  • task domaGen { ... } は以下のように変更します。
    • 変数は全て domaGen タスクの外に出します。
    • domaGen タスクは何も実装しません(中の処理を全て削除します)。また (group: "doma code generation") を記述して domaGen タスクが doma code generation グループに表示されるようにします。
    • task beforeDomaCodeGen { ... } を追加します。
    • domaCodeGen { ... } を追加します。
    • task afterDomaCodeGen { ... } を追加します。
    • beforeDomaCodeGen → domaCodeGenDbEntity → domaCodeGenDbDao → domaGen(何も処理しない)→ afterDomaCodeGen の順で処理されるよう dependsOn、finalizedBy を設定します。

変更後、Gradle Tool Window の左上にある「Refresh all Gradle projects」ボタンをクリックして更新すると doma code generation グループが表示されて、その下に domaCodeGenDb~ で始まる各種タスクと domaGen タスクが表示されます。

f:id:ksby:20200515000016p:plain

Tomcat を起動してから domaGen タスクを実行すると BUILD SUCCESSFUL が表示され entity クラス、dao インターフェースが生成されます。

f:id:ksby:20200515000402p:plain

履歴

2020/05/15
初版発行。