Gradle を使って Spring Boot 2 のマルチプロジェクトを作る方法。
環境
Java
openjdk 10.0.2 2018-07-17
Gradle
4.10
Spring Boot
2.0.4
対象のマルチプロジェクト
|-settings.gradle
|-build.gradle
|
|-foo/
| |-build.gradle
| :
|
`-bar/
|-build.gradle
:
-
foo
プロジェクトがbar
プロジェクトを参照している - 実装内容は今回関係ないので省略
ダメパターンの設定
/build.gradle
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
subprojects {
apply plugin: "java"
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
repositories {
mavenCentral()
}
sourceCompatibility = 10
targetCompatibility = 10
}
- サブプロジェクト全体 (
foo
,bar
) に共通でプラグインなどを設定している。 -
io.spring.dependency-management
は、 Maven の BOM を利用して依存するライブラリのバージョンを制御する仕組みを Gradle でも使えるようにしたやつ- 参考:Gradle で BOM を使いたいときには Spring チームの出している Dependency management plugin を使うのがよさそう - なにか作る
- Spring Boot 関係の
dependencies
のバージョン指定を省略できるようになる - 1.x の頃は
org.springframework.boot
が内部で利用していたが、 2.x では外に出されたっぽい
/foo/build.gradle
dependencies {
compile project(":bar")
compile "org.springframework.boot:spring-boot-starter-web"
}
-
:bar
への依存と、spring-boot-starter-web
への依存を宣言
コンパイル結果
> gradle :foo:compileJava
> Task :foo:compileJava FAILED
...\Foo.java:12: エラー: シンボルを見つけられません
return new Bar().bar();
^
シンボル: メソッド bar()
場所: クラス Bar
エラー1個
FAILURE: Build failed with an exception.
bar
プロジェクトのクラスが解決できずにエラーになる。
説明
-
bar
プロジェクトのビルド結果を確認してみる
> dir /b bar\build\
classes
tmp
-
bar
プロジェクトの jar が生成されていない- 1.x なら、
bar\build\libs
の下にbar.jar
という jar ファイルが出力されており、foo
プロジェクトはその jar を参照するようになっていた気がする
- 1.x なら、
- なんか、 2.x からはデフォルトで
jar
プラグインのenabled
がfalse
に設定されるようになったらしい- https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-and-normal
-
jar
タスクでは jar ファイルは生成されず、bootJar
タスクで生成されるようになったらしい
対処方法
java - Spring Boot multi module project with Gradle doesn't build - Stack Overflow
- ここでは、
jar.enabled
にtrue
を設定すればええでという方法が紹介されている - たしかに、これを設定すればビルドできるようになる
- ただ、公式の GitHub Issue の方を見ると、そもそも依存されている側のサブプロジェクト(
bar
プロジェクト)の方は Spring Boot プロジェクトではないのだから、サブプロジェクトにまでorg.springframework.boot
プラグインを適用することが間違っていると説明されている - 確かにその通りだと思うので、こっちの方法で修正する
OK パターン
/build.gradle
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
subprojects {
apply plugin: "java"
apply plugin: "io.spring.dependency-management"
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
}
}
sourceCompatibility = 10
targetCompatibility = 10
}
/foo/build.gradle
apply plugin: "org.springframework.boot"
dependencies {
compile project(":bar")
compile "org.springframework.boot:spring-boot-starter-web"
}
コンパイル結果
> gradle :foo:compileJava
BUILD SUCCESSFUL in 17s
説明
/build.gradle
buildscript {
ext {
springBootVersion = '2.0.4.RELEASE'
}
...
}
subprojects {
apply plugin: "java"
apply plugin: "io.spring.dependency-management"
...
dependencyManagement {
imports {
mavenBom "org.springframework.boot:spring-boot-dependencies:$springBootVersion"
}
}
...
}
- 全てのサブプロジェクトに
org.springframework.boot
を設定するのをやめる - そして、
dependencyManagement
を追加して Spring Boot の BOM を読み込む
/foo/build.gradle
apply plugin: "org.springframework.boot"
...
-
foo
プロジェクトのほうにだけorg.springframework.boot
を適用する