Hatena::ブログ(Diary)

裏紙

 | 

2012-12-31

Thymeleaf + JAX-RS + DomaをGlassFishで試してみる

| 23:30


というわけでやってみました。

とは言え、Thymeleaf + JAX-RSとJAX-RS + Domaをやれば良いのでそれぞれ見ていきます。

Thymeleaf + JAX-RS

以前やったときはJAX-RSのリソースメソッドでテンプレートのパスとバインドするパラメータをまとめたオブジェクトを返してました。

例えば、こんな感じです。

    @GET
    public ThymeleafTemplate sayHello(@QueryParam("yourName") String yourName) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("message", "Hello, " + yourName + "!");
        return new ThymeleafTemplate("hello.html", variables);
    }

ThymeleafTemplateというぁゃιぃクラスをnewしてたり、テンプレートにバインドする変数名がマップのキーなので文字列で設定してたり、あんまり嬉しくないなー、とか思ったり。

POJOを返すようにしておけばJacksonかましてJSONを返すように簡単に出来たりテストやりやすかったりすると思うので、今回は@Templateというアノテーションを作ってそれでテンプレートのパスを設定するようにしてみました。

リソースメソッドはこんな感じになりました。

    @GET
    @Template("hello.html")
    public HelloResponse sayHello(@QueryParam("yourName") String yourName) {
        HelloResponse response = new HelloResponse();
        response.setMessage("Hello, " + yourName + "!");
        return response;
    }

MessageBodyWriter#writeToではリフレクション使ってプロパティ名をキーにしてマップに突っ込んでからテンプレートに渡しています。リソースメソッドの戻り値がStringや基本型のラッパー、コレクションの場合は固定でvalueというキーでマップに突っ込むなどすると上記サンプルコードのように余計なクラスを作らなくてすむので良いかもしれませんね。というかどっちかっつーとMessageBodyWriterの実装の方が大事なのにコードを載せていないという。詳しくはThymeleafMessageBodyWriterを見てくださいませ。

JAX-RS + Domaそのいち

シンプルに普通にDaoImplをnewしても良いかもですね。

@Path("hello")
public class Hello {

    private MessageDao messageDao = new MessageDaoImpl();

    ...
}

Configはこんな感じ。DataSourceはJNDIルックアップ。

public class DomaConfig extends DomaAbstractConfig {

    private static Dialect dialect = new StandardDialect();

    @Override
    public DataSource getDataSource() {
        try {
            return InitialContext.doLookup("jdbc/__default");
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public Dialect getDialect() {
        return dialect;
    }
}

ただこの方法だとDaoをモックにすげ替えて雲丹っとテスト回したりするのがちょい面倒です。Java EE 6ならCDIで接着する方が嬉しそうですね。

JAX-RS + Domaそのに(CDIで接着バージョン)

DataSource、Dialectのプロデューサーを作成します。DataSourceのプロデューサーはこんな感じ。

package sample;

import javax.annotation.Resource;
import javax.enterprise.inject.Produces;
import javax.sql.DataSource;

public class DataSourceProducer {

    @Resource(name = "jdbc/__default")
    @Produces
    DataSource dataSource;

}

適当にクラス作ってフィールド定義して@Producesで注釈するだけです。JAX-RSのアノテーションにも@Produces(javax.ws.rs.Produces)があるけどそっちじゃないのでパッケージ名に注意です。

次に、Config実装クラスはJNDIルックアップしていましたが、フィールドを定義して@Injectでインジェクトします。

package sample;

import javax.inject.Inject;
import javax.sql.DataSource;
import org.seasar.doma.jdbc.DomaAbstractConfig;
import org.seasar.doma.jdbc.dialect.Dialect;

public class DomaConfig extends DomaAbstractConfig {

    @Inject
    private DataSource dataSource;

    @Inject
    private Dialect dialect;

    @Override
    public DataSource getDataSource() {
        return dataSource;
    }

    @Override
    public Dialect getDialect() {
        return dialect;
    }
}

DAOクラスは@DaoでConfig実装クラスを指定するのではなくコンストラクタインジェクションされるようにします。コンストラクタインジェクションするにはコンストラクタを@Injectで注釈する必要があります。DomaではDao実装クラスへの注釈を@AnnotateWithで設定することができます。Doma素晴らしいですね。

package sample;

import javax.inject.Inject;
import org.seasar.doma.AnnotateWith;
import org.seasar.doma.Annotation;
import org.seasar.doma.AnnotationTarget;
import org.seasar.doma.Dao;
import org.seasar.doma.Select;

@Dao
@AnnotateWith(annotations = {
    @Annotation(type = Inject.class, target = AnnotationTarget.CONSTRUCTOR)
})
public interface MessageDao {

    @Select
    Message select(Long id);
}

あとはリソースクラスでDaoを@Injectでインジェクトすればおk。

package sample;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;

@Path("hello")
@LocalBean
@Stateless
public class Hello {

    @Inject
    private MessageDao messageDao;

    ...
}

@Statelessで注釈してSession Beanにするとリソースメソッドがトランザクション境界になってSAStrutsにお世話になってたひと(つまり私)は幸せです。あとno-interfaceなので@LocalBeanで注釈しています。

まとめ

  • Thymeleaf良いですね
  • JAX-RS良いですね
  • EJB 3.1良いですね
  • Doma良いですね
  • CDI良いですね
  • GlassFish良いですね
  • Arquillian良いですね
  • Guice良いですね

大晦日に何やってんねん。

こーど

トラックバック - http://d.hatena.ne.jp/backpaper0/20121231/1356964206
 |