SWF-991, SWF-1413 - Add ajax-driven flow attribute and redirect-in-same-view-state flow execution attribute

This commit is contained in:
Rossen Stoyanchev
2011-01-31 00:32:00 +00:00
parent b0e64468ae
commit 5cb3ef0067
28 changed files with 2009 additions and 122 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@ import org.springframework.webflow.execution.RequestContextHolder;
* Custom {@link StateManager} that manages the JSF component state in web flow's view scope.
*
* @author Jeremy Grelle
* @author Rossen Stoyanchev
*/
public class FlowViewStateManager extends StateManager {
@@ -150,31 +151,35 @@ public class FlowViewStateManager extends StateManager {
/**
* <p>
* JSF 1.2 (or higher) version of state saving.
* </p>
*
* <p>
* In JSF 2 where a partial state saving algorithm is used, this method merely delegates to the next
* ViewStateManager. Thus partial state saving is handled by the JSF 2 runtime. However, a
* {@link FlowViewResponseStateManager} plugged in via {@link FlowRenderKit} will ensure the state is saved in a Web
* Flow view-scoped variable.
* </p>
* In JSF 2, if partial state saving is enabled this method delegates in order to obtain the serialized view state.
* During rendering JSF calls this method to prepare the state and then calls {@link FlowViewResponseStateManager}
* which writes it to Web Flow's view scope.
*
* <p>
* Nevertheless this method always writes the serialized state to Web Flow's view scope to ensure it is up-to-date
* for cases outside of rendering (e.g. ViewState.updateHistory()) or when the render phase doesn't call
* {@link FlowViewResponseStateManager} such as when processing a partial request.
*/
public Object saveView(FacesContext context) {
if (context.getViewRoot().isTransient()) {
return null;
}
FlowSerializedView view = null;
if ((!JsfUtils.isFlowRequest()) || JsfRuntimeInformation.isPartialStateSavingSupported()) {
return delegate.saveView(context);
Object[] state = (Object[]) delegate.saveView(context);
view = new FlowSerializedView(context.getViewRoot().getViewId(), state[0], state[1]);
} else {
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (logger.isDebugEnabled()) {
logger.debug("Saving view root '" + context.getViewRoot().getViewId() + "' in view scope");
}
FlowSerializedView view = new FlowSerializedView(context.getViewRoot().getViewId(),
getTreeStructureToSave(context), getComponentStateToSave(context));
requestContext.getViewScope().put(SERIALIZED_VIEW_STATE, view);
return view;
view = new FlowSerializedView(context.getViewRoot().getViewId(), getTreeStructureToSave(context),
getComponentStateToSave(context));
}
RequestContext requestContext = RequestContextHolder.getRequestContext();
if (logger.isDebugEnabled()) {
logger.debug("Saving view root '" + context.getViewRoot().getViewId() + "' in view scope");
}
requestContext.getViewScope().put(SERIALIZED_VIEW_STATE, view);
return view;
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,6 +88,13 @@ public class JsfView implements View {
try {
logger.debug("Asking faces lifecycle to render");
facesLifecycle.render(facesContext);
/* Ensure serialized view state is always updated even if JSF didn't call StateManager.writeState(). */
if (JsfRuntimeInformation.isAtLeastJsf20()) {
if (requestContext.getExternalContext().isAjaxRequest()) {
saveState();
}
}
} finally {
logger.debug("View rendering complete");
facesContext.responseComplete();
@@ -134,9 +141,10 @@ public class JsfView implements View {
// Set the temporary UIViewRoot state so that it will be available across the redirect
return new ViewRootHolder(getViewRoot());
} else {
// In JSF 2 the partial state saving algorithm attaches a system event listener to the UIViewRoot with
// a reference to the FacesContext instance. The FacesContext instance is released at end of each request.
// Hence, keeping the UIViewRoot across the redirect is not feasible.
// In JSF 2 the partial state saving algorithm attaches a system event listener to the UIViewRoot which
// holds on to a reference to the FacesContext instance. The FacesContext instance is released at end of
// each request. Hence, keeping the UIViewRoot across the redirect is not feasible.
// @see com.sun.faces.context.StateContext$AddRemoveListener
logger.debug("User event state requested but not saved.");
return null;
}