2010-11-10 31 views
2

首先,我的框架是帶有JSF,託管bean,EJB和JPA的Java EE 6。我編寫了一個簡單的程序來查詢數據庫中的信息。所以當我點擊一個按鈕時,它觸發了一個託管bean的事件,其中一個事件監聽器方法將訪問EJB方法。 EJB方法將對實體進行簡單的select查詢。如果數據庫關閉之前或期間的時間我select,我得到一個異常JavaEE6:如何在數據庫關閉時保護Web應用程序

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.DatabaseException 

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure 

The last packet successfully received from the server was 51,460 milliseconds ago. The last packet sent successfully to the server was 0 milliseconds ago. 
Error Code: 0 

如何維護從此異常了嗎?這裏肯定是try, catch,但不知道放在哪裏。當我做em.createNamedQueryem.remove時,我試着去捕捉com.mysql.jdbc.exceptions.jdbc4.CommunicationsException,但是我得到一個錯誤說:Exception com.mysql.jdbc.exceptions.jdbc4.CommunicationsException is never thrown in body of corresponding try statement

下面是我的代碼,我會在哪裏捕捉異常?

這是我EJB

@Stateless 
@LocalBean 
public class DocumentSBean { 
    @PersistenceContext 
    private EntityManager em; 

    public List<User> listUser(){ 
     Query query = em.createNamedQuery("User.listUser"); 
     query.returnResultList(); 
    } 
} 

這是我ManagedBean

@ManagedBean(name="document") 
@ViewScoped 
public class DisplayListController implements Serializable {    

    @EJB 
    DocumentSBean sBean; 

    List<User> users = null; 

    public void foo(){ 
     users = sBean.listUser(); 
    } 
} 

編輯

我嘗試下面列出兩種方式,但仍返回狀態200,而不是500的fireb UG

<p:commandButton update="myform" actionListener="#{document.setDisplayFacility}" rendered="#{utility.admin}" value="Facilities"/> 

OR

<p:commandButton update="myform" actionListener="#{document.setDisplayFacility}" rendered="#{utility.admin}" value="Facilities"> 
     <p:ajax actionListener="#{document.setDisplayFacility}" update="myform" event="click"/> 
</p:commandButton> 

這裏是setDisplayFacility()

public void setDisplayFacility(){ 
    facilities = sBean.getAllFacilities(); //sBean is EJB 
    displayFacility = true; 
} 

回答

6

如何避免此異常?絕對是一個嘗試,趕上這裏,但不知道把它放在哪裏。

只有在那裏你可以合理的方式處理異常。


我試圖抓住com.mysql.jdbc.exceptions.jdbc4.CommunicationsException,但我得到了一個錯誤說:異常com.mysql.jdbc.exceptions.jdbc4.CommunicationsException永遠不會在身體扔對應的try語句。

CommunicationsException是在這種情況下DatabaseException一個嵌套異常。的EclipseLink是蓋已經捕捉CommunicationsException並與CommunicationsException重新拋出它作爲DatabaseException的根本原因下。喜歡的東西:

try { 
    // Execute query. 
} catch (Exception e) { 
    throw new DatabaseException("Internal Exception: " + e, e); 
} 

從理論上講,可以如下只處理:

try { 
    // Let EclipseLink execute query. 
} catch (DatabaseException e) { 
    if (e.getCause() instanceof CommunicationsException) { 
     // Handle. 
    } 
} 

然而這是醜陋的,在這種特定情況下不推薦使用。


下面是我的代碼,在那裏我會捕獲異常?

取決於您想如何處理的例外。如果你想在通用錯誤頁面中顯示它,那麼你不應該自己動手,只是放手吧。然後servletcontainer將自己捕獲並處理它。它會在web.xml中查找最匹配的<error-page>並顯示它。

<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/generic-error.xhtml</location> 
</error-page> 

這人會顯示爲/generic-error.xhtml所有java.lang.Exception

如果你想在一個特定錯誤頁面來顯示它,那麼你需要聲明<exception-type>更具體的符合實際的異常類型。例如。:

<error-page> 
    <exception-type>org.eclipse.persistence.exceptions.DatabaseException</exception-type> 
    <location>/database-error.xhtml</location> 
</error-page> 

然而,儘管在你的問題沒有明確規定,我知道根據您使用JSF與PrimeFaces你的問題的歷史。你需要記住PrimeFaces將會在最初的請求由ajax進行時顯示錯誤頁面而不是。相反,它的ajax視圖處理程序本身已經捕捉到異常,它將委託給視圖中的<p:ajaxStatus>組件。嘗試將ajax="false"添加到PrimeFaces命令組件中,您將最終看到顯示了servlet容器的默認錯誤頁面(或者如果找到匹配的web.xml中的任何一個,那麼您的任何一個)。

如果您想在PrimeFaces收到ajax錯誤時顯示一些通用JSF UI,請使用<p:ajaxStatus>error構面。例如。

