http://zh.objectweb.org/JOnAS/gb/PG_Transaction.html
事務處理行為
面向的讀者和內容提要
本文面向的讀者主要是企業bean的提供者,例如負責在服務器端開發組件的程序員。本文解釋了如何定義EJB應用程序的事務處理.
以下是本文的內容提要:
-
面向的讀者和本文的內容提要
-
聲明性的事務管理
-
BEAN管理的事務
-
分布事務管理
聲明性的事務管理
在容器管理事務這種事務管理方式的情況下,企業BEAN的事務處理行為是在配置時被定義的,具體體現在標準部署描述符文件中的集成描述符元素( assembly-descriptor element)部分中. 在配置時我們可以為同一BEAN中所有的方法(methods)同時定義一個共通的事務處理行為,也可以為每個方法( methods )分別定義不同的事務處理行為 . 我們通過指定事務屬性來配置事務的行為.事務的屬性有如下幾種:
-
NotSupported:如果該方法是在一個事務上下文中被調用,那么該方法執行過程中,該事務將被掛起.
-
Required:如果該方法是在一個事務上下文中被調用,該方法在該事務上下文中執行.否則(該方法不在一個事務上下文中被調用),在該方法執行前,容器將自動生成一個新的事務,隨后該方法在新的事務上下文中執行,并且在該方法結束時,容器將自動提交這個被自動生成新的事務.
-
RequiresNew:該方法總是要求在一個新的事務上下文中執行.在該方法執行前,容器將自動生成一個新的事務,并且在該方法結束返回時,容器將自動提交這個被自動生成的新事務.如果該方法是在一個事務上下文中被調用,那么新的事務開始時,該事務將被掛起,并且新事務結束后,該事務將重啟.
-
Mandatory:該方法總是要求在一個事務上下文中被調用.否則,容器將拋出 TransactionRequired 例外.
-
Supports:該方法如果在一個事務上下文中被調用,那么該方法將在該事務上下文中執行.如果該方法的調用者不處在事務上下文中,那么該方法也就不在任何事務上下文中執行.
-
Never:該方法要求該方法的調用者不能處在事務上下文中.否則,容器將拋出 RemoteException 例外.
表格說明如下:
事務屬性 |
調用者事務 |
企業BEAN方法(METHOD)的事務 |
NotSupported |
-
T1 |
-
- |
Required |
-
T1 |
T2
T1 |
RequiresNew |
-
T1 |
T2
T2 |
Mandatory |
-
T1 |
錯誤
T1 |
Supports |
-
T1 |
-
T1 |
Nervere |
-
T1 |
-
錯誤 |
根據EJB規范書要求,事務屬性在部署描述符的集成描述符(assembly - descriptor)中設定,例如:
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>AccountImpl</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Supports</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>AccountImpl</ejb-name>
<method-name>getBalance</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
<method>
<ejb-name>AccountImpl</ejb-name>
<method-name>setBalance</method-name>
</method>
<trans-attribute>Mandatory</trans-attribute>
</container-transaction>
</assembly-descriptor>
在本例中,對于AccountImpl bean的所有沒有用container-transaction元素作明確指定的方法, 使用缺省事務屬性Supports(匹配符*指定缺省事務屬性,適用于該BEAN所有方法( method )).并且明確指定getBalance 和 setBalance 方法的事務屬性分別是 Required 和 Mandatory (通過給定特定的 方法method名).
BEAN管理的事務
對于自己管理自己事務的BEAN,必須在標準部署描述符中設定其對應的 transaction-type元素.例如下:
<transaction-type>Bean</transaction-type>
對于BEAN自己管理的事務,BEAN程序員應該使用javax.transaction.UserTransaction來界定事務邊界.該接口(interface)javax.transaction.UserTransaction由EJB服務器在服務器內部一個對象上實現.可以通過調用EJBContext.getUserTransaction()來獲得該接口(這兒的EJBContext根據bean的種類session BEAN或entity bean的不同而不同, 在session bean 中 EJBContext指 SessionContext,而在 entity bean EJBContext指 EntityContext ).下面的就是一個例子,在 session bean的"doTxJob" 方法中界定事務邊界; UserTransaction 對象(接口)通過 sessionContext對象獲取.其中sessionContext對象在BEAN初始化方法 setSessionContext(BEAN初始化時自動被EJBserver調用)中作為參數傳遞過來.(這意味著BEAN程序員應該在setSessionContext中將該 sessionContext對象保存在BEAN的變量中).(參考 example of the session bean).
public void doTxJob() throws RemoteException {
UserTransaction ut = sessionContext.getUserTransaction();
ut.begin();
... // transactional operations
ut.commit();
}
另一個獲得接口 UserTransaction 的方法是用 JNDI ,即在初始化上下文中通過使用 java:comp/UserTransaction名字來獲取.
分布事務管理
正如前面部分所講,一個應用程序的事務行為可以通過聲明的方式來定義,也可以由BEAN或BEAN的調用者分別,或BEAN和BEAN的調用者協助,用編程的方式在代碼中指定(界定事務邊界).不管在哪中情況下,事務的分布特性這方面,無論對BEAN提供者(bean provider) 還是對應用集成商(application assembler.)來說都是完全透明的.這意味著一個事務可能有多個在不同的EJB服務器上的BEAN參與,而平臺應該自己從全局角度管理分布事務.平臺在多個不同的服務器間使用兩相提交協議(two phase commit )來管理分布事務,從而BEAN程序員不用考慮事務的分布特性這方面.
在 been已經開發完成,并且應用集成結束后,部署人員 (deployer)或管理員( administrator )也可以將不同的BEAN配置分布在同一或多個不同的機器上的同一或多個不同的EJB服務器里.
這種配置過程可以在不涉及到代碼的變動或部署描述符的修改的情況下完成.The distributed configuration is specified at launch time: in the environment properties of an EJB server, you may specify分布事務的配置是在EJB服務器啟動時進行進行:所以分布事務的配置在EJB服務器的環境配置文件中設定.設定如下:
這須通過設定環境配置文件 jonas.properties 里的jonas.service.ejb.descriptors 和 jonas.service.jtm.remote項來完成.前一個列出該EJB服務器中管理的所有企業BEAN(通過指定部署描述符文件名或ejb-jar文件名),后一個設定Java Transaction Monitor(JTM)啟動模式:
-
if set to false, the JTM is local, i.e. it will run into the same JVM as the EJB Server. 如果設為false,那么JTM使用本地方式,即該EJB服務器的JVM中同時啟動一個JTM
例如:
jonas.service.ejb.descriptors Bean1.xml, Bean2.xml
jonas.service.jtm.remote false
JTM可運行在單獨的JVM中,而不必一定運行于某個EJB服務器內.在這種情況下,可以如下命令文單獨啟動JTM:
TMServer
通過這種靈活的配置方式,就可根據資源(CPU或數據源)的具體情況而采用不同的配置,從而得到最佳的系統性能.
如下例圖是針對三個企業BEAN而采用四種不同配置,

