我正在 Glassfish v3 上开发一个 JSF 2.0 应用程序,并且我正在尝试处理 ViewExpiredException。但无论我做什么,我总是得到一个 Glassfish 错误报告,而不是我自己的错误页面。
为了模拟 VEE 的发生,我将以下函数插入到我的支持 bean 中,它会触发 VEE。我正在通过commandLink 从我的JSF 页面触发此功能。编码:
@Named
public class PersonHome {
(...)
public void throwVEE() {
throw new ViewExpiredException();
}
}
起初我通过简单地向我的 web.xml 添加一个错误页面来尝试它:
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/error.xhtml</location>
</error-page>
但这不起作用,我没有重定向到错误,但我看到了 Glassfish 错误页面,它显示了一个 HTTP 状态 500 页面,其中包含以下内容:
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
接下来我尝试编写 ExceptionHandlerFactory 和 CustomExceptionHandler,如JavaServerFaces 2.0 - The Complete Reference中所述。所以我将以下标签插入到 faces-config.xml 中:
<factory>
<exception-handler-factory>
exceptions.ExceptionHandlerFactory
</exception-handler-factory>
</factory>
并添加了这些类:工厂:
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;
}
}
自定义异常处理程序:
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();
}
}
但我仍然没有重定向到我的错误页面 - 我得到了与上面相同的 HTTP 500 错误。我做错了什么,我的实现中可能缺少什么异常处理不正确?任何帮助都非常感谢!
编辑
好吧,我说实话。事实上,我的代码实际上是用 Scala 编写的,但说来话长。我一直认为这是一个Java问题。在这种情况下,真正的错误是我自己的愚蠢。在我的 (Scala) 代码中,在 CustomExceptionHandler 中,我忘记添加带有“i.remove();”的行 所以 ViewExpiredException 在处理后留在了 UnhandledExceptionsQueue 中,并且它“冒泡了”。当它冒泡时,它变成了一个 ServletException。
真的很抱歉让你们俩感到困惑!