TX その9 CMTにおけるトランザクションマネージャ
昨日の日記
あとはCMTが"java:/TransactionManager"をlookupして使っているということが証明できれば,CMT/BMTといったレイヤーの話を切り捨ててTransactionManager以下のレイヤーのみで話を進められる.
これを調べるためにCMT関連のソースを読んでいたのだが「かなり」道草を食ってしまった.そろそろ本題に戻ろう.
TxInterceptorCMTクラスにある"javax.transaction.TransactionManager"型インスタンス変数は親クラスであるAbstractTxInterceptorクラスから継承したもの.AbstractTxInterceptorクラスのcreateメソッドを見ると
public void create() throws Exception { super.create(); tm = getContainer().getTransactionManager(); }
と書いてある.コンテナに格納されているものを取ってきているだけのようだ.このgetContainer()はさらに親クラスなAbstractInterceptorクラスのメソッド.
public void setContainer(Container container) { this.container = container; } public Container getContainer() { return container; }
ただのアクセッサメソッドだ.ここでまた例の強引な手法でどの実装クラスが突っ込まれているのかをログに出してみる.
public void create() throws Exception { super.create(); tm = getContainer().getTransactionManager(); log.debug("ikdttr5 Container = " + getContainer()); log.debug("ikdttr5 TransactionManager = " + tm); }
再コンパイルしてJBoss起動後に"grep 'ikdttr5' server.log"をする.
DEBUG [TxInterceptorCMT] ikdttr5 Container = org.jboss.ejb.StatelessSessionContainer@5438e1 DEBUG [TxInterceptorCMT] ikdttr5 TransactionManager = org.jboss.tm.TxManager@1627b8b
とりあえずCMTでも"org.jboss.tm.TxManager"が使われていることが確認できた.絶対これが使われる,という証拠ではないけどね.
もう一押し欲しい.
StatelessSessionContainerのgetTransactionManagerは,親クラスのSessionContainerのさらに親クラスのContainerクラスのsetTransactionManagerでセットされたインスタンスを返すものだ.仕方が無いのでこのsetterを呼んでいるやつを探す.
EjbModuleクラスのinitializeContainerメソッドでセットしているようだが,このときに使っているインスタンス自体,EjbModuleクラスのコンストラクタで与えられたものだ.うーむ,もうちょい!
EjbModuleインスタンスをnewしているのはEJBDeployerクラス.EJBDeployerクラスが持っているTransactiomManagerインスタンスというのは,,,
tm = (TransactionManager)getServer().getAttribute(transactionManagerServiceName, "TransactionManager");
でた,MBeanServerから取得かよ.はぁ〜.
ObjectName(transactionManagerServiceName)もsetterメソッドで設定されているので証拠としての度合いがさがるが,まずこのObjectNameをlog.debugを追加して再コンパイル→再起動で調べる.ObjectNameは"jboss:service=TransactionManager"だった.
jmx-consoleによればこいつの実装MBeanクラスはXMBeanとのこと.つまり設定ファイルを見れとのこと.jboss-service.xmlで定義されている."org.jboss.tm.TransactionManagerService"クラスとのこと.つまり一回りしてまたここに戻ったということ.
変数定義
public static String JNDI_NAME = "java:/TransactionManager";
startServiceメソッドにて
bindRef(JNDI_NAME, "org.jboss.tm.TxManager");
これでやっとOK.