S2Containerのドキュメント

ここ数日静かだったのでもしやと思っていたら案の定.(^^;
それにしてもすごい... ひがさんのプライドを見た感じ.
しかし... ひがさんの集中力とか瞬発力とか見習いたいと思いながらも,これから「ウォーターボーイズ2」を見ようとしている自分が悲しい...
心より恥じる.

「ウォーターボーイズ2」

後ろめたさを感じつつも,今週のえみちぃチェーーック!!
今週はすごいっすよぉ.

  • なにコソコソ コソコソ コソコソしゃべってんの?
  • たーいへん,たいへん,たいへん!!
  • みぃんな,みんな,みんなぁー!
  • 頑張れ,頑張れ,頑張れぇ〜.
  • 永吉君のこと,ホントにホントにホントになんでもないんだよね?
  • やって やって やってぇ〜.

「旅美人」

今週の旅美人は悠美.モデルっぽいです.ぐぐってみたら JJ とかに出ていたのですか? ちょっと記憶にない... 残念!!!!
でも,さすがにスタイルはいいなぁ.
行き先は群馬県の前橋.そして当地出身(?)の詩人,萩原朔太郎の話が.
それはもしや,先週のセカチューで朔ちゃんの名前の由来として出てきた人ですか?
今週は街中なのか,風景があまり出てきませんでした.残念!!!!

Hibernate 入門記 セッションその8 後始末とテンプレ

お待たせいたしました.今回はついに「9.7. Ending a Session」へと進みます.待望の,セッションの後始末です!!
いやぁ,たかが後始末とはいえ,入門記開始以来○ヶ月にわたってセッションの後始末をすることなく過ごしてきましたからねぇ.まさに「心より恥じる」ですよ.
しかし,それも昨日までの話.今日からは,きれいに後始末するのだ.残念!!!!
ということで,まずはセッションを終了する過程は次のようになっているとのことです.

  1. セッションのフラッシュ.
  2. トランザクションのコミット.
  3. セッションのクローズ.
  4. 例外のハンドリング.

なぁんだ,セッションのクローズ以外はもうやってますね.残念!!!!
…イヤべつに残念でもなんでもないのですが


そんなわけでまずは最初のステップ,「9.7.1. Flushing the Session」です.昨日学習したばっかりなのですが,再度登場です.
なんでも,Transaction を使ってトランザクションをコミットする場合には,セッションのフラッシュを明示的にしなくてもよいのだとか.それはおそらく,セッションのフラッシュモードが AUTO または COMMIT の場合の話だと思いますが.
そうでなければ Session#flush() を呼び出せとのこと.らじゃ.


そして次のステップは「9.7.2. Committing the database transaction」です.
トランザクションをコミットまたはロールバックする方法は,二通りあります.
一つめは Transaction を使う方法で,次のメソッドを呼び出します.

    • void commit()
    • void rollback()

もう一つは JDBC コネクションを使う方法です.JDBC コネクションは,Session#connection() により取得することが出来ます.
そうかぁ,Session#connection() は単に JDBC コネクションを返すのですね.それを直接使って commit()rollback() しても,Hibernate は介入しないので,勝手にフラッシュしてくれたりはしなかったのかぁ.残念!!!!
ということは,基本的に Transaction を使うべきということでしょう.こちらを使った場合は,JTA を利用した分散トランザクションにも対応できるとのことです.
なお,トランザクションロールバックした場合は,即座にセッションを終了しろとのことです.そうすれば,Hibernate の内部状態の一貫性が保証されるとのこと.らじゃ.


そしてついに!! 「9.7.3. Closing the Session」です.
セッションを終了するには,Session

    • Connection close()

を使用します.それだけですか.こんな簡単なことを延々今日まで放置してきたのか... 無念だ.
ちなみにこの Session#close() ですが,Hibernate が管理する JDBC コネクションを使っている場合には,JDBC コネクションはプールに戻されます.SessionFactory#openSession(Connection)JDBC コネクションを与えた場合は,Session#close() は何もしないで,元の JDBC コネクションが返されます.そのコネクションのクローズは自分でやれということですね.


そして最後のステップ,「9.7.4. Exception handling」です.
もしセッションが例外をスローしたら,トランザクションロールバックして,セッションをクローズして,セッションのインスタンスを破棄しろとのことです.あらら,そうだったんだ...
そんなわけで,Transaction を使った場合,JDBC コネクションのトランザクションを使った場合,JTA を使った場合の推奨イディオムが掲載されています.テンプレですね.


ということで早速お試ししましょう.
今回もテーブル,モデルの永続クラス,マッピングファイルは前々回と同じです.
手抜きじゃありませんよぉ〜.
そんなわけで (いみふめ),今回はテンプレを作りましょう.
まずはテンプレからコールバックされる interface

package study;
import net.sf.hibernate.Session;

public interface HibernateCallback {
    Object doProcess(Session session) throws Exception;
}

そしてテンプレート.

package study;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;

public class HibernateTemplate {
    SessionFactory factory;

    public HibernateTemplate() throws HibernateException {
        this(new Configuration());
    }
    public HibernateTemplate(Configuration config) throws HibernateException {
        factory = config.configure().buildSessionFactory();
    }

    public Object process(HibernateCallback callback) throws Exception {
         Session session = factory.openSession();
        try {
            Transaction tx = session.beginTransaction();
            try {
                Object result = callback.doProcess(session);
                tx.commit();
                return result;
            }
            catch (Exception e) {
                tx.rollback();
                throw e;
            }
        }
        finally {
            session.close();
        }
    }
}

名前がパクリなのは気にしない気にしない.
リファレンスのテンプレとは微妙に異なっていますが,自分はこんな風に,リソース (この場合は SessionTransaction) を獲得するたびに try ブロックを書くのが好きです.多少入れ子が深くなっても (深すぎると思ったらメソッド分割!!).
Transaction#commit() の呼び出しでセッションのフラッシュが行われることを前提に,Session#flush() は明示的に呼び出していません.もし,HibernateCallback(Session) の中でフラッシュモードを変更した場合は,自己責任でフラッシュするものとしました.
ということで,このテンプレを使った実行用のクラス.

package study;
import java.util.Iterator;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;

public class Main {
    public static void main(String[] args) {
        try {
            HibernateTemplate template = new HibernateTemplate();

            System.out.println("*** first session ***");
            template.process(new HibernateCallback() {
                public Object doProcess(Session session) throws Exception {
                    Model yuri = new Model("Yuri Ebihara", "CanCam");
                    session.save(yuri);
                    Model yu = new Model("Asami Usuda", "CanCam");
                    session.save(yu);
                    Model sayo = new Model("Sayo Aizawa", "ViVi");
                    session.save(sayo);
                    return null;
                }
            });

            System.out.println("*** second session ***");
            template.process(new HibernateCallback() {
                public Object doProcess(Session session) throws Exception {
                    Iterator it = session.find("from study.Model").iterator();
                    while (it.hasNext()) {
                        System.out.println(it.next());
                    }
                    return null;
                }
            });
        }
        catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

最初のセッションで永続オブジェクトを作成して,次のセッションでそれを問い合せしているだけです.
こいつを実行!!!!

*** first session ***
onSave() : Yuri Ebihara
Hibernate: insert into Model (name, magazine, id) values (?, ?, null)
Hibernate: call identity()
onSave() : Asami Usuda
Hibernate: insert into Model (name, magazine, id) values (?, ?, null)
Hibernate: call identity()
onSave() : Sayo Aizawa
Hibernate: insert into Model (name, magazine, id) values (?, ?, null)
Hibernate: call identity()
*** second session ***
Hibernate: select model0_.id as id, model0_.name as name, model0_.magazine as magazine 
           from Model model0_
onLoad() : Yuri Ebihara
onLoad() : Asami Usuda
onLoad() : Sayo Aizawa
Yuri Ebihara (CanCam)
Asami Usuda (CanCam)
Sayo Aizawa (ViVi)

おっけー.
ふぅー,これでやっとこさ後ろめたさがなくなって気分すっきり♪
にしても,なんでここまで引っ張る羽目になったんだっけ? 覚えてないなぁ.まいっか.

S2Axis 開発記 準備その2 JWSHandler

Axis には JWS という,手軽に Web サービスを記述して配備する機能があるそうです.
JWS というのは,拡張子 .jws を持ったただの Java ソースファイルです.ただし,パッケージに属することは出来ないみたいですが.
その JWS を Axis の管理しているディレクトリに配置すると,それだけでそこに記述されたクラスが Web サービスとして公開されるらしいです.すげー.
いわば,JSP の Web サービス版ですね.
このメカニズム,S2Axis に使えるんじゃないかなぁ?


昨日はこう書いたんですけど...

自分が最初にこの S2Axis の話を聞いたときにイメージしたのは,Axis と S2 (コンテナ&コンポーネント) を組み込んだ Web アプリを Tomcat なんかにデプロイすると,S2ContainerServlet の初期化の際に S2Axis によってコンポーネントが Axis に登録されるというもの.

なんかこれ,イマイチっぽい.
というのも,コンテナ内のどのコンポーネントを Axis に登録するか? という問題があるから.
コンポーネントを片っ端から全部登録するってのはイマイチですよね.DataSource とか公開してどうするの? とかあるわけで.
そうすると,Web サービスとして公開するコンポーネントを識別できるように,dicon ファイルに何らかの方法で記述してあげなくてはなりません.
集中管理的なアプローチだと,S2Axis が Web サービス公開用のコンポーネントを提供して,そのプロパティに設定されたコンポーネント (複数) が公開されるとか.
あるいは分散管理的なアプローチだと,公開対象のコンポーネントS2Axis が提供するアスペクトを組み込むとか.
でも,これだと Web サービス用の記述が必要になるわけで,WSDD を書くのと手間は大して変わらないんじゃないかと思ったり.S2 らしい「易しさと優しさ」が足りない気がしたわけです.


そこで JWS 的アプローチ.
JWS を処理するのは JWSHandler というクラスなのですが概ね次のように動いているようです.

ここで,JWS を見つけてコンパイルする代わりに,S2 コンテナからコンポーネントをルックアップして同じ事をすればいいのではなかろうか?
Axis というのはメッセージを処理する「ハンドラ」の固まりとして実装されていて,その構成はかなり自由にできるようなことがドキュメントに書いてあります.であれば,このアプローチでもいけそうな気がします.


ということで,JWS の実装を中心に学習していこうと思います.
え? これだけかって? (^^; うん,今日はこれだけです.
...はい、学習できない子なんです。
残念!!!!