組み込みTomcat と Jersey MVC と JSP でWebアプリ開発

組み込みTomcatのうえでJersey MVCを動かす必要に迫られて調べたのですが参考になるドキュメントをなかなか見つけられずハマったので、得た知見をシェアします！

> 以下記事で利用しているソースコードは[GitHub](https://github.com/0x9n/my-jersey-mvc-with-embedded-tomcat)にあげてあります。

## 筆者の前提

- Maven 3.0
- JDK 1.8
- Mavenあんまり分かってない
- ミドルウェアほとんど分かってない

## JerseyMVCでアプリを書く

JerseyMVCはJavaで簡単にRESTfulなWebアプリが作れるフレームワーク。アノテーションでURLとメソッドを紐付けることができる。

[先人の智慧](http://qiita.com/opengl-8080/items/f4c25ad671e8a6dac743)をそのまま参考にさせていただきました。

以下のように、

```java:MyResource.jsva
@Path("hello-mvc")
public class MyResource {

    /**
     * /hello-mvcへのGETリクエストを受け取ってJSPを返却する。
     * @return Viewableインスタンス
     */
    @GET
    public Viewable helloworld() {
        return new Viewable("/hello-mvc");
    }
}
```

アノテーションでPathとHTTPメソッドを指定したコントローラーを書いて、

```java:MyApplication.java
this.packages(MyApplication.class.getPackage().getName()).register(JspMvcFeature.class);
```

それをアプリケーションの部品として`JspMvcFeature`に登録して、

```xml:web.xml
<filter>
        <filter-name>Jersey MVC JSP Filter</filter-name>
        <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
        <init-param>
            <!-- MyApplicationクラスをJAX-RSのアプリケーションとして登録 -->
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.example.MyApplication</param-value>
        </init-param>
        <!-- ... -->
    </filter>
```

`web.xml`でそれを読み込むようにfilterの設定を書くと、URLに対応づけられてアプリが動くようになる。

## 組み込みTomcatの設定

組み込みTomcatを動かすための依存関係を`pom.xml`に記述。[参考資料](http://people.apache.org/~markt/presentations/2010-11-04-Embedding-Tomcat.pdf)参照。

```xml:pom.xml
<dependency>
           <groupId>org.apache.tomcat.embed</groupId>
           <artifactId>tomcat-embed-core</artifactId>
           <version>8.0.26</version>
       </dependency>
       <dependency>
           <groupId>org.apache.tomcat.embed</groupId>
           <artifactId>tomcat-embed-logging-juli</artifactId>
           <version>8.0.26</version>
       </dependency>
       <dependency>
           <groupId>org.apache.tomcat.embed</groupId>
           <artifactId>tomcat-embed-jasper</artifactId>
           <version>8.0.26</version>
       </dependency>
```

`tomcat-embed-core`と`tomcat-embed-logging-juli`は必須で、`tomcat-embed-jasper`はJSPを扱うために必要なオプションのライブラリ。

これを取り込んでおけば以下のようにTomcatが起動できる。

```java:Main.java
// Tomcatインスタンスを宣言
Tomcat tomcat = new Tomcat();
tomcat.setPort(9000);

String baseDoc = new File("src/main/webapp").getAbsolutePath(); // DocumentBaseを設定
Context ctx = tomcat.addContext("/servletSample", baseDoc); // ContextPathを設定
tomcat.addWebapp(null, "", baseDoc); // webappにアプリケーションを追加

// 単にサーブレットだけを追加するなら以下のように。
// これでhttp://localhost:8080/servletSample でHelloWorldServletにアクセスできる。
// HelloWorldServlet自体はHttpServletを継承した、ただのServletクラス。
tomcat.addServlet(ctx, "HelloWorld", new HelloWorldServlet()); 
ctx.addServletMapping("/*", "HelloWorld");

// Tomcatの起動と永続化
tomcat.start();
while (true) {
    Thread.sleep(5000);
}
```

ここでキモなのが、`tomcat.addWebapp(null, "", baseDoc)`。Webアプリケーションのフレームワークにお世話になるならこの形式でプロジェクト内のWebアプリをデプロイしてもらう必要がある。

## 今回の学び

組み込みTomcatとJerseyMVCを同時に使用して思い通りに動作しないとどっちが悪いのかわからないまま全部良くないような気がしてくる。けれど上記の通り、それぞれは単にサーブレットコンテナとWebアプリの関係であるから、分けて考えることができる。

あと使用する技術要素は、時間をかけても1個ずつ基本を押さえておかないと、結局後からハマって余計時間がかかる。

明日のためにClojureの勉強しておこう。

## 参考資料

- [Java - JerseyMVCの使い方メモ - Qiita](http://qiita.com/opengl-8080/items/f4c25ad671e8a6dac743)
- [Embedding Tomcat(PDF)](http://people.apache.org/~markt/presentations/2010-11-04-Embedding-Tomcat.pdf)