¿Por qué usar una herramienta JSF ExceptionHandlerFactory en lugar de una redirección de<error-page>?
templates jsf primefaces (2)
Todos los ejemplos de ExceptionHandlerFactory
que he encontrado hasta ahora redirigen a un usuario a una página viewExpired.jsf
en el caso de que se ViewExpiredException
una ViewExpiredException
:
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();
}
}
Me parece que la siguiente configuración simple de web.xml
es básicamente la misma y mucho más simple:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/viewExpired.jsf</location>
</error-page>
Esto genera la pregunta: ¿por qué uno usaría una ExceptionHandlerFactory
?
Depende de qué desea hacer cuando recibe ViewExpiredException
.
Si solo desea mostrar una página de error de usuario, puede hacerlo como dijo.
Esta post muestra cómo interceptar mediante programación la ViewExpiredException
y hacer algo bueno con ella.
El ejemplo particular hace solo una cosa útil: guarda la ID de la vista como un atributo de solicitud para que pueda usar, por ejemplo,
<h:link value="Go back to previous page" outcome="#{currentViewId}" />
Pero esto no es tremendamente útil ya que el URI de solicitud sin procesar ya está disponible por el atributo de solicitud predeterminado de <error-page>
javax.servlet.error.request_uri
.
<h:outputLink value="#{requestScope[''javax.servlet.error.request_uri'']}">Go back to previous page</h:outputLink>
Sin embargo, una cosa para la que es realmente útil un ExceptionHandler
personalizado es que le permite tratar con excepciones durante las solicitudes ajax . Por defecto, no tienen ninguna forma única de comentarios útiles en el lado del cliente. Solo en Mojarra, con la etapa del proyecto configurada en "Desarrollo", verá un mensaje de alerta de JavaScript con el mensaje de excepción. Pero eso es todo. No hay una forma única de retroalimentación en la etapa de "Producción". Con un ExceptionHandler
personalizado, usted podría analizar el web.xml
para encontrar las ubicaciones de la página de error, crear una nueva UIViewRoot
con ella y forzar a JSF a establecer una representación de @all
en @all
.
Entonces, básicamente :
String errorPageLocation = "/WEB-INF/errorpages/500.xhtml";
context.setViewRoot(context.getApplication().getViewHandler().createView(context, errorPageLocation));
context.getPartialViewContext().setRenderAll(true);
context.renderResponse();
Consulte también esta pregunta relacionada: ¿Cuál es la forma correcta de lidiar con las excepciones JSF 2.0 para componentes AJAXified? y este blog: Full Ajax Exception Handler .