読者です 読者をやめる 読者になる 読者になる

日々常々

ふつうのプログラマがあたりまえにしたいこと。

JAX-RSをGradleでアレしたい

Gradle JAX-RS

なんか最近ほっとな感じがするJAX-RSのお話に便乗。

short answer

apply plugin: 'java'
apply plugin: 'jetty'

repositories.mavenCentral()

dependencies {
  providedCompile 'com.sun.jersey:jersey-bundle:1.17.1'
  providedCompile 'asm:asm:3.1'
}

これで `gradle jettyRun` で動かせます。やったね。


以下ははまりどころとかpom出力とか。

ライブラリの依存解決

jersey-bundleは全部入りでコンパイルするには便利なんですが、動かす際のライブラリがprovidedになってたりして持ってきてくれません。(asmが要る理由がその辺)
なのでJSONとかを使う場合、jersey-jsonを使用するとデフォルトスコープになっているので勝手に持ってきてくれるjackson周りがprovidedになっているため、この辺を足してやらなきゃいけなくなります。

これだけならMavenでもGradleでも同じ話なのですが、「それならjersey-bundleを使わずjersey-servletとかを使おう!」となった場合、GradleからMavenリポジトリを使用する際の問題にぶつかります。それがこれ。

以下はjersey-serverのpom.xmlから抜粋したもの。

<profile>
  <id>default</id>
  <activation>
    <activeByDefault>true</activeByDefault>
  </activation>
  <dependencies>
    <dependency>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-core</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>
</profile>

Mavenのprofileを使用している依存関係を認識してくれません。Mavenを使用しているなら勝手にアクティブになって勝手に足されるのですが。なのでこんな感じでダラダラ書かなきゃいけなくなります。

dependencies {
  providedCompile 'com.sun.jersey:jersey-json:1.17.1'
  providedCompile 'com.sun.jersey:jersey-core:1.17.1'
  providedCompile 'com.sun.jersey:jersey-server:1.17.1'
  providedCompile 'com.sun.jersey:jersey-servlet:1.17.1'
}

別に一行で書ける*1とかはどうでもよくて、Mavenではそれなりに解決出来ることがGradleで出来ないのは正直困る……(´・ω・`)

実際のところはwarとかにしてGlassFishにねじ込むとかするでしょうし、「開発時だけそれっぽく動けばいいよー」ならばbundleは手っ取り早くて便利です。どれをとか覚えなくていいですしね。
Jerseyのページでは「bundleは非Mavenユーザー向けだよ!」くらいの勢いですが、どうせprovidedにするしコンパイル出来ればいいよねくらいの割り切りならbundleで良いんじゃねーのと思ったり思わなかったり……。


この辺りでうだうだしてたら

……(´・ω・`)

Gradleからpom.xmlを吐く

依存解決絡みで「Mavenでは動くらしいのにGradleでは動かない」なんてことになった場合、Mavenで動くかを試すのにわざわざpom.xmlを書くのは面倒です。手で書くと間違えるかもしれませんし。なのでMavenプラグインで書き出します。

apply plugin: 'maven'

// ...

task writePom << {
    pom().writeTo('pom.xml')
}

シンプルなのならこれで十分。それっぽいpomが出てくれ、普通に動きます。流石にGradleでjettyプラグインを使ってるからと言って、Mavenプラグインを足してくれたりしませんが*2。build.gradleでバージョンやgroupIdを書いていない場合は変なこと*3になるので、必要なら適当に足しとくと良いです。
あとMavenプラグインを足したい場合などはpomメソッドクロージャを引数にとるので、MarkupBuilderなノリで書いてしまえば、適当にpom.xmlに足してくれます。結構お手軽。詳しくはGradleのユーザーガイドでも見てください。そんな詳しく説明が必要なものでもないですが。

大人の事情でどうしてもpom.xmlが必要な場合、Gradleからpom.xmlを吐かせるようにして、pom.xmlエディタとしてGradleを使うとかよくわからないアプローチも有るかも無いかもです。

*1:例えば ['core', 'server', 'json', 'servlet'].each { providedCompile "com.sun.jersey:jersey-$it:1.17.1" } で同等

*2:別物ですしね。

*3:それぞれundefinedと空