当前位置:首页 > 开发 > 系统架构 > 架构 > 正文

javax.faces.application.ViewExpiredException: View could not be restored

发表于: 2013-10-21   作者:sunjing   来源:转载   浏览次数:
JSF
摘要: The ViewExpiredException will be thrown whenever the javax.faces.STATE_SAVING_METHOD is set to server (default) and the enduser sends a HTTP POST request using <h:commandLink> or <h:commandBu

The ViewExpiredException will be thrown whenever the javax.faces.STATE_SAVING_METHOD is set to server (default) and the enduser sends a HTTP POST request using <h:commandLink> or <h:commandButton> on a view, while the associated view state isn't available in the session anymore. The view state is identified by a hidden input field javax.faces.ViewState of the <h:form>. With the state saving method set to server, this contains only the view state ID which references a serialized view state in the session. So, when the session is expired for some reason (either timed out in server or client side, or the session cookie is not maintained anymore for some reason in browser, or by calling HttpSession#invalidate() in server), then the serialized view state is not available anymore in the session and the enduser will get this exception.

With the state saving method set to client, the javax.faces.ViewState hidden input field contains instead the whole serialized view state, so the enduser won't get a ViewExpiredException when the session expires.

In order to prevent ViewExpiredException when the state saving is set to server, only redirecting the POST request after logout is not sufficient. You also need to instruct the browser to not cache the dynamic JSF pages, otherwise the browser may show them from the cache instead of requesting a fresh one from the server when you send a GET request on it (e.g. by back button). If you're using POST for page-to-page navigation, this will in turn fail.

To fire a redirect after logout in JSF 2.0, either add <redirect /> to the <navigation-case> in question (if any), or add ?faces-redirect=true to the outcome value.

    <h:commandButtonvalue="Logout"action="logout?faces-redirect=true"/>

or

    public String logout() {
        // ...
        return "index?faces-redirect=true";
    }

To instruct the browser to not cache the dynamic JSF pages, create a Filter which is mapped on the servlet name of the FacesServlet and adds the needed response headers to disable the browser cache. E.g.

 

// Must match <servlet-name> of your FacesServlet.
@WebFilter(servletNames={"Faces Servlet"})
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
            res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            res.setDateHeader("Expires", 0); // Proxies.
        }

        chain.doFilter(request, response);
    }

    // ...
}

When you want to handle the ViewExpiredException on an arbitrary page which was already opened in some browser tab/window while you're logged out in another tab/window, then you'd like to specify an error-page for that in web.xml which goes to index/login page or maybe a "Your session is timed out" page. E.g.

 

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/login.xhtml</location>
</error-page>

 

Note that handling exceptions during ajax requests requires a special ExceptionHandler. See also the last "See also" link below for a detailed answer on that.

 

See also:

 

Unrelated to the concrete problem, using HTTP POST for pure page-to-page navigation isn't very user/SEO friendly. In JSF 2.0 you should really prefer <h:link> or <h:button> over the <h:commandXxx> ones for plain vanilla page-to-page navigation.

See also

javax.faces.application.ViewExpiredException: View could not be restored

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
在XML中布局时,我们自定义的View的触摸原点在哪??这又是一个问题啊,学习的过程就是不断发现问题
起因: 公司的电脑启动就会蓝屏,Windows XP Sp2 (建议用Windows 7),经过安全模式,还原最近配置
iOS Programming View and View Hierarchy 视图和视图等级 1.1(1)File → New → Project.. From
Android4.0设计规定的有效可触摸的UI元素标准是48dp,转化为一个物理尺寸约为9毫米。7~10毫米,这是
  In this tutorial, you learn how to create a common page layout for multiple pages in your
说了这么多,那 View 的大小是多少呢?这小节我就研究下 View 的大小。通过 LogCat 来研究 View 的
Android自定义View研究:View的大小 Android开发View是一个基本的视图界面,但是如何做一个自定义的
我们自定义了View,但是有没想过一个问题,就是View中的(0,0)坐标,也就是原点坐标在哪??我们是不
view.frame参照的是父视图的位置和大小,而view.bounds参照的是本地坐标系统中的位置和大小。 如上
好像有段时间没有更新了,主要项目比较着急,不过现在cocos2d基本算是全拿下了,进展很顺利,那么在
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号