Preventing ViewExpiredException in JSF
When our page is idle for x amount of time the view will expire and throw javax.faces.application.ViewExpiredException to prevent this from happening
one solution is to create CustomViewHandler that extends ViewHandler
and override restoreView method all the other methods are being delegated to the Parent
import java.io.IOException; import javax.faces.FacesException; import javax.faces.application.ViewHandler; import javax.faces.component.UIViewRoot; import javax.faces.context.FacesContext; import javax.servlet.http.HttpServletRequest; public class CustomViewHandler extends ViewHandler { private ViewHandler parent; public CustomViewHandler(ViewHandler parent) { //System.out.println("CustomViewHandler.CustomViewHandler():Parent View Handler:"+parent.getClass()); this.parent = parent; } @Override public UIViewRoot restoreView(FacesContext facesContext, String viewId) { /** * {@link javax.faces.application.ViewExpiredException}. This happens only when we try to logout from timed out pages. */ UIViewRoot root =null; root = parent.restoreView(facesContext, viewId); if(root == null) { root = createView(facesContext, viewId); } return root; } @Override public Locale calculateLocale(FacesContext facesContext) { return parent.calculateLocale(facesContext); } @Override public String calculateRenderKitId(FacesContext facesContext) { String renderKitId = parent.calculateRenderKitId(facesContext); //System.out.println("CustomViewHandler.calculateRenderKitId():RenderKitId: "+renderKitId); return renderKitId; } @Override public UIViewRoot createView(FacesContext facesContext, String viewId) { return parent.createView(facesContext, viewId); } @Override public String getActionURL(FacesContext facesContext, String actionId) { return parent.getActionURL(facesContext, actionId); } @Override public String getResourceURL(FacesContext facesContext, String resId) { return parent.getResourceURL(facesContext, resId); } @Override public void renderView(FacesContext facesContext, UIViewRoot viewId) throws IOException, FacesException { parent.renderView(facesContext, viewId); } @Override public void writeState(FacesContext facesContext) throws IOException { parent.writeState(facesContext); } public ViewHandler getParent() { return parent; } }
Then you need to add it to your faces-config.xml
<view-handler>com.demo.CustomViewHandler</view-handler>
This will prevent you from getting ViewExpiredException’s
October 25th, 2009 at 11:23 pm
Hi, I am trying to implement this example but not sure where does the object ‘parent’ come from. Please help me.
Regards,
Kashif
October 27th, 2009 at 8:24 am
Parent comes from the ViewHandler constructor, also there are other methods that can be overwritten if you like.
private ViewHandler parent;
public CustomViewHandler(ViewHandler parent) {
//System.out.println("CustomViewHandler.CustomViewHandler():Parent View Handler:"+parent.getClass());
this.parent = parent;
}
Hope this helps, also I will update the post with this.
November 18th, 2009 at 10:41 am
Hi I tried this example and I get failure. It is due to the spread of ViewHanler you add other methods that do not what to do with them. In asking that page shows me what I’m doing gives me an error java.lang.NullPointerException: renderKitId
I’m a little awkward and not what you have to do. Please help.
November 18th, 2009 at 12:28 pm
I have updated the example with the other overwritten methods that should fix your problem.
If you still having issues post your code for your Custom ViewHandler
November 19th, 2009 at 2:57 am
Thank you very much, Greg.
November 19th, 2009 at 5:56 pm
No problem I hope this helps you.
July 23rd, 2010 at 3:38 am
Great work man :). It is the simplest working solution. Thanks.
July 23rd, 2010 at 9:07 am
Thanks
August 12th, 2010 at 8:04 am
If you’re using Facelets you can extend FaceletViewHandler and just have the restoreView() method. In my case I also return an error/information page if root == null. I think it’s more user friendly. Here’s the code:
August 17th, 2010 at 2:59 pm
Thanks for the solution. But I still do have some problems getting around my basic issue.
I have a secured application (Spring security), with a simple login form. I can happen fairly often that the user opens the login page and leaves the browser open without performing a login.
The session times out and when the user tries to login he would get a ViewExpiredException.
Displaying a session-time-out-page makes no sense, the user was at the start page and overriding the ViewExpiredException-behaviour for this single, simple issue seems like a dangerous overkill for me.
Is there any other way telling JSF this is the start page, we do not need a stored view for this??? I have read numerous articles about this and it has been bugging me for nearly a year(!) that you need to make fairly big changes in the JSF-ecosystem for imho a very, very common problem.
Where am I wrong?
August 19th, 2010 at 8:38 am
You might want to use
javax.faces.application.ViewExpiredException /sessionExpired.jsfin you faces-config.xml it might work for you. There is also a way of defining on how to catch errors in web.xml