免責
いまいち原因が理解できていませんが、困っている人のために公開します。
やりたいこと
Maven で書かれた doma-spring-boot-starter のチュートリアルを Gradle で実装したい。
https://github.com/domaframework/doma-spring-boot
環境
- IntelliJ IDEA 2017.2.4
- JDK 1.8
- Gradle 3.5.1
やったこと
- IntelliJ から Spring Initializr を使ってプロジェクト初期化
- Web, JDBC, H2 にチェック
- build.gradle に doma-spring-boot-starter を追加
compile('org.seasar.doma.boot:doma-spring-boot-starter:1.1.1')
- build.gradle に Doma ドキュメント にある記述を追加
- 最終的なbuild.gradleは↓の方にあります
- IntelliJ の Doma Plugin をインストール
- あとはチュートリアル通りにクラスなどを作成
ハマり1: エディタに赤線が出る
ReservationDao
をフィールド定義するところでエラーが表示されます。これは Maven でも同様です。
@SpringBootApplication
@RestController
public class DomaGradleApplication {
@Autowired
public ReservationDao reservationDao;
//=> Could not autowire. No beans of 'ReservationDao' type found.
...
}
解決策(?)
IntelliJのバグみたいです。
https://stackoverflow.com/questions/26889970/intellij-incorrectly-saying-no-beans-of-type-found-for-autowired-repository
この記事にいろいろ解決策が書いてありますが、異なるバージョンへの対策だったりワークアラウンドであったりするので注意が必要です。
実行時に問題にならないので、私はお布施をして修正を待つことにしました。
ハマり2: Domaクラスが生成されない
IntelliJ の Run
ボタンで実行すると、ビルドは成功するものの、下記のエラーでサーバーの起動に失敗してしまいました。
***************************
APPLICATION FAILED TO START
***************************
Description:
Field reservationDao in com.example.domagradle.DomaGradleApplication required a bean of type 'com.example.domagradle.ReservationDao' that could not be found.
Action:
Consider defining a bean of type 'com.example.domagradle.ReservationDao' in your configuration.
ちなみに Constructor Injection で書き換えた場合、Description は下記となります。
Description:
Parameter 0 of constructor in com.example.domagradle.DomaGradleApplication required a bean of type 'com.example.domagradle.ReservationDao' that could not be found.
原因
out
フォルダの中身を見てみると、Doma で生成されるはずの ReservationDao
実装クラスが存在しません。今の場合「a bean of type '...ReservationDao'」とはこの実装クラスを探して見つからなかったということになります。
解決策
なぜ生成されないのかをまだ理解していませんが、gradlew
を使えば生成されることに気付きました。
$ ./gradlew build
これにより、build
フォルダが新たに作られ、その中に必要なクラスファイルやjarが作られます。jarを実行してサーバーを起動します。
$ java -jar ./build/libs/***.jar
ただ、これではIntelliJを使ったデバッグができません。
調べてみると、build.gradle に設定を加えることで動くようになるとのこと。
https://stackoverflow.com/questions/45174989/building-with-intellij-2017-2-out-directory-duplicates-files-in-build-director
実際、allprojects {...}
をbuildscript{...}
の直後に書くことで、無事動作するようになりました。せっかくなのでbuild.gradle
全体を掲載します。
buildscript {
ext {
springBootVersion = '1.5.7.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
// https://stackoverflow.com/questions/45174989/building-with-intellij-2017-2-out-directory-duplicates-files-in-build-director
allprojects {
apply plugin: 'idea'
idea {
module {
outputDir file('build/classes/main')
testOutputDir file('build/classes/test')
}
}
if(project.convention.findPlugin(JavaPluginConvention)) {
// Change the output directory for the main and test source sets back to the old path
sourceSets.main.output.classesDir = new File(buildDir, "classes/main")
sourceSets.test.output.classesDir = new File(buildDir, "classes/test")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
// JavaクラスとSQLファイルの出力先ディレクトリを同じにする
processResources.destinationDir = compileJava.destinationDir
// コンパイルより前にSQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する
compileJava.dependsOn processResources
repositories {
mavenCentral()
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-jdbc')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.seasar.doma.boot:doma-spring-boot-starter:1.1.1')
runtime('com.h2database:h2')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
注意
DAOや.sqlファイルを変更したら再度 ./gradle build
する必要があります。
最後に
素直に Maven でやった方が楽なのではと思いました。