|
|
要在Bean上使用CMT,基本上,就是在方法上使用@TransactionAttribute設定交易屬性,例如:
package onlyfun.caterpillar;
package onlyfun.caterpillar; 這個Stateless Session Bean示範了兩個方法,皆設定交易屬性為REQUIRED,Bean預設的交易為CMT,您無需特別設定,若要明確設定,則使用@TRansactionManagement標註如下: @Stateless
@TransactionManagement(TransactionManagementType.CONTAINER) public class HelloBeanImpl implements HelloBean { .... } 根據設定,在呼叫方法時,會啟始一個交易,若無法完成交易,則會撤回操作,程式中的demoTransaction2()則示 範了,如何透過SessionContext的setRollbackOnly()方法設定撤回標記,設定了撤回標記,方法呼叫結束後,容器將撤回交易,您可以使用getRollbackOnly()方法來判斷交易撤回是否被設定,您也可以丟出javax.transaction.SystemException,由容器退回交易。 通常,您會在方法呼叫中捕捉到例外時,呼叫setRollbackOnly()方法設定撤回標記,例如: ...
try { ... } catch(SomeException ex) { context.setRollbackOnly(); } catch(OtherException ex) { context.setRollbackOnly(); } .... 您也可以在自訂例外類別時,使用@ApplicationException(rollback=true)設定,當丟出例外時,設定撤回標記,這在之後說明例外處理時還會介紹。 setRollbackOnly()方法可以在REQUIRED、REQUIRED_NEW與MANDATORY設定時呼叫,否則會丟出IllegalStateException。 上面這個範例,搭配 TimerService 與 Timer 回呼 中的Message-Driven Bean,若呼叫demoTransaction1(),則Message-Driven Bean會收到訊息加以處理,若呼叫demoTransaction2(),則訊息不會傳給Message-Driven Bean。 在訊息服務中使用交易時常見的誤會是:「認為交易包括的產生者的訊息傳送、消耗者的接收、回覆。」事實上,交易是無法從產生者傳遞至接收者,訊息服務中若要使用交易,是訊息產生者傳送訊息至MOM是一個交易,而訊息消耗者從MOM接收訊息是另一個交易。 您無法傳遞交易環境給Message-Driven Bean的onMessage()方法,若您要在onMessage()上使用CMT,則可以設定的屬性是REQUIRED、NOT_SUPPORTED,Message-Driven Bean消耗訊息回覆確認之後才算完成交易,若交易失敗,則訊息不會被消耗,訊息仍被放在佇列上,回復至交易之前的狀態。 在Timer服務時,Timeout的回呼方法若要使用交易,可使用REQUIRED或REQUIRED_NEW,若交易被撤回,則Timeout方法會被重新呼叫。 容器會負責撤回資源系統的變更(例如資料庫上的欄位變更、MOM上的訊息),但不負責撤回Stateful Session Bean的成員變數,所以必須考慮到,當交易作用於Stateful Session Bean上,在交易撤回時,Stateful Session Bean的成員變數是否需回復至交易開始前的狀態,若這是必要的,則您可以實作SessionSynchronization介面: public interface SessionSynchronization {
void afterBegin() throws EJBException, RemoteException; void beforeCompletion() throws EJBException, RemoteException; void afterCompletion(boolean committed)throws EJBException,RemoteException; } afterBegin()會在交易開始之後呼叫,beforeCompletion()會在交易完成或撤回前呼叫, afterCompletion()會在交易完成或撤回後呼叫,若其中committed為true,表示交易成功,false表示交易撤回,這是您可以 回復Stateful Session Bean成員變數的地方。 |