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 ではワーカスレッドで MDBMessageListener#onMessage(Message) を呼び出すわけですが,トランザクション境界はこの周囲に設定することになるっぽい.
つまり,ワーカスレッドで

  • TransactionManager#begin()
  • MessageListener#onMessage(Message)
  • TransactionManager#commit()

ってことになるみたいなんですが (これを実際に行うのが先に書いた MessageEndpoint),これより前,ワーカスレッドに処理が届く前に JMS 実装はメッセージを受信しちゃってるわけで,それをどうやってこのトランザクションの一部にしたらよかとですか?


そんなわけで (どんなわけで?),ExecutionContext です.
通常の JTA トランザクション制御では,リソースマネージャはトランザクションマネージャから渡された Xid を使うのですが,JCA の Message Inflow なシナリオではリソースマネージャはトランザクションマネージャと関わることなく自分で勝手に Xid を割り当ててトランザクションを開始してメッセージを受信しちゃう模様.
んで,その XidExecutionContext に詰め込んでアプリケーションサーバに渡します.
そしてアプリケーションサーバはリソースマネージャが割り当てた Xidトランザクションマネージャに「インポート」するみたいなんですねぇ.
といっても,JTA 仕様では TransactionManager あるいは Transaction にそんなインタフェースは用意されていないので,トランザクションマネージャ固有のやり方で実装しろってことみたい.うーみゅ...


当然,現在の S2JTA ではそんな機能を持っていないので,手を加えないといけない感じ.
たぶん,TransactionManagerImplbegin(Xid, XAResource) みたいなメソッドを追加するのかなぁ.
この XAResource はもちろんメッセージを受信したリソースアダプタなのですが,そいつの start(Xid, int) を呼び出すべきかどうかはまだ不明.どこに書いてあるの?
可能性としては,

  • リソースは開始されていない.TMNOFLAGSstart(Xid, int) を呼び出す.
  • リソースはサスペンドしている.TMRESUMEstart(Xid, int) を呼び出す.
  • リソースは開始されている.prepare(Xid) 等を呼び出すまでやることなし.

といった辺りかなぁ.
最悪 JBossGeronimo のコードを追っかけて同じような振る舞いにするしかないかも〜.あ,ActiveMQ のリソースアダプタをチェックした方がいいかも.


そんなわけで (どんなわけで?),ちょっと時間がかかりそうですが,どっちみちこの辺の制御は WorkManager ではなく MessageEndpoin で対応することになりそうなので,WorkManager としては一区切りかな.
ともあれ (JW),最新の S2JMSS2JCA を明日 (01/04) 中に seasar.org の SVN に突っ込みたいと思います.