diff --git a/spring-webflow/changelog.txt b/spring-webflow/changelog.txt index 6c6fc873..9e5ec8dd 100644 --- a/spring-webflow/changelog.txt +++ b/spring-webflow/changelog.txt @@ -15,6 +15,8 @@ Package org.springframework.webflow.executor * Statics on FlowFacesUtils are now public: they're supposed to be well known names. * FlowPhaseListener.cleanupResources() is now protected. * Added AutowiringFlowExecutionListener (SWF-746). +* In a JSF 1.2 environment, SWF will now correctly maintain the "java.faces.ViewState" parameter accross flow + execution redirects (SWF-445). Changes in version 1.0.5 (03.10.2007) ------------------------------------- diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfArgumentHandler.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfArgumentHandler.java new file mode 100644 index 00000000..b10d711b --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfArgumentHandler.java @@ -0,0 +1,46 @@ +package org.springframework.webflow.executor.jsf; + +import org.springframework.webflow.context.ExternalContext; +import org.springframework.webflow.execution.FlowExecutionContext; +import org.springframework.webflow.executor.support.RequestParameterFlowExecutorArgumentHandler; + +/** + * JSF specific argument handler that ensures the JSF 1.2 "javax.faces.ViewState" parameter is maintained accross flow + * execution redirects. Note that this argument handler does not rely on JSF 1.2 specific APIs, so it can be used safely + * in a JSF 1.1 environment. + *

+ * Maintaining the "javax.faces.ViewState" parameter is important because JSF uses it to tell whether or not a request + * is a postback. If the request is a postback, the JSF {@link javax.faces.application.StateManager} will be used to + * restore the JSF component states in the view, otherwise state is lost. The actual value of the parameter is not + * defined by the JSF specification. + *

+ * Note that the "javax.faces.ViewState" parameter will only be added to + * {@link #createFlowExecutionUrl(String, FlowExecutionContext, ExternalContext) flow execution URLs}. It doesn't make + * sense to add it to + * {@link #createFlowDefinitionUrl(org.springframework.webflow.execution.support.FlowDefinitionRedirect, ExternalContext) flow definition URLs} + * or + * {@link #createExternalUrl(org.springframework.webflow.execution.support.ExternalRedirect, String, ExternalContext) external URLs}, + * since we're clearly not in a postback situation in those cases. + * + * @since 1.0.6 + * + * @author Erwin Vervaet + * @author Mike Seghers + */ +public class JsfArgumentHandler extends RequestParameterFlowExecutorArgumentHandler { + + // the ViewState parameter as defined by ResponseStateManager.VIEW_STATE_PARAM in JSF 1.2 + private static final String VIEW_STATE_PARAM = "javax.faces.ViewState"; + + public String createFlowExecutionUrl(String flowExecutionKey, FlowExecutionContext flowExecution, + ExternalContext context) { + StringBuffer url = new StringBuffer(super.createFlowExecutionUrl(flowExecutionKey, flowExecution, context)); + String viewStateParam = context.getRequestParameterMap().get(VIEW_STATE_PARAM); + if (viewStateParam != null) { + url.append('&'); // the flow execution key is already there + appendQueryParameter(url, VIEW_STATE_PARAM, viewStateParam); + } + return url.toString(); + } + +}