gradle の copy タスク活用

MyBatis を使用した開発プロジェクトで、gradle を使用した時にマッパーXMLを配置するのに、
不都合なことがある。

Java の interface クラスを置いたJavaソースと同じ場所に、XMLを置いてビルドした時、
classpathXMLも配置して欲しいのである。
例えば、、

src--main-+--java---aa/bbb/ccc
          |
          |
          +--resources

というsrc (ソース)の下がこのようにディレクトリ、aa.bbb.ccc パッケージがあって、
aa.bbb.ccc パッケージに、UserMapper.java

package aa.bbb.ccc
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface UserMapper{
   @Select("SELECT COUNT(id) FROM USERS WHERE DELETE_FLG = 0")
   public long countUsers();
}

があったとする。更に、長いSQLを書く為に、UserMapper.xml を、
resources の下に、aa.bbb.ccc パッケージのとおりに
ディレクトリ階層を作って配置するのは、手間もかかり
誤ったディレクトリを作って配置したら気がつくのに時間かかって苦労する。
Javaソースと同じ、src--main-+--java---aa/bbb/ccc に UserMapper.xml を配置してビルドした時に、
build/resources の下に配置して欲しいのだ。


sourceSets で、デフォルトの src/main/resources だけでなく追加する方法、、、

sourceSets.main.resources.srcDirs = [ "src/main/resources", "src/main/java" ]

これで、src/main/java/aa/bbb/ccc/UserMapper.xml は、
ビルドした時に、build/resources の下に、
build/resources/aa/bbb/ccc/UserMapper.xml とコピーしてくれるのだが、
 欠点がある!!
 aa/bbb/ccc 以外の 他のパッケージ構成も build/resources の下に作成されてしまう。


gradle のコピータスクを用意する方法、、、
コピーを定義して、build finalizedBy として最後にコピーを実行させる

task copyMapperXML(type: Copy) {
   from 'src/main/java/aa/bbb/ccc'
   into 'build/resources/aa/bbb/ccc'
   include '*.xml'
}
build {
   finalizedBy copyMapperXML
}

マッパーXMLが1つのパッケージだけでなく、複数のパッケージに存在するなら、
その分、コピータスク、finalizedBy を列挙すれば良いだろう。

build {
   finalizedBy finalizedBy( 'copyMapperXML', 'copyMapperXML2')
}

コピー対象が複数パターンなら、

     include('*.xml', '*.properties')