Re: JtaTransactionManagerとnon-XA-awareのDataSource
またまた id:taedium さんからネタを頂きました.(^^;
まずはちょっと整理.
JTA は分散トランザクションすなわち 2 フェーズコミットを利用するために規定されている仕様で,トランザクションを表現するインタフェースとして Transaction
,トランザクションに参加できるリソースを表現するインタフェースとして XAResource
を定めています.そして,Transaction#enlistResource(XAResource)
を呼び出す事で,そのリソースをトランザクションに参加させることが出来ます.
ここで注意すべきなのは,誰が Transaction#enlistResource(XAResource)
を呼び出すかは規定されていない (そういうインタフェースやクラスは決められていないという意味) ということです.
次に JDBC ですが,こちらで分散トランザクションに関連するのは XADataSource
と XAConnection
です.XAConnection#getXAResource()
を呼び出すと,その RDBMS を表す XAResource
を取得することが出来ます.
ここで注意すべきなのは,誰が XAConnection#getXAResource()
を呼び出すかは規定されていないということです.
そんなわけで (どんなわけで?),JTA と JDBC を並べてみると,XAResource
を通じて両者を結びつける存在が欠けていることが分かります.それを担うのは誰か? J2EE 仕様的には,アプリケーションサーバということになっています.とはいえ,別にアプリケーションサーバである必要はありません.多くの場合,この仲介者としての責務を果たすのはコネクションプールです.
ということで JDBC を見直すと,XAConnection
は PooledConnection
を extends
しています.PooledConnection
とはプールされるコネクションということですよね.プールする側ではなくて,プールされる側.XAConnection
はどこかにコネクションプールが存在し,そいつにプールされることを前提としているわけです.
通常,コネクションプールは DataSource
を実装します.そしてアプリケーションから getConnection()
が呼び出されると,プールされている XAConnection
を取ってきて XAResource
を取得し,Transaction#enlistResource(XAResource)
を呼び出します.そして XAConnection#getConnection()
が返す Connection
をアプリに返すわけです.
ちなみに,大抵のコネクションプールは非 XA な DataSource
を JTA なトランザクションに参加させるためのラッパーも提供していると思います.
という具合に,コネクションプールはとても重要な存在なのですが,それは仕様の一部ではなくて個別に提供される実装です.そんなわけで (どんなわけで?),S2 はコネクションプールの実装として S2DBCP を提供しています.さらに S2 では JTA の実装も S2Tx として提供しています.
一方 Spring はそのようなコネクションプールの実装を提供していません (たぶん).JTA の実装も提供していません (たぶん).それらはどこかから調達してくる必要があります.かつての入門記ではそのために S2DBCP と S2Tx を使いましたが,その他に例えば 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 はできませんが).
頑張ってねぇ〜.