ViewExpiredException显示在web.xml中的java.lang.Throwable错误页面中

时间:2010-07-08 18:49:32

标签: jsf servlets web.xml custom-error-pages viewexpiredexception

我正在开发一个JSF Web应用程序,如果视图过期,我需要在其中显示“Session Expired”页面,但是所有其他页面都会出现一般技术错误页面。当我触发异常时,应用程序仅进入技术错误页面。这是错误页面定义:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/jsps/utility/sessionExpired.jsp</location> 
</error-page> 
<error-page> 
    <exception-type>java.lang.Throwable</exception-type> 
    <location>/jsps/utility/technicalError.jsp</location> 
</error-page> 
<error-page>
    <error-code>500</error-code>
    <location>/jsps/utility/technicalError.jsp</location>
</error-page>

我删除了technicalError.jsp错误页面元素并且它工作正常,但是当我把它们放回去时我无法访问sessionExpired.jsp页面。如何告诉Web容器评估这些标记的顺序,以便出现正确的页面?感谢。

2 个答案:

答案 0 :(得分:16)

这是因为根据JSF规范,ViewExpiredException被包装在ServletException中。以下是JSF 1.2 specification的第10.2.6.2节的摘录:

  

10.2.6.2 FacesServlet

     

调用已保存的execute()实例的Lifecycle方法,并传递   此请求的FacesContext实例作为参数。如果是execute()方法   抛出FacesException将其重新抛出ServletException   FacesException为根本原因

如何分配错误页面在Servlet API规范中指定。以下是Servlet API specification 2.5第9.9.2节的摘录:

  

SRV.9.9.2错误页面

     

如果包含error-page没有 exception-type声明适合使用   类层次结构匹配,抛出的异常是ServletException或   其子类,容器提取包装的异常,如下所定义   ServletException.getRootCause方法。 对错误进行了第二次传递   页面声明,再次尝试匹配错误页面   声明,但改为使用包装的异常。

在类层次结构中,ServletException已匹配Throwable,因此第二遍不会提取其根本原因。

要证明此指定行为,请将javax.faces.application.ViewExpiredException替换为javax.servlet.ServletException作为<exception-type>并重试。您将看到正在显示的预期错误页面。

要解决此问题,只需删除 java.lang.Throwablejava.lang.Exception上的错误页面即可。如果没有一个异常特定错误页面匹配,那么无论如何它将回退到500的错误代码。所以,你需要的只是:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/jsps/utility/sessionExpired.jsp</location> 
</error-page> 
<error-page>
    <error-code>500</error-code>
    <location>/jsps/utility/technicalError.jsp</location>
</error-page>

更新:根据OP的(删除的)注释:为了可靠地测试它,你不能在bean构造函数或方法中执行throw new ViewExpiredException()。它反过来会包含在一些EL异常中。您最终可以在rootCause中添加打印Filter的调试行以自行查看。

如果您正在使用Eclipse / Tomcat,则可以通过以下方式快速测试ViewExpiredException

  1. 使用简单的命令按钮创建一个JSF页面,部署并运行它并在webbrowser中打开它。
  2. 返回Eclipse,右键单击Tomcat服务器并选择 Clean Tomcat Work Directory 。这将重启Tomcat 垃圾所有序列化会话(重要的是!只是重新启动Tomcat是不够的)。
  3. 返回webbrowser并按下命令按钮(不事先重新加载页面!)。

答案 1 :(得分:0)

如BylusC所述,部署描述符不得包含任何会捕获ViewExpiredException(包裹在ServletException中)的错误页面处理程序,而不是正确的错误页面处理程序-ViewExpiredException的错误页面。

不要忘记验证服务器的部署描述符(例如TomEE / conf / web.xml)是否不包含java.lang.Throwable或java.lang.Exception错误页面定义。因为这两个web.xml基本上是合并的。

是-应用程序的web.xml优先于服务器的web.xml,但是如果应用程序的web.xml包含

  • 500个错误页面(/error.xhtml)

和服务器的web.xml用于

  • 500(/500.html)和
  • 可投掷(/bigerror.html)

然后,应用程序上下文将包含这两个的合并:

  • 500(/error.xhtml)
  • 可投掷(/bigerror.html)

和ViewExpiredExcpetion错误处理将无法正常工作。