単体検査などで使うWebAPIスタブを作る時などは、
わざわざtomcat上にwarをデプロイするのは面倒なので、
javaコマンド一発で実行できるようにしたいです。

そこで、このエントリでは、
jettyをembedしてServletを動かす手順をまとめておきます。

このエントリでは、以下流れでモジュールを作っていきます。

  • ビルド定義にjettyを追加
  • sbt-assemblyの設定とメインクラスの定義
  • メインクラスの実装(jettyの起動)
  • jettyサーバへのサーブレットハンドラ設定
  • ビルド及び実行

以下の記事を参考に、このエントリをまとめました。

Embedding Jetty | eclipse.org
https://www.eclipse.org/jetty/documentation/9.3.x/embedding-jetty.html

ビルド定義にjettyを追加

作業ディレクトリを作成し、以下の様にビルド定義にjettyを記載します。
ここではsbtを使っていますが、
maven/gradleなどを利用している方は、適宜読み替えてください。

build.sbt

libraryDependencies ++= Seq(
  "org.eclipse.jetty" % "jetty-webapp" % "9.3.12.v20160915"
)

sbt-assemblyの設定とメインクラスの定義

ここではfat-jarを作成し「java -jar」で起動できる様にしたいので、
以下の様にassemblyとメインクラスの定義を追加します。

build.sbt

mainClass := Some("com.takemikami.samples.jettyembed.HelloServer")

libraryDependencies ++= Seq(
  "org.eclipse.jetty" % "jetty-webapp" % "9.3.12.v20160915"
)

project/assembly.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3")

メインクラスの実装(jettyの起動)

jettyサーバーを起動するメインクラスを実装します。

src/main/java/com/takemikami/samples/jettyembed/HelloServer.java

package com.takemikami.samples.jettyembed;

import org.eclipse.jetty.server.Server;

public class HelloServer {
    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);
        server.start();
        server.dumpStdErr();
        server.join();
    }
}

以下のコマンドでjarをビルドします。

$ sbt assembly

以下のコマンドで実行します。
※jarファイルの名前は、作業ディレクトリの名称によって変わります。

$ java -jar target/scala-2.10/jettyembed-sample-assembly-0.1-SNAPSHOT.jar

この段階では、8080ポートを開いているだけで、
何も処理が実装されていないので、次項でサーブレットを実装します。
一旦、Ctrl+Cで停止します。

jettyサーバへのサーブレットハンドラ設定

以下の様にHelloServletを実装します。

src/main/java/com/takemikami/samples/jettyembed/HelloServlet.java

package com.takemikami.samples.jettyembed;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet  {
    @Override
    protected void doGet( HttpServletRequest request,
                          HttpServletResponse response ) throws ServletException, IOException {
        response.getWriter().println("Hello");
    }
}

以下の様に、前項で作成したメインクラスに、HelloServletを設定します。

src/main/java/com/takemikami/samples/jettyembed/HelloServer.java

package com.takemikami.samples.jettyembed;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;

public class HelloServer {
    public static void main(String[] args) throws Exception {
        Server server = new Server(8080);

        ServletHandler handler = new ServletHandler();
        server.setHandler(handler);
        handler.addServletWithMapping(HelloServlet.class, "/hello");

        server.start();
        server.dumpStdErr();
        server.join();
    }
}

ビルド及び実行

以下のコマンドで、もう一度ビルド・実行します。

$ sbt assembly
$ java -jar target/scala-2.10/jettyembed-sample-assembly-0.1-SNAPSHOT.jar

上記を実行した状態で、
以下のコマンドのように「8080」ポートの「/hello」にgetリクエストを送ると、
サーブレットが実行されて、「Hello」という文字が返却されます。

$ curl http://localhost:8080/hello
Hello

以上の手順で、jarを作っておけば、
jarファイルだけでWebAPを起動できるので、お手軽です。

WebAPIを開発していて、
APIのクライアント開発チームにスタブを提供する時などは、
warファイルとセットアップ手順を渡すよりも、
この手順でモジュールを作ってしまった方が手っ取り早いと思います。