大鳥的學(xué)習(xí)樂園
          路漫漫其修遠(yuǎn)兮,吾將上下而求索
          posts - 26,comments - 27,trackbacks - 0
          在WebLogic 7/8/9中,對(duì)TransactionManager的引用可以通過在Weblogic 7的TxHelper中定義的靜態(tài)方法getTransactionManager()而獲得。該類在WebLogic 8中被否決了,而用TransactionHelper取而代之。

          public TransactionManager getFromWebLogicFactory()
          throws Exception {
          try {
          // WebLogic 8/9
          return
          weblogic.transaction.TransactionHelper
          .getTransactionManager();
          }
          catch (ClassNotFoundException ex) {}

          try {
          // WebLogic 7
          return
          weblogic.transaction.TxHelper
          .getTransactionManager();
          }
          catch (ClassNotFoundException ex) {}

          return null;
          }


          使用TransactionManager

            一旦成功地獲得TransactionManager引用,就可以用它來掛起和恢復(fù)事務(wù),正如以下的示例代碼所示。

          // obtain UserTransaction object and start transaction
          InitialContext ctx = new InitialContext();
          UserTransaction userTransaction = (UserTransaction)
          ctx.lookup("java:comp/UserTransaction");

          // start first transaction
          userTransaction.begin();

          // obtain TransactionManager
          // using one of the methods described above
          TransactionManager tm = getTransactionManager();

          // suspend transaction
          // suspend() returns reference to suspended
          // Transaction object which later should be passed
          // to resume()
          Transaction transaction = tm.suspend();

          // here you can do something outside of transaction
          // or start new transaction,
          // do something and then commit or rollback
          userTransaction.begin();

          // commit subtransaction
          userTransaction.commit();

          // resume suspended transaction
          tm.resume(transaction);

          // commit first transaction
          userTransaction.commit();
          ...



          正如您所看到的,在TransactionManager接口的幫助下,可以對(duì)UserTransaction所提供的標(biāo)準(zhǔn)功能進(jìn)行擴(kuò)展,在BMT代碼中實(shí)現(xiàn)與CMT bean相同的靈活性水平。

            需要知道的是,當(dāng)事務(wù)被掛起時(shí),并不意味著事務(wù)的計(jì)時(shí)器停止了。換言之,如果把事務(wù)的超時(shí)設(shè)定為30秒,而事務(wù)已掛起了20秒并恢復(fù)了,那么該事務(wù)只剩10秒就要到達(dá)超時(shí)了。事務(wù)的掛起會(huì)解除事務(wù)與正在運(yùn)行的線程之間的關(guān)聯(lián),然后resume()調(diào)用會(huì)再次將其關(guān)連,而不影響事務(wù)超時(shí)計(jì)時(shí)器。

            已知問題

            因?yàn)镴2EE規(guī)范并不要求TransactionManager在J2EE容器中的可用性以及功能(雖然從底層的JTA基礎(chǔ)架構(gòu)中我們知道它應(yīng)該是存在的),所以有些應(yīng)用服務(wù)器中存在一些問題。例如,在WebLogic 7、8以及9(beta版)中有種特別奇怪的現(xiàn)象:假如一個(gè)事務(wù)被標(biāo)記為回滾(通過調(diào)用UserTransaction.setRollbackOnly()),然后被掛起,當(dāng)被掛起的事務(wù)嘗試恢復(fù)時(shí),它將會(huì)出現(xiàn)如下的提示:
          javax.transaction.InvalidTransactionException: Attempt to resume an inactive transaction

          以下代碼說明了該行為:

          // obtain UserTransaction object and start transaction
          InitialContext ctx = new InitialContext();
          UserTransaction userTransaction = (UserTransaction)
          ctx.lookup("java:comp/UserTransaction");
          userTransaction.begin();

          // mark for rollback
          userTransaction.setRollbackOnly();

          TransactionManager tm = getTransactionManager();

          // suspend transaction
          Transaction transaction = tm.suspend();

          // resume suspended transaction
          // this call will fail with InvalidTransactionException
          // in WebLogic
          tm.resume(transaction);
          ...


          幸運(yùn)的是,對(duì)于該問題,有一個(gè)應(yīng)急方案。WebLogic的TransactionManager實(shí)現(xiàn)連同標(biāo)準(zhǔn)的resume(Transaction transaction)方法,有一個(gè)可用于替代的forceResume方法。以下的代碼展示了一種在WebLogic中運(yùn)行代碼時(shí)需要用到的模式。注意,在這種情況下,應(yīng)該把對(duì)TransactionManager的引用轉(zhuǎn)換到WebLogic的定制實(shí)現(xiàn)接口(WebLogic 7中的weblogic.transaction.TransactionManager或WebLogic 8以及更高版本中的weblogic.transaction.ClientTransactionManager)。

          ...
          // obtain UserTransaction object and start transaction
          InitialContext ctx = new InitialContext();
          UserTransaction userTransaction = (UserTransaction)
          ctx.lookup("java:comp/UserTransaction");
          userTransaction.begin();

          // mark for rollback
          userTransaction.setRollbackOnly();

          TransactionManager tm = getTransactionManager();

          // suspend transaction
          Transaction transaction = tm.suspend();

          // resume suspended transaction
          try ...{
          // first try standard JTA call
          tm.resume(transaction);
          }
          catch (InvalidTransactionException e) ...{
          // standard method failed, try forceResume()
          if (tm instanceof
          weblogic.transaction.ClientTransactionManager) ...{
          // WebLogic 8 and above
          ((weblogic.transaction.ClientTransactionManager)tm)
          .forceResume(transaction);
          }
          else if (tm instanceof
          weblogic.transaction.TransactionManager) ...{
          // WebLogic 7
          ((weblogic.transaction.TransactionManager)tm)
          .forceResume(transaction)
          }
          else ...{
          // cannot resume
          throw e;
          }
          }
          ...


          TransactionManager在Spring Framework中的用法

            在流行的Spring framework中,以上所描述的技術(shù)都被廣泛地用于事務(wù)代理。應(yīng)該注意的是,每次使用PROPAGATION_REQUIRES_NEW或PROPAGATION_NOT_SUPPORTED、事務(wù)屬性以及JtaTransactionManager來配置Spring的TransactionProxyFactoryBean時(shí),Spring就會(huì)用JTA的TransactionManager來掛起和恢復(fù)事務(wù)。Spring太智能了,但有時(shí)太智能了反而使我無法接受——甚至沒有指定,它就會(huì)發(fā)現(xiàn)容器中的TransactionManager。例如,當(dāng)在一個(gè)Spring應(yīng)用程序上下文中定義JtaTransactionManager時(shí),就可以為UserTransaction提供一個(gè)JNDI名,而如果UserTransaction也實(shí)現(xiàn)了它,它就將“自動(dòng)檢測(cè)”TransactionManager。如上所示,這對(duì)WebLogic、Orion和Oracle OC4J都適用。

            有時(shí),這可能并不是我們所想要的,尤其是當(dāng)您想要嚴(yán)格遵循J2EE/EJB規(guī)范,并確保跨所有J2EE容器的完全可移植性的時(shí)候。正如我們所看到的,有時(shí)候編程式的事務(wù)掛起和恢復(fù)可能存在一些問題。雖然Spring知道如何繞過這些問題,至少是對(duì)于上面所描述的問題,即,在Welogic中,在掛起之前將事務(wù)標(biāo)記為回滾。在這種情況下,可以在配置JtaTransactionManager時(shí)把a(bǔ)utodetectTransactionManager屬性設(shè)定為false。如果這么做了,那么任何使用PROPAGATION_REQUIRES_NEW或PROPAGATION_NOT_SUPPORTED事務(wù)屬性的嘗試都會(huì)拋出TransactionSuspensionNotSupportedException而失敗。但PROPAGATIO-REQUIRED、PROPAGATION-SUPPORTS、PROPAGATION-MANDATORY以及PROPAGATION-NEVER應(yīng)該會(huì)正常運(yùn)行。這對(duì)應(yīng)于JTA Usertransaction所提供的功能,而且在任一個(gè)兼容J2EE的容器中都起作用。

            以下是Spring應(yīng)用程序上下文中的事務(wù)管理器定義,其中禁用了TransactionManager自動(dòng)檢測(cè):

          <bean id="transactionManager" class=
          "org.springframework.transaction.jta.JtaTransactionManager">
          <property name="userTransactionName">
          <value>javax.transaction.UserTransaction</value>
          </property>
          <property name="autodetectTransactionManager">
          <value>false</value>
          </property>
          </bean>

          結(jié)束語

            J2EE規(guī)范不要求對(duì)JIA TransactionManager接口的支持。但由于J2EE使用JTA作為它的底層事務(wù)基礎(chǔ)架構(gòu),所以幾乎所有的J2EE服務(wù)器都把它公開為J2EE的擴(kuò)展。存在一些已知的兼容性問題,而在某些情況下,可以用特定于容器的代碼來繞過這些問題。但是,如果需要實(shí)現(xiàn)編程式事務(wù)掛起,則J2EE中的TransactionManager是一個(gè)強(qiáng)大的特性。只需首先在所選擇的J2EE服務(wù)器中檢測(cè)一下它是否可用就可以了。

          posted on 2008-11-26 19:28 大鳥 閱讀(445) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 额敏县| 搜索| 潜江市| 汉源县| 望谟县| 南岸区| 莱芜市| 凤台县| 上饶县| 肃北| 静乐县| 新泰市| 方正县| 岳阳市| 洛阳市| 隆德县| 东台市| 同心县| 嘉禾县| 黑山县| 河北区| 青海省| 文水县| 萨嘎县| 鄂州市| 江安县| 革吉县| 达州市| 灯塔市| 成都市| 鄄城县| 温州市| 彭阳县| 乌鲁木齐市| 甘孜县| 临漳县| 界首市| 大姚县| 上虞市| 浦江县| 崇仁县|