JSF State Saving: Best of Both Worlds

When the state saving method of a JSF application is set to server by the javax.faces.STATE_SAVING_METHOD context parameter, state of the each page is saved in session map. The viewid of each page which corresponds to the pagename is used as the key in session. Although this method has performance advantages compared to the client state saving, nobody is perfect. The thing is that, if you have memory issues saving each page’s state in session does not seem to be a good choice.

Following is the output of FacesTrace tool visualizing the situation, there are 3 pages visited, each view of the page is hold in session by the page name and there is also a list in session holding the list of the view ids.

When the state saving is set to client, the state is sent to the browser as a hidden variable and then restored when a post occurs. This means there is only one view each request is aware of, this is also possible with the server side state saving,(with a little manual tuning of course). The best place to intersect the navigation and clean the view which is navigated from is a navigation handler. Here is one for this job;

  
    
    

    public class MyNavigationHandler extends NavigationHandler{
  
  protected NavigationHandler baseNavigationHandler;
  
  public NavigationHandler getBaseNavigationHandler() {
    return baseNavigationHandler;
  }

  public void setBaseNavigationHandler(NavigationHandler baseNavigationHandler) {
    this.baseNavigationHandler = baseNavigationHandler;
  }

  public void handleNavigation(FacesContext facesContext, String actionMethod, String actionName) {
    removeViewFromSession(facesContext);
    baseNavigationHandler.handleNavigation(facesContext, actionMethod, actionName);
    
  }
  
  protected void removeViewFromSession(FacesContext facesContext) {
    Map sessionMap = facesContext.getExternalContext().getSessionMap();
    String viewId = facesContext.getViewRoot().getViewId();
    sessionMap.remove(viewId);
      List viewsInSession = ((List)sessionMap.get("com.sun.faces.VIEW_LIST"));
      if(viewsInSession != null)
        viewsInSession.remove(viewId);
  }
}
      

This example works for the Sun’s RI implementation, I remember once there is a context parameter to tune the number of views in session in MyFaces but I cannot see it in the latest builds. Anyway this method takes the both side’s advantages in the state saving business. There is only one view the session allowed and the overhead caused by restoring the encoded state in client mode is escaped.

2 Responses to JSF State Saving: Best of Both Worlds

  1. kapa says:

    hi, im confused about
    “since the state is hold at session, even you navigate to other pages, it is likely to see the values entered to the form when you come back to the page. So this is the answer to the question; Why the components still hold the same values even their value bindings are to request scoped managed beans and there is no postback?”

    i dont know what u mean about “components still hold the same values”, is that true?and how to reproduce it? when i use server state, using value binding from Page1.jsp’s textfield to some request scope’s property, then push page1’s button to update the property then going page2, click the link in page2 to go back page1, and there isnt holding anything in the page1’s textfield.

    something wrong of my understanding?

  2. Cagatay says:

    Hi Kapa, no there is nothing wrong with your understanding, it is my bad actually. This is a situation in our project. There was a special case causing the components to hold their values and applying this navigation handler fixed it. I’ve updated the entry to prevent any more misunderstandings.

%d bloggers like this: