Hi SergeySmirnov,
Thanks for your reply. We might be able to create war files, but I'll start by explaining the behaviour that I'm seeing. I stepped through the code and located the difference.
To recap, we have two environments:
1) Application Maintenance (AM): MyFaces 1.1.4, Tomahawk 1.1.2, Ajax4JSF, JSPs, etc.
2) Developments: The same as above, but RichFaces 3.1.4 instead of A4J.
I started by putting a breakpoint in org.apache.myfaces.lifecycle.LifecylcleImpl in the restore view method:
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
if (viewRoot == null)
{
viewRoot = viewHandler.createView(facesContext, viewId);
viewRoot.setViewId(viewId);
facesContext.renderResponse();
//viewCreated = true;
}
Note that this breakpoint on UIViewRoot viewRoot will be hit twice: first for the page that we're leaving and again for the page that we're going to. I am interested in the page we're going to (assuming that I have already been to this page at least once).
For the page that we're going to, it goes into the AjaxViewHandler.restoreView. From there, it bounces around a bit, but ends up in the JspViewHandlerImpl:
public UIViewRoot restoreView(FacesContext facesContext, String viewId)
{
Application application = facesContext.getApplication();
ViewHandler applicationViewHandler = application.getViewHandler();
String renderKitId = applicationViewHandler.calculateRenderKitId(facesContext);
UIViewRoot viewRoot = application.getStateManager().restoreView(facesContext,
viewId,
renderKitId);
return viewRoot;
}
Note the call to the StateManager. In our AM environment, the StateManager is a JspStateManagerImpl, but in our Dev environment, the StateManager is a AjaxStateManager.
Here is where the two environments differ. Note the AjaxStateManager RestoreView code:
public UIViewRoot restoreView(FacesContext context, String viewId,
String renderKitId) {
UIViewRoot viewRoot = null;
ResponseStateManager responseStateManager = getRenderKit(context,
renderKitId).getResponseStateManager();
TreeStrutureNode treeStructure = null;
Object[] state = null;
if (isSavingStateInClient(context)) {
....
} else {
Object[] serializedView = restoreStateFromSession(context, viewId,
renderKitId);
if (null != serializedView) {
treeStructure = (TreeStrutureNode) serializedView[0];
state = (Object[]) serializedView[1];
}
}
if (null != treeStructure) {
viewRoot = (UIViewRoot) treeStructure.restore(componentLoader);
if (null != viewRoot && null != state) {
viewRoot.processRestoreState(context, state[0]);
restoreAdditionalState(context, state[1]);
}
}
return viewRoot;
}
In this case (we have server state saving enabled), it successfully restores the view from session and ultimately returns a view root to the lifecycle.
In our AM environment, we're seeing different behaviour:
From the Lifecycle it goes to AjaxViewHandler.restoreView, to JspViewHandlerImpl, to JspStateManagerImpl.restoreView. Note that the JspStateManagerImpl is used in place of the AjaxStateManager (which does not exist in A4J).
The code for the JspStateManagerImpl is as follows:
public UIViewRoot restoreView(FacesContext facescontext, String viewId, String renderKitId)
{
UIViewRoot uiViewRoot = restoreTreeStructure(facescontext, viewId, renderKitId);
if (uiViewRoot != null)
{
uiViewRoot.setViewId(viewId);
restoreComponentState(facescontext, uiViewRoot, renderKitId);
String restoredViewId = uiViewRoot.getViewId();
if (restoredViewId == null || !(restoredViewId.equals(viewId)))
{
if (log.isTraceEnabled()) log.trace("Exiting restoreView - restored view is null.");
return null;
}
}
return uiViewRoot;
}
Inside RestoreTreeStructure, the following code is called:
SerializedView serializedView = getSerializedViewFromServletSession(facesContext, viewId);
For the page that I'm going to, this always returns null. It's never retrieving the serialized view from session. This has an effect going back to the lifecycle:
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
if (viewRoot == null)
{
viewRoot = viewHandler.createView(facesContext, viewId);
viewRoot.setViewId(viewId);
facesContext.renderResponse();
//viewCreated = true;
}
Because the JspStateManager is never retrieving view roots, it's always creating them. This is in contrast to RichFaces where the ViewRoot is not null.
This is what we're seeing. In our AM environment (no RichFaces), we're always creating new view roots on the pages we're navigating to. With RichFaces in our Dev environment they're retrieved from session and restored. Can you shed any light on this behaviour?
Thanks.