Edited at

Domaが生成するソースコードもソースJARに含める


概要

DomaはPluggable Annotation Processing APIを用いてDAOの実装クラスやエンティティの補助クラスをコンパイル時に自動生成します。

Domaによって自動生成されるのはJavaファイルですが、MavenやGradleで普通に(?)紹介されている方法(下記のリンク先を参照)でソースJARを作っても自動生成されたJavaファイルはソースJARに含まれません。

テーブルと1対1にマッピングされるエンティティはDoma-Genで生成してJARにまとめてWebプロジェクトやバッチプロジェクトから参照するといった構成にすることがあると思いますが、その際にエンティティのソースJARにDomaによって自動生成されるJavaファイルも含めたいというモチベーションがあります。

ここではMavenとGradleそれぞれどうすればDomaによって自動生成されるJavaファイルをソースJARに含むことができるのかを記載します。


Maven

MavenでソースJARを作るにはorg.apache.maven.plugins:maven-source-pluginjarゴールを実行します。

パッケージングの対象がsrc/main/javasrc/main/resourcesのようなので、そこにDomaによって自動生成されるJavaファイルの出力先ディレクトリを追加すれば良さそうです。

そう考えてjarゴールのドキュメントを見たのですが、パッケージングの対象を追加できそうなオプションが見当たりませんでした。

仕方がないのでjarゴールの実装であるSourceJarMojoを見ました。

SourceJarMojoSourceJarNoForkMojoを継承していました。

SourceJarNoForkMojoの中でソースディレクトリ(パッケージングの対象)を取得している箇所を見ると、MavenProject#getCompileSourceRoots()が呼ばれています。

MavenProject#getCompileSourceRoots()のJavadocを見ても何も書かれていませんでしたが、クラス名などから察するにプロジェクト全体に関わる設定のようです。

以上のことからDomaによって自動生成されるJavaファイルの出力先をリソースディレクトリとして追加することにしました。

<resources>

<resource>
<filtering>false</filtering>
<directory>src/main/resources</directory>
</resource>
<resource>
<filtering>false</filtering>
<!--
Pluggable Annotation Processing APIが生成するソースコードのデフォルト出力先を
リソースディレクトリに追加することでsources-jarに含める。
https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#generatedSourcesDirectory
-->

<directory>${project.build.directory}/generated-sources/annotations</directory>
</resource>
</resources>

ただ、MavenはリソースのコピーをしてからコンパイルしてJARにパッケージングするので、何度かmvn packageをすると2回目以降のJAR(ソースJARではなく、クラスファイルがパッケージングされている方のJAR)にDomaによって自動生成されたJavaファイルもパッケージングされてしまいます。

そのため、org.apache.maven.plugins:maven-jar-pluginの設定でJavaファイルはパッケージに含めない設定を追加しました。

<!--

ソースディレクトリをリソースに追加したのでJARファイルに
Javaファイルを含めないようにする。
-->

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</configuration>
</plugin>

これであとはmvn package source:jarとするだけです。


Gradle

GradleはMavenと違ってソースJARを作るプラグインがあるわけではなく、Jarタスクをベースに自分でソースJARを作るタスクを定義します。

そのときにパッケージ対象のディレクトリへDomaによって自動生成されるJavaファイルの出力先を追加すれば良いです。

GradleではDomaによって自動生成されるJavaファイルの出力先はsourceSets.main.output.classesDirsがデフォルトです。

これはクラスファイルの出力先でもあるので、クラスファイルを除く設定も書きます。

task sourcesJar(type: Jar) {

from sourceSets.main.allJava, sourceSets.main.output.classesDirs //Domaが生成するソースはsourceSets.main.output.classesDirsに出力される
classifier = 'sources'
exclude '**/*.class' //sourceSets.main.output.classesDirsはclassファイルも含むのでフィルタリングする
}

前述の通り、Domaによって自動生成される(というかPluggable Annotation Processing APIを使って生成される)Javaファイルはクラスファイルと同じ場所に出力されます。

そのためデフォルトでJARファイルにJavaファイルがパッケージングされてしまうので、それを除く設定を追加します(なんでデフォルトでそんな場所に出力されるのか、、、)。

//sourceSets.main.output.classesDirsに出力されるJavaファイルを除く

jar.excludes = ['**/*.java']

これであとはgradle build sourcesJarとするだけです。


終わりに

動くコード例は次の場所に置いています。

ソースJARをローカルのNexusにデプロイするところまで体験できるようにしています。