<p:ajaxStatus> 
    <f:facet name="start"><h:graphicImage value="images/ajax-loader.gif" /></f:facet> 
    <f:facet name="success"><h:outputText value="" /></f:facet> 
    <f:facet name="error"> 
     <h:panelGroup layout="block" styleClass="ui-message-error ui-widget ui-corner-all"> 
      <h:outputText value="An error has occurred!" /><br /> 
      <h:outputLink value="#" onclick="window.location.reload(true)"><h:outputText value="Please reload page and retry" /></h:outputLink><br /> 
      <h:outputLink value="mailto:[email protected]?subject=Ajax%20Error"><h:outputText value="If in vain, please contact support" /></h:outputLink> 
     </h:panelGroup> 
    </f:facet> 
</p:ajaxStatus> 

(有但是在PrimeFaces一些bug 2.2 RC1這會導致顯示錯誤方面失敗,它工作正常在PrimeFaces 2.1)

+0

這是一篇很棒的文章。謝謝。當我捕獲java.lang.Exception時,它會工作,但是當我捕獲org.eclipse.persistence.exceptions.DatabaseException時,它不起作用。也許它再次嵌套到更一般的異常。我有一個問題與主題非常相關。我關閉了mysql服務器來測試它,但是當我把它重新打開時,事情不會恢復正常。意思是,當我點擊從數據庫查詢的組件時,它仍然給我錯誤頁面。我必須重新啓動glassfish和mysql服務器才能使其正常工作。這是正常的,BalusC? – 2010-11-17 17:57:29

+0

您需要捕捉跟蹤中最上面的異常,而不是跟蹤中的嵌套(「引起的」)部分。至於重新連接失敗:您需要在管理控制檯或'sun-resources.xml'文件中配置Glassfish'jdbc-connection-pool'重試次數和時間間隔(取決於您定義池的位置)。您可以在這裏找到所有配置選項:http://docs.sun.com/app/docs/doc/820-4507/6nfvg4rbl?l=en&a=view Ctrl + F「重試」。 – BalusC 2010-11-17 18:15:34

+0

謝謝。當我說catch時,我的意思是讓ServletContainer在web.xml中捕獲它。 'java.lang.Exception'很好,但是'org.eclipse.persistence.exceptions.DatabaseException'失敗了。對於ajax錯誤捕獲。我遇到了一個有趣的問題。當數據庫關閉並且發出ajax請求時,我的ajax-loader.gif開始旋轉,但它旋轉得像永遠一樣,但只要刷新頁面,就會顯示錯誤。我會期待ajax-loader.gif一段時間,然後出現錯誤。任何想法,爲什麼,BalusC? – 2010-11-17 19:06:20

2

在我看來,至少,一個數據庫變得不可用,是需要處理,通常儘快嚴重錯誤。防範此類情況的一般方法是通過數據庫聚類實施高可用性和故障轉移機制。

如果你沒有這個選項,但是你也不希望用戶看到一個很大的異常,你可能會嘗試做的是在發生這個特定的錯誤時將他路由到一個用戶友好的頁面。要做到這一點,把你的web.xml中進行以下(假設你的FacesServlet的映射爲* .faces):

<error-page> 
    <exception-type>com.mysql.jdbc.exceptions.jdbc4.CommunicationsException</exception-type> 
    <location>/errors/error.faces</location> 
</error-page> 

然後,在error.xhtml頁面一般的方法是把一些人性化並很大程度上表示歉意,表示管理員對用戶的不便感到抱歉...

無論如何,通過捕捉異常並且不對他們採取行動來處理這種情況,無論是通過重新投擲還是與他們打交道catch塊 - 如果可能的話,通常認爲在嚴重錯誤時可能會不被注意到是一種不好的做法。

對於您的「從未拋出相應的嘗試聲明」的問題,您可能需要檢查this文章。

乾杯!

+0

我不認爲它的工作。我把你的代碼放在我的'web.xml'中。加載我的頁面,關閉Mysql Server,發出請求,但沒有發現異常。換句話說,它沒有將我重定向到我指定的錯誤頁面。 – 2010-11-11 23:03:35

+0

如果將CommunicationsException放入異常類型元素中,這聽起來很正常。這是因爲,當你的異常到達web層時,很可能會被打包,所以它不會被規則過濾(異常類型將不同)。我建議檢查日誌以查看拋出的最後一個異常,或者嘗試使用超類(即java.lang.Exception)。 – 2010-11-12 08:17:35

+0

我是否仍然在我的web.xml或我的代碼中發現異常。我上面寫了一些代碼來演示我的設計。你可以看看他們嗎? – 2010-11-12 16:19:46

2

的CommunicationsException被包裹在一個的EclipseLink DatabaseException,這是一個運行時異常。如果您使用的是JPA或JTA,那麼這可能也會被封裝在PersistenceException或TransactionRolledbackException中。因此,嘗試捕獲其中的一個,或者最糟糕的情況是RuntimeException。 CommunicationsException將由鏈引起。

的EclipseLink會自動嘗試重新連接死連接,但如果你的數據庫是下跌,這將失敗(您可能會看到錯誤記錄的3倍),所以你需要一個錯誤報告給用戶。

+0

我已更新我的代碼,請看看他們,因爲我對你有更多問題。從上面的代碼中,我會在哪裏捕獲「PersistenceException」或「TransactionRolledBackException」。謝謝 – 2010-11-11 22:53:51

相關問題