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:
@@ -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();) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user