S2JMS 開発記 ExecutionContext と TransactionManager
WorkManager
の簡単な実装が概ね終了.
「簡単な実装」というのはスレッドプールをきめ細かく制御とかしていないため.例えばスレッドのプライオリティとか,スレッドプールにリクエストするキューの最大長を設定したりプライオリティキューにしたりなどなど.
大がかりなアプリケーションサーバならこの辺もちゃんとしないといけないのかもしれませんが,スタンドアロンな S2JMS-Container での利用を前提にするならあまり必要な状況にはならないような気のせいが.
そんなわけで (どんなわけで?),概ね終了.
「概ね終了」ということはまだ終了には至っていないわけですが,その大きなものが javax.resource.spi.work.ExecutionContext
のサポート.これがやっかいなんですよ.
ExecutionContext
というのは,リソースアダプタが受信したメッセージをワーカスレッド上で実行する際のトランザクションコンテキストを指定するもので,以下の二つのプロパティがあります.
- transactionTimeout
- xid
前者はまぁどうでもいいとして (いいのか?),問題は後者の xid.もちろん javax.transaction.xa.Xid
です.
昨日も書いたように,JCA + JMS + MDB というか要するに J2EE 改め JavaEE なプラットフォームでは,JMS メッセージを受信するスレッドとそれを処理する MDB を実行するスレッドが異なるモデルを想定している模様.
これはちょうど,ネットワークサービスを提供するサーバアプリケーションなどで,listen()〜accept()
するスレッドと,接続したコネクションからデータを受信して処理するスレッドを別にするのと同じようなものかな,と思います.
が,しかし.
JMS では接続待ちの代わりにメッセージの受信を行うわけですが,トランザクショナルにメッセージングを行う場合,その受信もトランザクションの一部になるという点に注意が必要.
んで,ですね.
JCA + JMS + MDB ではワーカスレッドで MDB の MessageListener#onMessage(Message)
を呼び出すわけですが,トランザクション境界はこの周囲に設定することになるっぽい.
つまり,ワーカスレッドで
TransactionManager#begin()
MessageListener#onMessage(Message)
TransactionManager#commit()
ってことになるみたいなんですが (これを実際に行うのが先に書いた MessageEndpoint
),これより前,ワーカスレッドに処理が届く前に JMS 実装はメッセージを受信しちゃってるわけで,それをどうやってこのトランザクションの一部にしたらよかとですか?
そんなわけで (どんなわけで?),ExecutionContext
です.
通常の JTA トランザクション制御では,リソースマネージャはトランザクションマネージャから渡された Xid
を使うのですが,JCA の Message Inflow なシナリオではリソースマネージャはトランザクションマネージャと関わることなく自分で勝手に Xid
を割り当ててトランザクションを開始してメッセージを受信しちゃう模様.
んで,その Xid
を ExecutionContext
に詰め込んでアプリケーションサーバに渡します.
そしてアプリケーションサーバはリソースマネージャが割り当てた Xid
をトランザクションマネージャに「インポート」するみたいなんですねぇ.
といっても,JTA 仕様では TransactionManager
あるいは Transaction
にそんなインタフェースは用意されていないので,トランザクションマネージャ固有のやり方で実装しろってことみたい.うーみゅ...
当然,現在の S2JTA ではそんな機能を持っていないので,手を加えないといけない感じ.
たぶん,TransactionManagerImpl
に begin(Xid, XAResource)
みたいなメソッドを追加するのかなぁ.
この XAResource
はもちろんメッセージを受信したリソースアダプタなのですが,そいつの start(Xid, int)
を呼び出すべきかどうかはまだ不明.どこに書いてあるの?
可能性としては,
- リソースは開始されていない.
TMNOFLAGS
でstart(Xid, int)
を呼び出す. - リソースはサスペンドしている.
TMRESUME
でstart(Xid, int)
を呼び出す. - リソースは開始されている.
prepare(Xid)
等を呼び出すまでやることなし.
といった辺りかなぁ.
最悪 JBoss や Geronimo のコードを追っかけて同じような振る舞いにするしかないかも〜.あ,ActiveMQ のリソースアダプタをチェックした方がいいかも.
そんなわけで (どんなわけで?),ちょっと時間がかかりそうですが,どっちみちこの辺の制御は WorkManager
ではなく MessageEndpoin
で対応することになりそうなので,WorkManager
としては一区切りかな.
ともあれ (JW),最新の S2JMS&S2JCA を明日 (01/04) 中に seasar.org の SVN に突っ込みたいと思います.