2013-12-16 70 views
3

我希望框架捕獲每個未捕獲的異常並顯示適當的通知消息。Vaadin中的中央錯誤處理

所以我把我的UI定製ErrorHandler這樣的(由「Vaadin之書」的啓發:https://vaadin.com/book/-/page/application.errors.html):

public abstract class MyUI extends UI { 

    @Override 
    protected void init(final VaadinRequest request) { 
     setErrorHandler(new DefaultErrorHandler() { 
      @Override 
      public void error(final com.vaadin.server.ErrorEvent event) { 
       Throwable error = event.getThrowable(); 
       Notification.show(error.getLocalizedMessage(), Notification.Type.ERROR_MESSAGE); 
      } 
     }); 
    } 
} 

但是,當我從後臺加載惹的錯誤,也會不執行。相反,表單不完全顯示,當我重新加載頁面(F5)時,我得到一個異常視圖,就像我從Tomcat的一般異常處理程序中知道的那樣。

這是錯誤的,因爲我設置了ErrorHandler?有沒有更好的辦法?

我使用Glassfish的4和7 Vaadin

回答

5

我們還使用Glassfish的4和7 Vaadin你 可以編寫自己的自定義的ErrorHandler(它實現了接口com.vaadin.server.ErrorHandler),因爲我們做:

@Override 
public void error(ErrorEvent event) { 
    // Finds the original source of the error/exception 
    AbstractComponent component = DefaultErrorHandler.findAbstractComponent(event); 
    if (component != null) { 
     ErrorMessage errorMessage = getErrorMessageForException(event.getThrowable()); 
     if (errorMessage != null) { 
      component.setComponentError(errorMessage); 
      new Notification(null, errorMessage.getFormattedHtmlMessage(), Type.WARNING_MESSAGE, true).show(Page.getCurrent()); 
      return; 
     } 
    } 
    DefaultErrorHandler.doDefault(event); 
} 

方法getErrorMessageForException找出的主要原因這常常是有用的:

private static ErrorMessage getErrorMessageForException(Throwable t) { 

    PersistenceException persistenceException = getCauseOfType(t, PersistenceException.class); 
    if (persistenceException != null) { 
      return new UserError(persistenceException.getLocalizedMessage(), AbstractErrorMessage.ContentMode.TEXT, ErrorMessage.ErrorLevel.ERROR); 
    } 
    SQLException sqlException = getCauseOfType(t, SQLException.class); 
    if (sqlException != null) { 
     return new SQLErrorMessage(sqlException); 
    } 
    FieldGroup.CommitException commitException = getCauseOfType(t, FieldGroup.CommitException.class); 
    if (commitException != null) { 
     return new CommitErrorMessage(commitException); 
    } 
    EJBException eJBException = getCauseOfType(t, EJBException.class); 
    if (eJBException != null) { 
     return new UserError(eJBException.getLocalizedMessage(), AbstractErrorMessage.ContentMode.TEXT, ErrorMessage.ErrorLevel.ERROR); 
    } 
    ... 
} 

private static <T extends Throwable> T getCauseOfType(Throwable th, Class<T> type) { 
    while (th != null) { 
     if (type.isAssignableFrom(th.getClass())) { 
      return (T) th; 
     } else { 
      th = th.getCause(); 
     } 
    } 
    return null; 
} 

厚福這有助於你爲你找到一個好的解決方案。

編輯:關於問題和提示在哪裏設置的ErrorHandler:

import com.vaadin.annotations.Theme; 
import com.vaadin.cdi.CDIUI; 
import com.vaadin.ui.UI; 

@CDIUI 
@Theme("abc") 
public class CustomUI 
     extends UI { 
    ... 

    @Override 
    protected void init(VaadinRequest request) { 
     ... 
     // at main UI ... 
     UI.getCurrent().setErrorHandler(new CustomErrorHandler()); 

     // ... or on session level 
     VaadinSession.getCurrent().setErrorHandler(new CustomErrorHandler()); 
    } 

    ... 
} 
+0

我調試了一點,發現我的''不執行ErrorHandler'',但''DefaultErrorHandler''。你如何/在哪裏設置錯誤處理程序? – Andy

+0

我們在主UI的init(...)期間設置ErrorHandler:[我將編輯格式化代碼的主要答案]。 – Mayoares

+3

不幸的是,它無法在UI上設置ErrorHandler,而是發現我必須在Session-Level上設置它:''VaadinSession.getCurrent()。setErrorHandler(new MyCustomErrorHandler());''。 (如果您將此選項添加到您的答案中,我將接受它) – Andy