-
第1種情況: 三個企業BEAN B1, B2 and B3 分布在同一個EJB服務器內,EJB服務器內同時啟動了一個Java Transaction Monitor.
-
第2種情況: 三個企業BEAN分別分布在不同的EJB服務器內,其中有只有一個EJB服務器內啟動了一個Java Transaction Monitor,用于管理全局分布事務.
-
第3種情況:三個企業BEAN分別分布在不同的EJB服務器內,JTM運行在每個單獨的JVM中.
-
第4種情況:三個企業BEAN分別分布在不同的EJB服務器內. 每個EJB服務器內啟動了一個Java Transaction Monitor. 其中一個作為主監視器( master monitor),另外兩個為附屬監視器( slaves. )
這些不同的配置情況可通過配置EJB 服務器對應的環境屬性配置文件,再啟動 EJB 服務器來實現,有些情況下也要啟動JTM(第3種情況).基本原則是應該根據資源的位置和負載均衡來作出合適的選擇.以下幾點說明,以供參考:
-
如果企業BEAN要求運行于同一臺機器,并且要求相同的EJB服務器配置,第1種情況應該是最佳選擇.
-
如果企業BEAN要求運行于不同機器,那么第4種情況應該是最佳選擇.因為在這種情況下,本地方式的事務管理更加合適.
-
如果企業BEAN要求運行于同一臺機器,而要求不同的EJB服務器配置,第2種情況應該是好的選擇.