JAX-RS + mustache

これはJava EE Advent Calendar 2013の2日目のブログエントリーです。

昨日は@kikutaro_さんのJSF2.2のFaces Flows(FlowScoped)でした。
明日は@backpaper0さんです。よろしくおねがいします!

   

9月に開催されたJavaOne2013でJersey 2 MVC in Actionというセッションがあったそうです。

Jersey 2 MVC in Action [BOF5548]

JAX-RSの参照実装であるJerseyの独自機能ではありますが、良い機能が色々と含まれていて、テンプレートエンジンにmustacheも使えます。

個人的にはJerseyMVC自体をJavaEEの標準機能にして欲しいと思っているのですが、
JSFがあるので、それ以外のMVCフレームワークが標準機能に含まれる事は無いのかなぁ。。。

   

現時点では、まだ新規プロジェクトでJavaEE6を採用するケースが多いんじゃないかと思いますが、
JavaEE6(GlassFish3.1.2.2)でJAX-RSのテンプレートエンジンにmustacheを使えるようにするjersey-mustacheというのがあったので試してみました。
jersey-mustacheはMVCフレームワークではなく、mustacheをテンプレートエンジンに使えるようにするためのViewProcessorです。

 

今回はSonatypeにあるSnapshotを使うのでrepositoryを追加します。

```xml pom.xml sonatype-nexus-snapshots Sonatype Nexus Snapshots https://oss.sonatype.org/content/repositories/snapshots/


 

次にdependencyを追加。  
__jersey-mustacheがGlassFish3.1.2.2に含まれているバージョンと違うjersey-serverとjersey-coreに依存しているため、exclusionsで除外しました。__

```xml pom.xml
<dependency>
    <groupId>org.eluder.jersey</groupId>
    <artifactId>jersey-mustache</artifactId>
    <version>1.1.0-SNAPSHOT</version>
    <exclusions>
        <exclusion>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
        </exclusion>
        <exclusion>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

 

次にGlassFish3.1.2.2に含まれているJerseyのdependencyをprovidedで追加。

```xml pom.xml com.sun.jersey.glassfish.v3.osgi jersey-gf-server 1.11.1 provided


&nbsp;

そして、JAX-RSを有効にします。  
javax.ws.rs.ApplicationPathを継承したクラスを作れば良いのですが、今回はweb.xmlにしました。  
ついでにjersey-mustacheの初期パラメータを指定しています。  

* mustache.resource.root   -> テンプレート配置ディレクトリのルート
* mustache.template.expiry -> テンプレートキャッシュの有効期限(単位: ミリ秒)

```xml web.xml
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         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_3_0.xsd"
         version="3.0">
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>info.matsumana.resource; org.eluder.jersey.mustache</param-value>
        </init-param>
        <init-param>
            <param-name>mustache.resource.root</param-name>
            <param-value>/templates</param-value>
        </init-param>
        <init-param>
            <param-name>mustache.template.expiry</param-name>
            <param-value>3600000</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

 

サンプルとして、こんな画面を作りました。
参考ページ: 今どきのJava Webフレームワークってどうなってるの?

 

画面の初期表示

初期表示

 

値を入力すると足し算を行います。

submit後

 

{% raw %} テンプレートはこんな感じ。
{{ と }} で囲みます。ホントに口髭みたいですねw
Mapの場合はキーで参照、POJOの場合はフィールド名で参照します。POJOのフィールドはpublicでもOKです。 {% endraw %}

{% raw %} ```html calc.mustache <!DOCTYPE html> mustache Page

Hello JAX-RS!

        <input name="left" value="{{left}}" />
        と
        <input name="right" value="{{right}}" />
        <br/>
        <input type="submit" value="足す" />
        答え {{ans}}
    </form>
</body>
</html>
{% endraw %}

&nbsp;

リソースクラスはこんな感じ。  
mustacheとは関係ありませんが、POSTされたフォームの値をCalcResourceParamというDtoにマッピングして受け取れるようにしています。  
参考ページ: [JAX-RS (Jersey) でパラメータとして独自のクラスをインジェクトする (1)](http://kenichiro22.hatenablog.com/entry/20110124/1295854770)

```java CalcResource.java
@Named
@RequestScoped
@Path("calc")
@Produces(MediaType.TEXT_HTML)
public class CalcResource {

    @Inject
    CalcDomain calcDomain;

    @GET
    public Viewable index() {
        return JaxrsUtil.newViewable("/calc.mustache");
    }

    @POST
    public Viewable calc(@Context ResourceContext rc) {
        CalcResourceParam param = rc.getResource(CalcResourceParam.class);
        calcDomain.calc(param);

        return JaxrsUtil.newViewable("/calc.mustache", param);
    }
}

 

これがフォームの入力値をマッピングさせるDtoです。
フィールドに@FormParamアノテーションを付けます。
publicフィールドが嫌いな人はLombokをどうぞ。

```java CalcResourceParam.java public class CalcResourceParam {

@FormParam("left")
public Integer left;
@FormParam("right")
public Integer right;
public Integer ans;

}


&nbsp;

ドメインは計算しているだけ。

```java CalcDomain.java
@Named
@RequestScoped
public class CalcDomain {

    public void calc(CalcResourceParam param) {
        param.ans = param.left + param.right;
    }
}

 

JavaにはFreeMarkerという定番テンプレートエンジンがあるので、mustacheはあんまり使われてないと思いますが、
Jersey 2 MVCをきっかけにシンプルさがウケけて流行るかも知れませんね!

ソースはこちらに置いています。
jersey-mustache-sandbox

 
comments powered by Disqus