Estoy desarrollando una aplicación JSF 2.0 en Glassfish v3 y estoy tratando de manejar la ViewExpiredException. Pero haga lo que haga, siempre obtengo un informe de error de Glassfish en lugar de mi propia página de error.JSF: No se puede detectar ViewExpiredException
Para simular la aparición del VEE, inserté la siguiente función en mi bean de respaldo, que dispara el VEE. Estoy activando esta función desde mi página JSF a través de un commandLink. El Código:
@Named
public class PersonHome {
(...)
public void throwVEE() {
throw new ViewExpiredException();
}
}
Al principio lo intenté simplemente añadiendo una página de error, a mi web.xml:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/error.xhtml</location>
</error-page>
Pero esto no funciona, no estoy redirigido a error pero yo estoy mostró el ErrorPage Glassfish, que muestra un estado HTTP 500 página con el siguiente contenido:
description:The server encountered an internal error() that prevented it from fulfilling this request.
exception: javax.servlet.ServletException: javax.faces.application.ViewExpiredException
root cause: javax.faces.el.EvaluationException:javax.faces.application.ViewExpiredException
root cause:javax.faces.application.ViewExpiredException
siguiente que probé era escribir ExceptionHandlerFactory y una CustomExceptionHandler, como se des cibed en JavaServerFaces 2.0 - La referencia completa. Así que me inserta la siguiente etiqueta en faces-config.xml:
<factory>
<exception-handler-factory>
exceptions.ExceptionHandlerFactory
</exception-handler-factory>
</factory>
y ha añadido estas clases: La fábrica:
package exceptions;
import javax.faces.context.ExceptionHandler;
public class ExceptionHandlerFactory extends javax.faces.context.ExceptionHandlerFactory {
private javax.faces.context.ExceptionHandlerFactory parent;
public ExceptionHandlerFactory(javax.faces.context.ExceptionHandlerFactory parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getExceptionHandler() {
ExceptionHandler result = parent.getExceptionHandler();
result = new CustomExceptionHandler(result);
return result;
}
}
El manejador de excepción personalizada:
package exceptions;
import java.util.Iterator;
import javax.faces.FacesException;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
class CustomExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler parent;
public CustomExceptionHandler(ExceptionHandler parent) {
this.parent = parent;
}
@Override
public ExceptionHandler getWrapped() {
return this.parent;
}
@Override
public void handle() throws FacesException {
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
ExceptionQueuedEvent event = i.next();
System.out.println("Iterating over ExceptionQueuedEvents. Current:" + event.toString());
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
Throwable t = context.getException();
if (t instanceof ViewExpiredException) {
ViewExpiredException vee = (ViewExpiredException) t;
FacesContext fc = FacesContext.getCurrentInstance();
NavigationHandler nav =
fc.getApplication().getNavigationHandler();
try {
// Push some useful stuff to the flash scope for
// use in the page
fc.getExternalContext().getFlash().put("expiredViewId", vee.getViewId());
nav.handleNavigation(fc, null, "/login?faces-redirect=true");
fc.renderResponse();
} finally {
i.remove();
}
}
}
// At this point, the queue will not contain any ViewExpiredEvents.
// Therefore, let the parent handle them.
getWrapped().handle();
}
}
pero todavía NO se me redirige a mi página de error; recibo el mismo error de HTTP 500 que el anterior. ¿Qué estoy haciendo mal, qué podría faltar en mi implementación que la excepción no se maneja correctamente? Cualquier ayuda muy apreciada!
EDITAR
Ok, soy honesto. De hecho, mi código está escrito en Scala, pero esa es una historia larga. pensé que era un problema de Java todo el tiempo. El error REAL en este caso fue mi propia estupidez. En mi código (Scala), en CustomExceptionHandler, olvidé agregar la línea con "i.remove();" Entonces ViewExpiredException se mantuvo en UnhandledExceptionsQueue después de manejarlo, y se "borró". Y cuando se enciende, se convierte en una ServletException.
¡Realmente lo siento por confundirlos a los dos!
* "para que pueda lanzar una ViewExpiredException en CUALQUIER JSF-fase" *: de forma predeterminada, cuando se hace esto dentro de un grano como en su primera ejemplo, este será envuelto en una 'FacesException' y lo hará no terminará en la página de error esperado. – BalusC
Gracias. Tienes razón, eliminé la declaración any-jsf-phase de mi última edición. – ifischer
¿Su última publicación editada lo hace funcionar? Necesito establecer la misma redirección en el error ViewExpired también –