かんがるーさんの日記

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

Gradle で Multi-project を作成する ( その13 )( doma2lib+cmdapp+webapp編、PropertiesLauncher を利用して doma2-lib の jar ファイルを外部に出す )

概要

記事一覧はこちらです。

Gradle で Multi-project を作成する ( その12 )( doma2lib+cmdapp+webapp編、sample-webapp プロジェクトを作成する ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • Doma 2 の Entity、Dao を提供するライブラリ+Spring Boot ベースのコマンドラインアプリケーション+Spring Boot ベースの Web アプリケーションの Multi-project を作成します。
    • doma2lib+cmdapp+webapp編のここまでの記事では実行可能 Jar ファイルを起動するのに JarLauncher を利用する方式でしたので sample-cmdapp-1.0.0-RELEASE.jar、sample-webapp-1.0.0-RELEASE.jar の中に doma2-lib-1.0.0-RELEASE.jar が入っていましたが、PropertiesLauncher を利用する方式に変更して doma2-lib-1.0.0-RELEASE.jar を外部に出すようにしてみます。

参照したサイト・書籍

  1. E.3 Launching Executable Jars
    https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html#executable-jar-launching

  2. Spring Boot 2 and external libs with the PropertiesLauncher
    https://medium.com/saas-startup-factory/spring-boot-2-and-external-libs-with-the-propertieslauncher-fc49d2d93636

  3. Gradle Docs 5.4.1 - Copy
    https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Copy.html

目次

  1. gradle-multiprj-doma2lib-cmdwebapp の build.gradle を変更する
  2. sample-cmdapp、sample-webapp の build.gradle を変更する
  3. clean タスク実行 → Rebuild Project 実行 → build タスク実行を行う
  4. 動作確認
  5. sample-webapp を IntelliJ IDEA の Run Dashboard から起動するとどうなるのか?
  6. 次回は。。。

手順

gradle-multiprj-doma2lib-cmdwebapp の build.gradle を変更する

PropertiesLauncher を利用するのに必要な設定と、jar ファイルを gradle-multiprj-doma2lib-cmdwebapp プロジェクトのルートディレクトリ直下の libs ディレクトリ(新規に作成します)にコピーするための task を gradle-multiprj-doma2lib-cmdwebapp の build.gradle に記述します。

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

..........

subprojects {
    ..........

    // サブプロジェクトの build/libs の下に生成された jar ファイルを
    // プロジェクトのルートディレクトリ直下の libs ディレクトリにコピーする
    task copyJarToLibsDir(type: Copy) {
        from "build/libs"
        include "*.jar"
        into "${rootDir}/libs"
    }
    copyJarToLibsDir.dependsOn test
    check.dependsOn copyJarToLibsDir
}

configure(subprojects.findAll { it.name ==~ /^(doma2-lib|sample-cmdapp|sample-webapp)$/ }) {
    ..........
}

configure(subprojects.findAll { it.name ==~ /^(sample-cmdapp|sample-webapp)$/ }) {
    bootJar {
        manifest {
            attributes 'Main-Class': 'org.springframework.boot.loader.PropertiesLauncher'
        }
    }
}
  • subproject block 内に task copyJarToLibsDir(type: Copy) { ... } を追加します。また test タスクの後に実行するために copyJarToLibsDir.dependsOn testcheck.dependsOn copyJarToLibsDir の2行を追加します。
  • configure は複数記述できるようなので、sample-cmdapp、sample-webapp だけに適用する設定を記述する configure(subprojects.findAll { it.name ==~ /^(sample-cmdapp|sample-webapp)$/ }) { ... } を追加します。この中に PropertiesLauncher を利用するのに必要な設定を記述します。

またプロジェクトのルートディレクトリ直下に libs ディレクトリを作成しておきます。

sample-cmdapp、sample-webapp の build.gradle を変更する

sample-cmdapp、sample-webapp の build.gradle では doma2-lib への依存関係を implementation で記述しており、このままでは jar ファイル内に doma2-lib-1.0.0-RELEASE.jar が含まれてしまうので、implementation project(":doma2-lib")compileOnly project(":doma2-lib") に変更します。

■sample-cmdapp の build.gradle

dependencies {
    implementation("org.springframework.boot:spring-boot-starter")

    compileOnly project(":doma2-lib")
    implementation("com.univocity:univocity-parsers:2.8.1")
    implementation("args4j:args4j:2.33")
    implementation("com.github.rozidan:modelmapper-spring-boot-starter:1.0.0")
}

■sample-webapp の build.gradle

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    runtimeOnly("org.springframework.boot:spring-boot-devtools")

    compileOnly project(":doma2-lib")
}

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

