diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/EndState.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/EndState.java index 52ba7ab2..506b07e2 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/EndState.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/EndState.java @@ -18,6 +18,7 @@ package org.springframework.webflow.engine; import org.springframework.binding.mapping.Mapper; import org.springframework.binding.mapping.MappingResults; import org.springframework.core.style.ToStringCreator; +import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.execution.Action; import org.springframework.webflow.execution.ActionExecutor; @@ -83,8 +84,8 @@ public class EndState extends State { } /** - * Specialization of State's doEnter template method that executes behavior specific to this state - * type in polymorphic fashion. + * Specialization of State's doEnter template method that executes behavior specific to this state type + * in polymorphic fashion. *

* This implementation pops the top (active) flow session off the execution stack, ending it, and resumes control in * the parent flow (if necessary). If the ended session is the root flow, a final response is rendered. @@ -96,7 +97,7 @@ public class EndState extends State { FlowSession activeSession = context.getFlowExecutionContext().getActiveSession(); if (activeSession.isRoot()) { // entire flow execution is ending; issue the final response - if (finalResponseAction != null && context.getExternalContext().isResponseAllowed()) { + if (finalResponseAction != null && canSendResponse(context.getExternalContext())) { ActionExecutor.execute(finalResponseAction, context); context.getExternalContext().recordResponseComplete(); } @@ -123,6 +124,10 @@ public class EndState extends State { return output; } + private boolean canSendResponse(ExternalContext context) { + return context.isResponseAllowed() && !context.isResponseComplete(); + } + protected void appendToString(ToStringCreator creator) { creator.append("finalResponseAction", finalResponseAction).append("outputMapper", outputMapper); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java index cab244ca..f741e219 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java @@ -22,6 +22,7 @@ import java.util.Map; import org.springframework.core.style.ToStringCreator; import org.springframework.util.Assert; +import org.springframework.webflow.context.ExternalContext; import org.springframework.webflow.definition.TransitionDefinition; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.FlowExecutionException; @@ -168,7 +169,7 @@ public class ViewState extends TransitionableState { protected void doEnter(RequestControlContext context) throws FlowExecutionException { context.assignFlowExecutionKey(); - if (context.getExternalContext().isResponseAllowed()) { + if (canSendResponse(context.getExternalContext())) { if (shouldRedirect(context)) { context.getExternalContext().requestFlowExecutionRedirect(); if (popup) { @@ -191,7 +192,7 @@ public class ViewState extends TransitionableState { logger.debug("Event '" + event.getId() + "' returned from view " + view); } boolean stateExited = context.handleEvent(event); - if (!stateExited && context.getExternalContext().isResponseAllowed()) { + if (!stateExited && canSendResponse(context.getExternalContext())) { if (context.getExternalContext().isAjaxRequest()) { render(context, view); } else { @@ -203,7 +204,7 @@ public class ViewState extends TransitionableState { } } } else { - if (context.getExternalContext().isResponseAllowed()) { + if (canSendResponse(context.getExternalContext())) { render(context, view); } } @@ -228,6 +229,10 @@ public class ViewState extends TransitionableState { } } + private boolean canSendResponse(ExternalContext context) { + return context.isResponseAllowed() && !context.isResponseComplete(); + } + private boolean shouldRedirect(RequestControlContext context) { if (redirect != null) { return redirect.booleanValue();