謎言語使いの徒然

適当に気になった技術や言語を流すブログ。

Gradle4 + Jersey2 + Kotlin でRESTサービスを作ってみる

SPA でアプリ作ろう思って、サーバに当初 Spring 考えてたけど、こっちの方が API サーバが楽そうだった。

で、Kotlin は個人的な好み

教科書はこれ

JAX-RS(Jersey)+GradleでWebアプリを作る - Olivinecafe - blog

Gradle

汎用ビルドツール。
Java 専用ではないので、Java 書きたければ基本はプラグイン
独自の DSL で記述するが、Java ライブラリとか普通に叩けた。

個人的に好きなのは、gradle wrapper コマンドで、これを実行するとカレントディレクトリに gradlew コマンドを吐き出す。
こいつは単独実行可能な gradle コマンドなので、いちいち使う人に Gradle のインストールを強要しない。

sbt も大概 jar 一つでやってのけるのだが、こういう仕様がないと、複数人での開発がだるくて仕方ない。

とりあえず、build.gradle はこんな感じで書いた。

apply plugin: 'maven'
apply plugin: 'war'
apply plugin: 'org.akhikhl.gretty'
apply plugin: 'kotlin'

def jerseyVersion = '2.25.1'

sourceCompatibility = 1.7

buildscript {
  repositories {
    jcenter()
    mavenCentral()
  }

  dependencies {
    classpath 'org.akhikhl.gretty:gretty:+'
    classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.3'
  }
}

ext {
    project.version = '0.0.1'
    project.group = 'net.white-azalea'
    appName = 'example'
    project.description = 'example gradle application/'
}

configurations {
     all*.exclude module: 'servlet-api'
}

dependencies {
    providedCompile 'javax.ws.rs:javax.ws.rs-api:2.0.1'
    compile "org.glassfish.jersey.containers:jersey-container-servlet:${jerseyVersion}"
    testCompile 'junit:junit:4.+'
}

repositories {
    jcenter()
    mavenCentral()
    mavenLocal()
}

とてもざっくり説明すると、

  • リリース時は war でビルドするよ
  • gretty プラグインを使って、デバック実行時に jetty サーバ使うよ
  • Kotlin 言語でやるよ
    しかも Java プラグイン入れてないので、Java 書けないよ
  • servlet-api は war には含まない様にしてるよ
    これが含まれてると、Tomcat とかのサーバにデプロイした時バージョン衝突とかめんどくさいことになる場合がある
  • Jersey2.25.1 を必要とするよ

これを gradlew appRun すると、依存する jar とか、実行サーバとか諸々勝手にダウンロードしてくる。
開発マシンにわざわざ手動で Tomcat 入れさせる環境とか、ネットワーク接続禁止環境だけでしょ…Web アプリ作るのにネットワーク禁止とかこれいかに?

jersey2

JAX-RS 実装らしいがなんのことはない。
アノテーションでパス指定すれば色々できる。

まずは、src/main/webapp/WEB-INF/web.xml を記述する。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <servlet>
        <servlet-name>jersey-example</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>net.white_azalea</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.scanning.recursive</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>10</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey-example</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

設定は全て Gradle にお任せモードする web.xml だ。

お次はソース。src/main/kotlin/net.white-azalea/Example.kt を作成して以下を記述

package net.white_azalea

import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces
import javax.ws.rs.core.MediaType

@Path("/hello")
class Example {

    @GET
    @Produces(MediaType.TEXT_HTML)
    fun hello(): String = "Hello!"
}

ここまできたら全部おしまい。

./gradlew appRun して、http://localhost:8080/jersey-example/hello にアクセスできれば OK.

jar 依存がだいぶ足りてないので、オブジェクト返すとコケる。
まぁその辺は この辺 みて自力解決しよう。