2012-05-10 1 views
22

Все ExceptionHandlerFactory примеров я сталкивался до сих пор перенаправить пользователя на viewExpired.jsf странице в том случае, если ViewExpiredException ловится:Зачем использовать JSF ExceptionHandlerFactory вместо <error-page> перенаправление?

public class ViewExpiredExceptionExceptionHandler extends ExceptionHandlerWrapper { 
    private ExceptionHandler wrapped; 

    public ViewExpiredExceptionExceptionHandler(ExceptionHandler wrapped) { 
     this.wrapped = wrapped; 
    } 

    @Override 
    public ExceptionHandler getWrapped() { 
     return this.wrapped; 
    } 

    @Override 
    public void handle() throws FacesException { 
     for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) { 
      ExceptionQueuedEvent event = i.next(); 
      ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); 

      Throwable t = context.getException(); 
      if (t instanceof ViewExpiredException) { 
       ViewExpiredException vee = (ViewExpiredException) t; 
       FacesContext facesContext = FacesContext.getCurrentInstance(); 
       Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap(); 
       NavigationHandler navigationHandler = facesContext.getApplication().getNavigationHandler(); 
       try { 
        // Push some useful stuff to the request scope for use in the page 
        requestMap.put("currentViewId", vee.getViewId()); 
        navigationHandler.handleNavigation(facesContext, null, "/viewExpired"); 
        facesContext.renderResponse(); 
       } finally { 
        i.remove(); 
       } 
      } 
     } 

     // At this point, the queue will not contain any ViewExpiredEvents. Therefore, let the parent handle them. 
     getWrapped().handle(); 
    } 
} 

Мне кажется, что следующий простой web.xml конфигурации принципиально то же и намного проще:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/viewExpired.jsf</location> 
</error-page> 

Возникает вопрос - почему бы один использовать ExceptionHandlerFactory?

+0

Является ли код выше вашего? если нет, можете ли вы кредитовать источник? – Mindwin

ответ

23

Конкретный пример не только одна полезная вещь: она сохраняет вид ID в качестве атрибута запроса, так что вы можете использовать, например,

<h:link value="Go back to previous page" outcome="#{currentViewId}" /> 

Но это не чрезвычайно полезно в качестве исходного запроса URI уже доступен по атрибуту запроса по умолчанию <error-page>javax.servlet.error.request_uri.

<h:outputLink value="#{requestScope['javax.servlet.error.request_uri']}">Go back to previous page</h:outputLink> 

Однако одна вещь, что обычай ExceptionHandler действительно полезно в том, что она позволяет вам иметь дело с исключениями во время AJAX-запросы. По умолчанию у них нет единственной формы полезной обратной связи на стороне клиента. Только в Mojarra с этапом проекта, установленным в «Development», вы увидите сообщение с предупреждением о появлении JavaScript с сообщением об исключении. Но все. На этапе «Производство» нет единой формы обратной связи. С помощью настраиваемого ExceptionHandler вы сможете разобрать web.xml, чтобы найти местоположение страницы ошибки, создать с ним новый UIViewRoot и заставить JSF установить рендеринг ajax на @all.

Так, в основном:

String errorPageLocation = "/WEB-INF/errorpages/500.xhtml"; 
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation)); 
context.getPartialViewContext().setRenderAll(true); 
context.renderResponse(); 

Смотрите также этот родственный вопрос: What is the correct way to deal with JSF 2.0 exceptions for AJAXified components? и этот блог: Full Ajax Exception Handler.

+0

Может ли OmniFaces 'org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory' использоваться вместе с обработкой исключений, создав« ExceptionHandlerFactory »таким образом, чтобы переадресовать на глобальные страницы ошибок, если исключения брошенные, которые не должны быть обернуты этой фабрикой? Документация требует только одного обработчика исключений для каждого приложения ». * В каждом веб-приложении, использующем JavaServer Faces, должен быть один экземпляр ExceptionHandlerFactory. Этот экземпляр можно переносить переносимым способом, вызывая. *« Это хорошо работает для пересылки к глобальной странице ошибок, кстати. – Tiny

+0

@ Tiny: вы можете продлить его. См. Также javadoc. Переопределить 'shouldHandleExceptionRootCause()' для возврата 'false' (и добавить это фатальное сообщение). – BalusC

3

Это зависит от того, что вы хотите сделать, когда будете получать ViewExpiredException.

Если вы просто хотите отобразить страницу пользовательской ошибки, вы можете сделать это, как вы сказали.

Этот post показывает вам, как программно перехватывать ViewExpiredException и делать с ним что-то хорошее.

+1

ссылка не работает, добавьте рабочую ссылку, – aName