DropwizardのプロジェクトをGradleを使ってビルドする

Java のフレームワーク Dropwizard を使ったプロジェクトをビルドする Gradle スクリプトを用意できたのでメモ。
といっても構造的には Dropwizard に特化したものではなく他のプロジェクトにも普通に使える。

これまでは Maven で頑張ってきたが、今回を機にシフトしていく。

当然ながらほぼ素の build.gradle でもビルドしアプリケーションを動作させることは可能。

ところが実際のプロジェクトにおいては、外部ライブラリを取り込んだ jar ファイルを作成すると META-INF/services/ に配置されるファイルに同名のファイルが現れる状態が多々発生する。
この状態になるとパッケージ名が解決できずに正しくアプリケーションが動作しないことがある。

私が遭遇したのは Dropwizard アプリケーションが Configuration ファイルを読み出せず起動しないという症状。
調べてみると META-INF/services/com.fasterxml.jackson.core.JsonFactory が複数存在しYAMLのオブジェクトマッパーが動作しなくなっていた。（なお他にも競合しているファイルあり）

Maven を使用していたときに何故問題が起きていなかったかというと shade プラグインが競合するファイルをマージすることで問題を解決してくれていたわけだ。

ということは Gradle 環境においても同様の解決の手段があるはず。
いくつか情報をチェックしていて[こちらのブログ](https://www.yunspace.com/blog/dropwizard-gradle-shadowjar "Dropwizard Gradle Build with ShadowJar")内のbuild.gradleがすっきりとしたものだった。
プラグインにはMavenのshadeプラグインを強く意識して作られた[shadow](https://github.com/johnrengelman/shadow "shadow")を使用している。
このプラグインの機能のうち mergeServiceFiles() を shadowJar ブロックで呼び出しているのがポイントとなる。

先に紹介したブログ内の build.gradle を元に修正してみた。

* プラグインの取り込みはGradle2.1以降の書き方
* 使用するプラグインのバージョンは最新に
* source、targetの指定（Javaは1.8を使用）
* デフォルトエンコード（'UTF-8'）の指定
* 出力するパッケージ名の指定
* マニフェストはもう少し詳細に

といったあたりが大きな違いか。
今回のスクリプトを元にカスタムタスクを追加するなど活用していきたい。

```groovy:build.gradle
plugins {
  id 'java'
  id 'com.github.johnrengelman.shadow' version '1.2.2'
}

apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'application'

defaultTasks 'shadowJar'

project.ext {
    authorName = 'John Doe'
    dropwizardVersion = '0.8.2'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8
group = 'com.example'
version = '1.0'

applicationName = 'ExampleApplication'
mainClassName = 'com.example.dropwizard.ExampleApplication'

repositories {
    mavenLocal()
    mavenCentral()
}

def defaultEncoding = 'UTF-8'
tasks.withType(AbstractCompile)*.options*.encoding = defaultEncoding
tasks.withType(GroovyCompile)*.groovyOptions*.encoding = defaultEncoding

dependencies {
    compile "io.dropwizard:dropwizard-core:${dropwizardVersion}"
    compile "io.dropwizard:dropwizard-assets:${dropwizardVersion}"
    compile "io.dropwizard:dropwizard-views:${dropwizardVersion}"
    compile "io.dropwizard:dropwizard-views-freemarker:${dropwizardVersion}"
    compile "org.glassfish.jersey.media:jersey-media-multipart:2.19"

    testCompile "junit:junit:4.11"
    compile "io.dropwizard:dropwizard-testing:${dropwizardVersion}"

}

task wrapper(type: Wrapper) {
    gradleVersion = '2.5'
}

shadowJar {
    archiveName = String.format("%s-%s.jar", applicationName, version)
    mergeServiceFiles()
    exclude 'META-INF/*.SF'
    exclude 'META-INF/*.DSA'
    exclude 'META-INF/*.RSA'
}

jar {
    manifest {
        attributes(
            'Implementation-Title': applicationName,
            'Implementation-Version': version,
            'Built-By': authorName,
            'Built-Time': new Date(),
            'Main-Class': mainClassName,
            'Class-Path': configurations.compile.collect { it.getName() }.join(' ')
            )
    }
}
```

##### 2015/02/05 修正
GStringであればプロパティを展開できるとのことで一部書き直し。

##### 2015/07/19 修正
Dropwizard 0.8.2をビルドする内容へ記述変更。

参考リンク
[Dropwizard Gradle Build with ShadowJar](http://www.yunspace.com/2014/02/12/dropwizard-gradle-shadowjar/ "Dropwizard Gradle Build with ShadowJar")
[shadow](https://github.com/johnrengelman/shadow "shadow")
[Gradleで文字エンコーディングを指定する方法](http://nobeans.hatenablog.com/entry/20091104/1257344503 "Gradleで文字エンコーディングを指定する方法")