2012-07-31 58 views
2

今天我在EJB中發現了一些意外的行爲。我有默認交易屬性(REQUIRED)和事務屬性設置爲REQUIRES_NEW的SLSB的MDB。我的MDB調用SLSB並捕獲SLSB可能拋出的任何異常。當SLSB中發生某些真正的不良事件時,會拋出RuntimeException的某個子類。然後,爲SLSB創建的新事務標記爲回滾。從我的角度來看,這是一個正確的行爲。然後,MDB捕獲此異常並執行一些操作(例如,寫一條消息以記錄日誌)並重新拋出。但MDB交易不知何故也成爲回滾的標誌,這對我來說似乎很陌生。這種行爲是否正確?EJB中的嵌套事務行爲

爲了更加精確,我可以寫類似於實際的一個了一些代碼,產生這種行爲:

@MessageDriven 
public class A{ 

@EJB 
private B b; 

@Overried 
public void onMessage(Message msg){ 
... 
try{ 
b.process(msg); 
} catch (Throwable t){ 
logger.error("Something gone wrong",t); 
} 
... 
} 

而且SLSB看起來是這樣的:

@EJB 
@Stateless 
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public class B{ 
public void process(Message msg){ 
... 
} 
} 

有問題的任務流程是這樣的:

  1. 消息驅動bean onMessage(Message)被調用。
  2. 消息驅動bean執行一些操作成功,然後調用B.process(Message)方法。
  3. 發生了B錯誤,RuntimeException被拋出。
  4. RuntimeException被封裝在EJBException中,並被消息驅動bean成功捕獲。
  5. 郵件驅動的豆onMessage(Message)方法被完全執行,但其交易標記爲回滾

有人可以解釋這種行爲嗎? 在此先感謝。

+0

您使用的是什麼appserver /版本?這個鏈接表明你的評估是正確的,因爲你的代碼應該工作:http://stackoverflow.com/questions/10817838/ejb-3-0-nested-transaction-requires-new。 – 2012-07-31 21:34:47

+0

你也可以嘗試將兩個bean的*最小*例子放在一起 - 首先要確認你是否看到預期的行爲,並且刪除了所有其他「東西」,然後給其他人一些東西去玩另一個平臺。儘管這裏沒有承諾。 – 2012-07-31 21:55:37

+0

我使用WebLogic 12c服務器。目前我無法提供任何可以組裝和部署的示例,但我會盡量在接下來的10-20小時內提供。也許我會在嘗試提供示例時發現問題。 :) – gkuzmin 2012-07-31 21:59:28

回答

0

找到了解決此問題的方法。實際上TransactionAttribute註釋被放在B bean的抽象超類上,並被忽略。 WebLogic服務器中的EJB運行時環境忽略B超類的註釋,並使用默認的REQUIRED屬性。如果您遇到同樣的問題,我可以推薦您閱讀EJB 3.1規範中的13.3.7.1(您可以下載它here)。

+1

來自EJB 3.1規範第13.3.7.1節的相關部分: – alexsmail 2013-04-22 12:13:56

1

正如@gkuzmin所述。

相關部分從部分13.3.7.1從EJB 3.1 specfication:

如果bean類具有超類,以下附加規則適用。

  • 上的超類S]指定的事務屬性適用於如果在S未指定一個類層次的事務屬性由S.定義的業務的方法,它相當於TransactionAttribute(REQUIRED)的上S.規範

  • 事務屬性可以對由S類中定義的業務子程序M被指定以覆寫方法M中的事務屬性的類S.明確地或隱含指定的值

  • 如果S類的方法M覆蓋由S的超類定義的業務方法,則M的事務屬性由上述規則確定,適用於S類。

注意大膽的部分。你所期望的不是S超類的商業方法。