Properly deal with cases where the flow execution has ended (e.g. because the flow execution ends immediately after starting).

This commit is contained in:
Erwin Vervaet
2008-07-17 05:04:59 +00:00
parent c5a9957b60
commit 1bf0c0fe89
3 changed files with 33 additions and 16 deletions

View File

@@ -37,6 +37,7 @@ import javax.faces.event.PhaseListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.binding.mapping.AttributeMapper;
import org.springframework.util.Assert;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.core.collection.LocalAttributeMap;
@@ -416,8 +417,13 @@ public class FlowPhaseListener implements PhaseListener {
ViewSelection selectedView = holder.getViewSelection();
if (selectedView == null) {
// no navigation event has been processed - simply refresh the execution with the same key
selectedView = holder.getFlowExecution().refresh(context);
if (holder.getFlowExecution().isActive()) {
// no navigation event has been processed - simply refresh the execution with the same key
selectedView = holder.getFlowExecution().refresh(context);
} else {
// fall back to a null-view
selectedView = ViewSelection.NULL_VIEW;
}
holder.setViewSelection(selectedView);
} else {
// a navigation event has been processed - generate a new flow execution key if necessary
@@ -536,6 +542,12 @@ public class FlowPhaseListener implements PhaseListener {
*/
protected void restoreFacesMessages(FacesContext context) {
if (FlowExecutionHolderUtils.isFlowExecutionRestored(context)) {
if (!FlowExecutionHolderUtils.getRequiredCurrentFlowExecution(context).isActive()) {
// the flow execution has ended -- no need to restore faces messages since we can't have a
// redirect in this case anyway
return;
}
MutableAttributeMap scope = getFacesMessagesScope(context);
Map facesMessagesMap = (Map) scope.get(getFacesMessagesKey());
if (facesMessagesMap != null) {
@@ -559,6 +571,9 @@ public class FlowPhaseListener implements PhaseListener {
* @since 1.0.6
*/
protected void saveFacesMessages(FacesContext context) {
Assert.state(FlowExecutionHolderUtils.getCurrentFlowExecution(context).isActive(),
"The flow execution should be active when trying to save faces messages");
// gather all message to put away in the flow execution
Map facesMessagesMap = new HashMap();
for (Iterator clientIds = context.getClientIdsWithMessages(); clientIds.hasNext();) {

View File

@@ -22,8 +22,8 @@ import org.springframework.webflow.executor.support.RequestParameterFlowExecutor
* {@link #createExternalUrl(org.springframework.webflow.execution.support.ExternalRedirect, String, ExternalContext) external URLs},
* since we're clearly not in a postback situation in those cases.
* <p>
* Also note that the resulting URL could potentially be too long when using JSF client-side state saving mode. In general
* there are issues in trying to use alwaysRedirectOnPause with client-side state saving.
* Also note that the resulting URL could potentially be too long when using JSF client-side state saving mode. In
* general there are issues in trying to use alwaysRedirectOnPause with client-side state saving.
*
* @since 1.0.6
*
@@ -45,5 +45,4 @@ public class JsfArgumentHandler extends RequestParameterFlowExecutorArgumentHand
}
return url.toString();
}
}

View File

@@ -66,23 +66,26 @@ public abstract class AutowiringSupport {
}
/**
* Autowire all objects in flash, flow and conversation scope for given flow execution.
* Autowire all objects in flash, flow and conversation scope for given flow execution. Autowiring will only happen
* if the provided flow execution is still active.
* @see #autowire(ScopeType, MutableAttributeMap)
*/
public void autowire(FlowExecutionContext flowExecutionContext) {
// no need to autowire request scope since that will be setup from scratch in this request
if (flowExecutionContext.isActive()) {
// no need to autowire request scope since that will be setup from scratch in this request
// autowire flash and flow scope for all flow sessions in the flow execution
FlowSession flowSession = flowExecutionContext.getActiveSession();
while (flowSession != null) {
autowire(ScopeType.FLASH, flowSession.getFlashMap());
autowire(ScopeType.FLOW, flowSession.getScope());
// autowire flash and flow scope for all flow sessions in the flow execution
FlowSession flowSession = flowExecutionContext.getActiveSession();
while (flowSession != null) {
autowire(ScopeType.FLASH, flowSession.getFlashMap());
autowire(ScopeType.FLOW, flowSession.getScope());
flowSession = flowSession.getParent();
flowSession = flowSession.getParent();
}
// autowire conversation scope, which is not tied to the flow session
autowire(ScopeType.CONVERSATION, flowExecutionContext.getConversationScope());
}
// autowire conversation scope, which is not tied to the flow session
autowire(ScopeType.CONVERSATION, flowExecutionContext.getConversationScope());
}
/**