Monday, August 8, 2016

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(ViewHandlerparent) {
  //System.out.println("CustomViewHandler.CustomViewHandler():ParentViewHandler:" + parent.getClass());
  this.parent = parent;
 }

 /**
 *@linkjavax.faces.application.ViewExpiredException}.Thishappensonlywhenwetrytologoutfromtimedoutpages.
 */
 @Override
 public UIViewRoot restoreView(FacesContext facesContext,String viewId) {
  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

1 comment: