Re: JtaTransactionManagerとnon-XA-awareのDataSource

またまた id:taedium さんからネタを頂きました.(^^;
まずはちょっと整理.
JTA は分散トランザクションすなわち 2 フェーズコミットを利用するために規定されている仕様で,トランザクションを表現するインタフェースとして Transactionトランザクションに参加できるリソースを表現するインタフェースとして XAResource を定めています.そして,Transaction#enlistResource(XAResource) を呼び出す事で,そのリソースをトランザクションに参加させることが出来ます.
ここで注意すべきなのは,誰が Transaction#enlistResource(XAResource) を呼び出すかは規定されていない (そういうインタフェースやクラスは決められていないという意味) ということです.


次に JDBC ですが,こちらで分散トランザクションに関連するのは XADataSourceXAConnection です.XAConnection#getXAResource() を呼び出すと,その RDBMS を表す XAResource を取得することが出来ます.
ここで注意すべきなのは,誰が XAConnection#getXAResource() を呼び出すかは規定されていないということです.


そんなわけで (どんなわけで?),JTAJDBC を並べてみると,XAResource を通じて両者を結びつける存在が欠けていることが分かります.それを担うのは誰か? J2EE 仕様的には,アプリケーションサーバということになっています.とはいえ,別にアプリケーションサーバである必要はありません.多くの場合,この仲介者としての責務を果たすのはコネクションプールです.
ということで JDBC を見直すと,XAConnectionPooledConnectionextends しています.PooledConnection とはプールされるコネクションということですよね.プールする側ではなくて,プールされる側.XAConnection はどこかにコネクションプールが存在し,そいつにプールされることを前提としているわけです.
通常,コネクションプールは DataSource を実装します.そしてアプリケーションから getConnection() が呼び出されると,プールされている XAConnection を取ってきて XAResource を取得し,Transaction#enlistResource(XAResource) を呼び出します.そして XAConnection#getConnection() が返す Connection をアプリに返すわけです.
ちなみに,大抵のコネクションプールは非 XA な DataSourceJTAトランザクションに参加させるためのラッパーも提供していると思います.


という具合に,コネクションプールはとても重要な存在なのですが,それは仕様の一部ではなくて個別に提供される実装です.そんなわけで (どんなわけで?),S2 はコネクションプールの実装として S2DBCP を提供しています.さらに S2 では JTA の実装も S2Tx として提供しています.
一方 Spring はそのようなコネクションプールの実装を提供していません (たぶん).JTA の実装も提供していません (たぶん).それらはどこかから調達してくる必要があります.かつての入門記ではそのために S2DBCPS2Tx を使いましたが,その他に例えば ObjectWeb の XAPool と JOTM を使うことも出来るでしょうし,JBoss や WebSphere,WebLogic 等が提供するコネクションプールや JTA の実装を使うことも当然出来るでしょう.
その場合,JDBC コネクションをクローズしたりするのは Spring ではなくてコネクションプールの実装です.ですから,Spring のソースを見ても何も分かりませんから!! 残念!!!!


そんなわけで (どんなわけで?),「Spring では beforeCompletion でコネクションをクローズしている」という話の対象になると私が思ったのは JTA を使わない DataSourceTransactionManager を使った場合の話です.この場合も,一般的な DataSource は Spring の DataSourceTransactionManager の存在なんか知らないので,誰かが両者を結びつける必要があります.それを実際に行っているのが悪名高い DataSourceUtils で,それを意識しなくてもいいように追加されたのが TransactionAwareDataSourceProxy ということになります (たぶん).


ともあれ (JW),Spring で JTA を使いたいのなら JTA の実装とコネクションプールの実装が必要です.S2Tx および S2DBCP を使うのは以前入門記でやっているので,ここは是非 JOTM と XAPool でやってみてください.これらは Spring のディストリビューションに含まれています.XAPool には非 XA な DataSource に対するラッパーもついているので,HSQLDB とかでもお試しできます (その場合本当の 2PC はできませんが).
頑張ってねぇ〜.