clean タスク実行 → Rebuild Project 実行 → build タスク実行を行う

必要な設定は以上で完了です。clean タスク実行 → Rebuild Project 実行 → build タスク実行を行い、jar ファイルを生成し直して libs ディレクトリに集めます。

エラーメッセージは出ずに BUILD SUCCESSFUL が出力されています。各サブプロジェクトの test タスクの後では copyJarToLibsDir タスクが実行されて、

f:id:ksby:20190501224807p:plain f:id:ksby:20190501224943p:plain

libs ディレクトリの下に doma2-lib-1.0.0-RELEASE.jar、sample-cmdapp-1.0.0-RELEASE.jar、sample-webapp-1.0.0-RELEASE.jar がコピーされています。

f:id:ksby:20190501225129p:plain

sample-cmdapp-1.0.0-RELEASE.jar を表示させてみると lib ディレクトリの下には doma2-lib-1.0.0-RELEASE.jar は入っておらず、

f:id:ksby:20190501225355p:plain

sample-webapp-1.0.0-RELEASE.jar の方にも同様に入っていませんでした。

f:id:ksby:20190501225527p:plain

動作確認

employee テーブルのデータは以下の状況です。

f:id:ksby:20190501230241p:plain

PropertiesLauncher を利用する方式の場合、外部に配置した jar ファイルがある場所を loader.path で指定します。今回はコマンドラインからアプリを実行する時に libs ディレクトリに移動した後 -Dloader.path=. を追加したコマンドを使用するようにします。

コマンドラインから java -Dspring.profiles.active=product -Dloader.path=. -Dbatch.execute=EmployeeDataCsvToDbLoader -jar sample-cmdapp-1.0.0-RELEASE.jar -csvfile=D:\project-springboot\ksbysample-boot-miscellaneous\gradle-multiprj-doma2lib-cmdwebapp\sample-cmdapp\src\test\resources\employee.csv コマンドを実行するとエラーは出ずに終了し、

f:id:ksby:20190501230514p:plain f:id:ksby:20190501230635p:plain

employee テーブルにもデータが登録されていました。

f:id:ksby:20190501230750p:plain

java -Dspring.profiles.active=product -Dloader.path=. -jar sample-webapp-1.0.0-RELEASE.jar で sample-webapp を起動した後、

f:id:ksby:20190501231034p:plain f:id:ksby:20190501231141p:plain

http://localhost:8080/sample にアクセスすると employee テーブルに登録されているデータが表示されました。

f:id:ksby:20190501231218p:plain

動作は問題なさそうです。

また libs ディレクトリから doma2-lib-1.0.0-RELEASE.jar を削除した後、sample-cmdapp を実行しようとすると java.lang.NoClassDefFoundError: ksbysample/lib/doma2lib/dao/EmployeeDao が発生してエラーで終了しました。

f:id:ksby:20190501231805p:plain

sample-webapp を起動しようとすると java.lang.ClassNotFoundException: ksbysample.lib.doma2lib.entity.Employee が発生して、こちらもエラーで終了しました。

f:id:ksby:20190501232323p:plain (.....途中省略.....) f:id:ksby:20190501232420p:plain

sample-webapp を IntelliJ IDEA の Run Dashboard から起動するとどうなるのか?

JarLauncher か PropertiesLauncher かは実行可能 Jar で起動する時の話ですので、Run Dashboard から起動する時には関係がありません。

Configuration でも Main class には org.springframework.boot.loader.PropertiesLauncher ではなく ksbysample.app.samplewebapp.SampleWebappApplication を指定しているので、

f:id:ksby:20190501233224p:plain

設定を変更しなくても起動します。

f:id:ksby:20190501233500p:plain

次回は。。。

Doma 2 の Dao インターフェース、Entity クラスを別の jar ファイルにしようとすると意外に大変ですね。今回は知らないことがいろいろありました。

Gradle で Multi-project を作成する ( その1 )( 概要 ) に記載していたパターンは一通り作成しましたが、サブプロジェクトの1つが Javascript のプロジェクト(Vue.js かな?)+1つは Spring Boot ベースのプロジェクトのパターンを作成してみたいと思ったので、もう1パターンだけ作成してみます。

履歴

2019/05/01
初版発行。