04 May 2009

JSF ViewExpiredException fix

After spending some time wrestling with this beast, I might have found a solution. Here's the scenario:
  1. Launch a very simple JSF app consisting of two pages, as described by the Select example from Chapter 4 of the Core JavaServer Faces book by D. Geary and C. Horstmann (no database calls).
  2. Allow the session to time out.
  3. Use your browser's back button to return to the index.faces page.
  4. Re-submit the form.
  5. Watch the app blow up with this exception:

HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: viewId:/index.faces - View /index.faces could not be restored.
javax.faces.webapp.FacesServlet.service(FacesServlet.java:270)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

root cause

javax.faces.application.ViewExpiredException: viewId:/index.faces - View /index.faces could not be restored.
com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:186)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:104)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)

After a lot of research on the web, the following context parameter in the web.xml file resolves it:
 <context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>

To see it in action, set your session timeout to 1 minute in web.xml:
   <session-config>  
<session-timeout>1</session-timeout>
</session-config>

However, be careful using this setting: You will cause the entire UI component tree to be serialized and passed to the client. This can increase download lag time, especially on more complex layouts. Also, there are times when sessions must expire (authenticated sessions), so you'd want to stick with the server for your state saving method in most cases.

6 comments:

Anonymous said...

nice fix.

Alex C said...

Glad it helped :)

Anonymous said...

thanks :) it works

Anonymous said...

Not really a fix but rather a work around. As mentioned in the article, this adds overhead to the client calls and takes the session management away from the server.

Anonymous said...

very nice

Anonymous said...

ViewExpiredException could be the result of the servlet container re-posting the original form data (after you log back in) - see this page on the MyFaces wiki