Wicket + Guice + warp-persist + JPA を試す

 WicketActiveObjects の組み合わせが良いよ!という記事をかなり前に書きました。ところが、その「良さ」を発揮するための Databinder というプロダクトがなかなか Wicket 1.4.x に対応してくれない! んじゃあ、自分でやるぜ! と思って Databinder のソースを見てみたのですが、ちょっと厳しいところがありまして(Wicket 1.4 のジェネリクス対応のせい)Databinder の開発チームも同じところで悩んでいることがあとでわかりました。

 ということで、WicketActiveObjects の組み合わせが流行っているなんて言われる割に Databinder なしでみんなどうやってるんだろ? なんて思っていたところです。もしかして、DTO 的なものをわざわざ作っているのでしょうか? それとも Proxy を使ってる? 何にしてもいまいちスマートにならないんですよね、私の頭では。

 となってくると、O/R マッパの再選考だ! となるわけです。そこで、今試しているのが JPA。半分食わず嫌いだったのですが、いままでよくつかってきた S2JDBC のエンティティがそのまま使えるし、この際やってみよう! となりました。S2JDBC を使わないのは、dicon の組み立てでハマりまくった経験が多く、さすがに疲れてきたからです。

 で、そのまま JPA を使うのはおもしろくないので、warp-persist を使ってみました。バージョンは 2.0-20090214 です。これは何をするものかというと、

するものです。

 使い方ですが、まず、WicketApplication クラスの init メソッドの例です。

    @Override
    protected void init() {
        super.init();

        // warp-persist の Guice モジュール生成
        Module warpModule = PersistenceService.usingJpa().across(UnitOfWork.REQUEST).buildModule();

        // Guice Injector を生成
        Injector injector = Guice.createInjector(warpModule, buildWebModule());

        // Wicket に登録
        addComponentInstantiationListener(new GuiceComponentInjector(this, injector));
    }

    protected Module buildWebModule() {
        return new AbstractModule() {
            public void configure() {
                // JPA の persistence.xml に記述している persistence-unit name を指定
                bindConstant().annotatedWith(JpaUnit.class).to("persistence-unit name");
            }
        };
    }

次に DAO (S2JDBC 風にいえば Service)の作り方の例です。

package com.example.dao;

import com.example.dao.impl.SomeEntityDaoImpl;
import com.example.entity.SomeEntity;
import com.google.inject.ImplementedBy;

@ImplementedBy(SomeEntityDaoImpl.class)
public interface SomeEntityDao {
    void someMethod(SomeEntity someEntity);
}
package com.example.dao.impl;

import javax.persistence.EntityManager;

import com.example.dao.SomeEntityDao;
import com.example.entity.SomeEntity;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.wideplay.warp.persist.Transactional;

@Transactional
public class SomeEntityDaoImpl implements SomeEntityDao {
    @Inject
    private Provider<EntityManager> entityManagerProvider;

    @Override
    public void someMethod(SomeEntity someEntity) {
        EntityManager em = entityManagerProvicer.get();

        // 処理
    }
}

最後に web.xml に以下の filter を追加

    <filter>
        <filter-name>warpPersistFilter</filter-name>
        <filter-class>com.wideplay.warp.persist.PersistenceFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>warpPersistFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

以上です。JPA 自体の説明は今回は割愛します。

 JPA のエンティティは、POJO なので Wicket でも扱い易くていいですね。