Spring Framework を仕事でする必要があり、その時に、使えるビルドのシステムとして、Maven や Gradle があり、今回は Gradle を選択してみた。Java は相当久しぶりなこともあり、Javaそのものというより、Gradleがよく分かってないことが分かったので、地道にチュートリアルを実施したり、公式のドキュメントを読んだりしてみたので自分のメモとして、書き残してみたい。
目的
今回の目的は、Spring Boot の REST-API のプロジェクトに置いて、次のことが出来ること。
- プロジェクトの雛形を作る
- ビルドを実施する
- パスの通った場所に設定ファイル (XML ファイル) を置く必要があり、そのファイルを、設定ファイルのパスの通ったところにコピーすること。jar になる場合は、Jar に含めること。
リソース
1. Gradle のインストール
Mac の場合は、Brewで入る。Windows の場合は、公式では、ダウンロードしてパスを通すことになっているが、Chocoratelyでも良い様子。
Mac
brew install gradle
Windows
choco install gradle
ちなみに、Gradle では、Gradle Wrapperというものがあり、利用者の人が、Gradle をインストールしなくても、自動的にダウンロードして設定をしてくれるWrapperを作成することができる。それを使えば利用だけだとインストールはしなくても良い。
2. プロジェクトの雛形を作る
2.1. ディレクトリの作成
雛形の作成は、build.gradle
ファイルを作るところから始まる。Spring Boot の場合は、ソースをおくディレクトリを作る。例えば次のものを作る。-p
は、ディレクトリなければ作成するオプション。
mkdir -p src/main/java/hello
2.2. ビルドファイルの作成
ゼロから作る場合は、gradle init
でいくつかのテンプレートが用意されている。Spring Boot の場合は、公式にある雛形からスタートするのが良さげ。
build.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.5.RELEASE")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
bootJar {
baseName = 'gs-actuator-service'
version = '0.1.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile("junit:junit")
}
各パーツを解説してみる。
2.2.1. ビルドスクリプトの依存ライブラリの記述
プロジェクトではなく、build.gradle
自体に必要なライブラリの記述。ここでは、Mavenのライブラリを指定して、spring-boot-gradle-plugin
を依存に追加しているのがわかる。
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.5.RELEASE")
}
}
2.2.2. plugin
build.gradle
は Groovyの形式で書かれている。ちなみに、Kotlin の形式でもかける様子。基本的な挙動としては、Taskというスクリプトの実行単位があ理、実態はJavaのクラスになっている。そのDSLがこのファイルだ。そのTaskを実行したり、その依存関係を定義したりして使うようになっている。
plugin
は、先に誰かが作ったタスクの集まりを利用するためのもの。
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
2.2.3. 起動可能なJarの定義
こちらに説明があるが、java -jar xxx
の形式でサーバーが立ち上がる jar を作成することができる。このコンフィグレーションがBootJarを見ればわかる。ここでは、jar の名前と、バージョンを指定している。これ以外にもパッケージングに関する設定が可能になっている。
Spring Boot Gradle Plugin Reference Guide
bootJar {
baseName = 'gs-actuator-service'
version = '0.1.0'
}
チュートリアルにある雛形はこれで、これで、REST API を作るための Spring Boot のビルドファイルが出来ている。
2.2.4. その他のプロパティ
sourceCompatibility
は、JavaをコンパイルするときのJavaのバージョン
targetCompatibility
は、どのバージョンのクラスを作成するかの指定
おそらく、Javaは、古いバージョンのクラスファイルを作成できるのかもしれない。通常は同じでよい。
sourceCompatibility = 1.8
targetCompatibility = 1.8
2.2.5. プロジェクトの依存関係
先ほどは、スクリプト自体だったが、こちらは、プロジェクトに必要な依存関係を追加する場所。自分のプロジェクトに、ライブラリを追加したいときは、こちら。buildscript
の方に追加しても、プロジェクトの方は依存関係にならないので注意。
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile("junit:junit")
}
2.2.6. 設定ファイルをクラスパスが有効な場所に移動する
ビルドをするときに、クラスパス上に置く必要のあるxmlファイルがあり、それがビルド時にコピーされる必要があったので調べてみた。こういうエントリを追加すると、resources
ディレクトリの下にxmlファイルがコピーされる。ちなみに、これは、Jarファイルになったときには、Jarファイルのクラスパスの下に置かれる。
sourceSets.main.resources {
srcDirs = ['src/main/java']
include '**/*.xml'
}
ここで、Resources ディレクトリはどういうものだろうか?Javaプラグインで定義されており、XMLのプロパティファイルのような、プロダクションリソースを置く場所。デフォルトが決まっているが、Source setsを書き換えることで変更可能になる。デフォルトは [src/$name/resources]
。
2.3. 各種のコマンド
この状態で、コードを作成すれば、ビルドが出来る状態になるが、他にも便利なコマンドをみていこう。
2.3.1. ビルドする
gradle build
2.3.2. Gradle Wrapper を作る
使う人がGradleをインストールしなくても使えるようにGradleWrapperを作る
gradle wrapper --gradle-version 5.0
これで次回からgradlew
コマンドが使えるようになる。これによりユーザーのGradleのインストールが不要になる。
gradlew build
2.3.3. Spring Boot の実行
Spring boot を実行する場合は
gradle bootRun
でよい。もしくはつまり、ビルドした jar ファイルを実行してやれば良い。
gradle build
java -jar build/libs/gs-actuator-service-0.1.0.jar
2.3.4. 使えるタスクを調べる
gradle tasks
で現在使えるタスクのリファレンスができる
$ gradle tasks
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :tasks
------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------
Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'libs'.
components - Displays the components produced by root project 'libs'. [incubating]
dependencies - Displays all dependencies declared in root project 'libs'.
dependencyInsight - Displays the insight into a specific dependency in root project 'libs'.
dependentComponents - Displays the dependent components of components in root project 'libs'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'libs'. [incubating]
projects - Displays the sub-projects of root project 'libs'.
properties - Displays the properties of root project 'libs'.
tasks - Displays the tasks runnable from root project 'libs'.
To see all tasks and more detail, run gradle tasks --all
To see more detail about a task, run gradle help --task <task>
BUILD SUCCESSFUL in 5s
1 actionable task: 1 executed
2.3.5 ビルドの分析
なんとグラフィカルに、タスクを分析することが出来ます。
gradle taskname --scan
2.4. カスタムタスク
多くは説明しないが、Javaで出来ているので、カスタムタスクは単なるクラスだ。既存のクラスを組み合わせる場合は、特にクラスを作成する必要もない。これは、先のオペレーションを手動でしようともがいてたときの例。コピータスクを作成して、強引にbuildタスク実行時に実行しようとしている(ただし、この設定だと、このタスクでコピーしたのち、buildタスクがクリーンアップしてコピーしていると思われ、該当のファイルは消えます。
task copy(type:Copy) {
description 'Copies ApplicationInsights.xml to the class path dir'
from file('src/main/java/ApplicationInsights.xml')
into file('$buildDir/classes/java/main')
}
build.dependsOn copy
詳細は下記まで。
まとめ
表面的ではあるが、これで一通り、なんとかGradleを使い始められるようにはなったのでよしとしよう。