2009-10-17 88 views
11

我不停地從許多開發人員那裏得到這個「建議」。根據我的經驗,我發現EJBExceptions非常適合從bean實例的角度來看「世界末日」(比如當某些事情錯誤時,bean實例無法自行恢復)。如果一個實例可以恢復,我認爲最好拋出一個應用程序異常。爲什麼拋出一個EJBException是一個「推薦」的做法?

這裏是我遇到了一遍又一遍的模式:

 
private SomeResource resource; 
ejbCreate: 
    resource = allocateResource(...); 

omMessage: 
    try { 
    ... 
    } catch (JMSException e) { 
     throw new EJBException(e); 
    } 

ejbRemove: 
    freeResource(resource); 

恕我直言,這是導致資源泄漏一個反模式。

編輯:具體來說,EJB規範中說,如果一個bean從業務方法拋出運行時異常(和EJBException的是運行時異常),那麼這個bean是不調用的ejbRemove它丟棄。

這是否是拋出EJBException的相關示例? 應該拋出EJBException的相關情況是什麼?

+0

@vinny_g:我從您的評論我的(現已刪除)「答案」補充解釋。 – 2009-10-17 07:45:39

回答

7

EJBException投擲由EJB規範(14.2.2在EJB 3)在將EJB 不能從異常它遇到恢復情況下,建議。該規範還指出,EJB可以合理地允許(取消選中)系統異常傳播到容器。

我同意你對規範的閱讀,在這種情況下,生命週期回調方法不會被容器調用,因此你擔心任何資源整理通常會發生在ejbRemove()回調中不會發生所以存在資源泄漏的危險。

我的經驗是,由於缺乏防禦性編碼,出現了很多棘手的問題。 「情況X不可能出現在一個性能良好的系統中,如果它發生了,那麼整個系統就會被破壞,所以我不會爲這種可能性編碼。」然後,我們得到一些「有趣」的恆星和操作員錯誤對齊,並且「不可能發生」連續發生幾次,並且意外的副作用發生,導致真正難以診斷問題。

因此,我會說:

  1. 盡一切所能離開Bean實例的狀態下的業務方法的下一次調用可能是能夠工作。這可能意味着捕獲異常並關閉錯誤的資源。在這種情況下,您可能會選擇告訴來電者,「對不起,請求不起作用,但也許如果您稍後再試......」我通過拋出TransientException檢查異常來做到這一點。
  2. 如果您在ejbRemove中沒有重要的內務管理,那麼您可以允許SystemExceptions傳播 - 但我不確定這是否友好。你依靠一個庫,它會拋出一個NullPointerException。實際上是更強大的趕上並重新拋出TransientException
  3. 如果你確實有重要的家務管理,那麼我認爲你確實需要捕獲所有異常,並且至少嘗試清理。然後,您可能會選擇重新拋出EJBException或系統異常,以便實例被銷燬,但至少您已嘗試執行內務管理。
0

是否泄漏資源取決於如何管理這些資源。被丟棄的bean獲得垃圾收集,放棄其對資源的引用,當沒有更多引用指向它時,該資源依次獲取垃圾回收。如果資源也保存在具有根路徑的集合中,則該資源將泄漏,除非該容器具有可以檢測閒置資源並回收它的池管理器。

我同意你的看法,即bean應該自己處理任何異常,並讓調用者知道結果。對我來說,你描述的情況中的反模式是使用異常來傳遞對象狀態。異常應該是異常,不能用作返回值。

2

容器仍然可以提交即使EJB方法已經拋出應用程序異常當前事務。如果你的EJB方法可以拋出一個應用程序異常,那麼你應該考慮使用EJBContext.setRollbackOnly()這樣的:

public void method() throws ApplicationException { 
    try { 
    ... 
    } catch (ApplicationException e) { 
     _context.setRollbackOnly(); 
     throw e; 
    } 
} 

拋出EJBException異常或系統(未經檢查的)異常意味着容器將自動回滾事務。請參閱:http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html

如果您的系統的EJB不會定期捕獲和處理應用程序異常,那麼拋出它們的代碼可能會導致部分完成的操作提交其更改。

這可能導致難以發現的錯誤,因爲與CMP EJB方法的「用戶神話」是,它映射到一個事務,這是原子。部分完整的業務邏輯原子性地致力於數據庫。這在實踐中發生時非常混亂。喬爾關於漏泄抽象的文章:http://www.joelonsoftware.com/articles/LeakyAbstractions.html解釋了原因。

如果您的系統不處理應用程序異常的EJB正確的合乎邏輯的答案是修復他們,讓他們做。在問題得到解決之前,您的團隊可能有理由不想從EJB引發應用程序異常。

相關問題