Hatena::ブログ(Diary)

裏紙

 

2013-05-07

Stateful Session BeanはたぶんSerializableをimplementsしなくて良いと思うような気がしなくもない

| 22:33

これはゆとりアドベントカレンダーの何日目かです。


なーんもネタを考えてなかったのに5月7日は現時点であと二時間を切ったのでTwilogからゆとりさんとの初めての会話でも掘り起こしてお茶を濁しておきます。


ということで、初めての会話はStateful Session BeanってSerializableをimplementsしてなくてよかったんだっけ?的なアレでした。

私がつぶやいている通り「EJB 3.1のJSRに保存と復元が出来たらSerializableじゃなくても良いよーん」という記載があったと思うのですが、どこに書いてたか今もって忘れております。てへ。

まあ、実際にGlassFish v3辺りで試すとSerializableをimplementsしなくても動いているので、しなくても良いのでしょうね。たぶん。おそらく。

では遅くなりましたが、ゆとりさん転職おめでとうございます!

(相変わらずヒドいエントリ)

大事な追記


大事な追記2

2013-01-12

ブログをhttp://backpaper0.github.com/にするます

23:54

“たぶんブログを移行するけどしばらくはこっちにも記事へのリンクを含んだエントリを投稿しようと思います。”などと書いておりましたが、移行しちゃいます。Tinkerer好きになっちゃいました。

2013-01-06

Welcome to Tinkerer

22:15


たぶんブログを移行するけどしばらくはこっちにも記事へのリンクを含んだエントリを投稿しようと思います。

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良いですね

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

こーど

2012-12-30

2012年を振り返る

00:44

春頃

鍋駆動 テスト冬の陣 〜テイスティング駆動モグモグさせろください〜を開催。相変わらずタイトルが酷い←

鹿駆動勉強会を開催(一応中の人)。TL上の会いたいと思っていた人達にお会い出来て嬉しかった。あと奈良公園の公衆トイレは鹿が入ってこないよう入り口に可動式の柵みたいなのがあった。

結婚式。従妹の子供がリングピローを運んでくれたり、同期(男)が号泣してくれたり、二次会に呼んだhoge駆動メンバーがTLで会話してたり、楽しくて嬉しくて感動した。二次会に来てくれたhogeメンのみんな、本当にありがとう!コミュ症治せよ!←

夏頃

なぜかプロジェクターがあるいろふ宅にてClassLoader駆動 15の昼を開催した。ClassLoaderを触った記憶が無い。たんごさんは終始カレー作ってた。めっちゃ美味しかったのでまた食べたい。よろしく!

神戸らへんでScalaを開催した。昼食をCafe Scalaで頂いた。「もう今日の目標は5割達成しましたね」料理もおいしかったしな! 冗談抜きで本編も楽しかったのでまたやりたい。というかやっていなくてすみません。

秋頃

新婚旅行でイタリアに行ってきた。ジョジョ5部とARIA(ただしベネチアのみ)に思いを馳せたりしつつ楽しんだ。あとスカラ座見たときは自分の中のプログラマがテンション上がった。

やきに駆動 2.0 〜日本よ、これがHoge駆動だ〜を開催した。相変わらずタイトルが酷い。HTTPサーバに滅びのHTTPメソッド、BALSを追加したという発表とデモを行った。簡易で低機能でははあるがHTTPサーバを書くのは楽しかった。

冬頃

社内でJenkinsを布教。まだまだ成功とは言えないが最初の一歩は踏み出せたと思う。来年、継続する。

大都会の合同勉強会と忘年会に参加。きちんとした発表が続いていた中、BALSサーバの再演をした。正直ビビっていたけれど、ウケて良かった。それにしてもあの瀬戸内コミュニティの結びつきの強さは見習うべきものがあると思う。楽しかったので可能であれば来年もお邪魔したいです。

先日忘年会駆動 2012を開催した。そういえばさっきから「開催した」と書いているがhoge駆動勉強会は全員が開催者兼、参加者兼、発表者ですのでそこんとこよろしく! 暗号について簡単に話した。次回はホームズの発表をしたい。IT関係無いけど問題ない。そう、hoge駆動ならね。初めましてのひとも何人かいらっしゃった。くっくっく……hogeの輪が順調に広がっておる(黒幕)。

まとめ

素敵な一年でした。TL、勉強会、会社、プライベートで関わったすべての方々、本当にありがとうございました! 来年もよろしくお願い致します!