UserTransaction開始タイミング
UserTransaction.begin()を呼ぶ前にデータソースを取得しておかなければならないのか,あるいはUserTransaction.begin()を呼んだ後にデータソースを取得するという順番でないとならないのか,これはJ2EE実装依存の話のようだ。
この間はJBossかWebLogicかのどちらかの都合にあわせて(詳細失念)beginの前にデータソースを取得するようにテストコードを書いていた.例えばこんな感じである.
InitialContext ctx = new InitialContext(); UserTransaction ut = (UserTransaction) ctx.lookup(Const.USER_TRANSACTION_JNDI); DataSource ds = (DataSource) ctx.lookup(Const.XADS_JNDI); Connection conn = ds.getConnection(); conn.setCatalog("test"); Statement stmt = conn.createStatement(); ut.begin(); stmt.executeUpdate("INSERT INTO xasimpletest VALUES (1)"); ut.commit();
ところがWebSphereの場合はこの手順で実行すると次のようなエラーが発生する.
java.lang.IllegalStateException: Cannot start a new UOW. A LocalTransactionContainment is already active with work. at com.ibm.ws.LocalTransaction.LTCUOWCallback.uowPreBegin(LTCUOWCallback.java:238) at com.ibm.ws.LocalTransaction.LTCUOWCallback.contextChange(LTCUOWCallback.java:154) at com.ibm.ws.uow.UOWScopeCallbackManager.notifyCallbacks(UOWScopeCallbackManager.java:62) at com.ibm.ws.Transaction.JTA.UserTransactionImpl.begin(UserTransactionImpl.java:162) at testsuite.integration.xa.simple.websphere.SingleCommit2Servlet.doGet(SingleCommit2Servlet.java:58)
CMTなEJBでのことなら納得できるのだが,Servletとかで上記テストコードを走らせてこのエラーがでるとちょっと不思議に思う.
beginとデータソースの順序を以下のように入れ替えるとWebSphereでは上手くいく.(JBossかWebLogicのどちらかでうまくいかない,どっちだったっけな・・・)
InitialContext ctx = new InitialContext(); UserTransaction ut = (UserTransaction) ctx.lookup(Const.USER_TRANSACTION_JNDI); ut.begin(); DataSource ds = (DataSource) ctx.lookup(Const.XADS_JNDI); Connection conn = ds.getConnection(); conn.setCatalog("test"); Statement stmt = conn.createStatement(); stmt.executeUpdate("INSERT INTO xasimpletest VALUES (1)"); ut.commit();
まあとりあえずこういうメモを残しておこうということで.