flow outcome modeling
flow possible outcomes
This commit is contained in:
@@ -63,6 +63,12 @@ public interface FlowDefinition extends Annotated {
|
||||
*/
|
||||
public StateDefinition getState(String id) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the outcomes that are possible for this flow to reach.
|
||||
* @return the possible outcomes
|
||||
*/
|
||||
public String[] getPossibleOutcomes();
|
||||
|
||||
/**
|
||||
* Returns a reference to application context hosting application objects and services needed by this flow
|
||||
* definition.
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.springframework.binding.mapping.MappingResults;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
@@ -99,12 +98,11 @@ public class EndState extends State {
|
||||
if (finalResponseAction != null && context.getExternalContext().isResponseAllowed()) {
|
||||
ActionExecutor.execute(finalResponseAction, context);
|
||||
}
|
||||
context.endActiveFlowSession(createSessionOutput(context));
|
||||
context.endActiveFlowSession(getId(), createSessionOutput(context));
|
||||
} else {
|
||||
// there is a parent flow that will resume (this flow is a subflow)
|
||||
LocalAttributeMap sessionOutput = createSessionOutput(context);
|
||||
context.endActiveFlowSession(sessionOutput);
|
||||
context.handleEvent(new Event(this, getId(), sessionOutput));
|
||||
context.endActiveFlowSession(getId(), sessionOutput);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -76,16 +78,17 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
* implementations but may also be directly instantiated.
|
||||
* <p>
|
||||
* This class and the rest of the Spring Web Flow (SWF) engine have been designed with minimal dependencies on other
|
||||
* libraries. Spring Web Flow is usable in a standalone fashion (as well as in the context of other frameworks like
|
||||
* Spring MVC, Struts, or JSF, for example). The engine system is fully usable outside an HTTP servlet environment, for
|
||||
* example in portlets, tests, or standalone applications. One of the major architectural benefits of Spring Web Flow is
|
||||
* the ability to design reusable, high-level controller modules that may be executed in <i>any</i> environment.
|
||||
* libraries. Spring Web Flow is usable in a standalone fashion. The engine system is fully usable outside an HTTP
|
||||
* servlet environment, for example in portlets, tests, or standalone applications. One of the major architectural
|
||||
* benefits of Spring Web Flow is the ability to design reusable, high-level controller modules that may be executed in
|
||||
* <i>any</i> environment.
|
||||
* <p>
|
||||
* Note: flows are singleton definition objects so they should be thread-safe. You can think a flow definition as
|
||||
* analogous to a Java class, defining all the behavior of an application module. The core behaviors
|
||||
* {@link #start(RequestControlContext, MutableAttributeMap) start}, {@link #resume(RequestControlContext)},
|
||||
* {@link #handleEvent(RequestControlContext) on event}, {@link #end(RequestControlContext, MutableAttributeMap) end},
|
||||
* and {@link #handleException(FlowExecutionException, RequestControlContext)}. Each method accepts a
|
||||
* {@link #handleEvent(RequestControlContext) on event},
|
||||
* {@link #end(RequestControlContext, String, MutableAttributeMap) end}, and
|
||||
* {@link #handleException(FlowExecutionException, RequestControlContext)}. Each method accepts a
|
||||
* {@link RequestContext request context} that allows for this flow to access execution state in a thread safe manner. A
|
||||
* flow execution is what models a running instance of this flow definition, somewhat analogous to a java object that is
|
||||
* an instance of a class.
|
||||
@@ -210,6 +213,17 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
return getStateInstance(stateId);
|
||||
}
|
||||
|
||||
public String[] getPossibleOutcomes() {
|
||||
List possibleOutcomes = new ArrayList();
|
||||
for (Iterator it = states.iterator(); it.hasNext();) {
|
||||
State state = (State) it.next();
|
||||
if (state instanceof EndState) {
|
||||
possibleOutcomes.add(state.getId());
|
||||
}
|
||||
}
|
||||
return (String[]) possibleOutcomes.toArray(new String[possibleOutcomes.size()]);
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
@@ -541,10 +555,13 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
* mapper ({@link #setOutputMapper(Mapper)}).</li>
|
||||
* </ol>
|
||||
* @param context the flow execution control context
|
||||
* @param outcome the logical flow outcome that will be returned by the session, generally the id of the terminating
|
||||
* end state
|
||||
* @param output initial output produced by the session that is eligible for modification by this method
|
||||
* @throws FlowExecutionException when an exception occurs ending this flow
|
||||
*/
|
||||
public void end(RequestControlContext context, MutableAttributeMap output) throws FlowExecutionException {
|
||||
public void end(RequestControlContext context, String outcome, MutableAttributeMap output)
|
||||
throws FlowExecutionException {
|
||||
endActionList.execute(context);
|
||||
if (outputMapper != null) {
|
||||
MappingResults results = outputMapper.map(context, output);
|
||||
@@ -584,7 +601,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreVariables(RequestContext context) {
|
||||
public void restoreVariables(RequestContext context) {
|
||||
Iterator it = variables.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
FlowVariable variable = (FlowVariable) it.next();
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionContext;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
@@ -132,12 +131,12 @@ public interface RequestControlContext extends RequestContext {
|
||||
* End the active flow session of the current flow execution. This method should be called by clients that terminate
|
||||
* flows, such as end states. The <code>end()</code> method of the flow involved in the flow execution will be
|
||||
* called.
|
||||
* @param output output produced by the session that is eligible for mapping by a resuming parent flow
|
||||
* @return the ended session
|
||||
* @param outcome the logical outcome the ending session should return
|
||||
* @param output output the ending session should return
|
||||
* @throws IllegalStateException when the flow execution is not active
|
||||
* @see Flow#end(RequestControlContext, MutableAttributeMap)
|
||||
* @see Flow#end(RequestControlContext, String, MutableAttributeMap)
|
||||
*/
|
||||
public FlowSession endActiveFlowSession(MutableAttributeMap output) throws IllegalStateException;
|
||||
public void endActiveFlowSession(String outcome, MutableAttributeMap output) throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Returns true if the 'always redirect pause' flow execution attribute is set to true, false otherwise.
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowExecutionKeyFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionListener;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.RequestContextHolder;
|
||||
@@ -134,9 +135,9 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
|
||||
private String flowId;
|
||||
|
||||
/**
|
||||
* The flow execution outcome event.
|
||||
* The outcome reached by this flow execution when it ends.
|
||||
*/
|
||||
private transient Event outcome;
|
||||
private transient FlowExecutionOutcome outcome;
|
||||
|
||||
/**
|
||||
* Default constructor required for externalizable serialization. Should NOT be called programmatically.
|
||||
@@ -195,7 +196,7 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
|
||||
return hasStarted() && !isActive();
|
||||
}
|
||||
|
||||
public Event getOutcome() {
|
||||
public FlowExecutionOutcome getOutcome() {
|
||||
return outcome;
|
||||
}
|
||||
|
||||
@@ -383,16 +384,23 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
|
||||
return transition.execute(getCurrentState(), context);
|
||||
}
|
||||
|
||||
FlowSession endActiveFlowSession(MutableAttributeMap output, RequestControlContext context) {
|
||||
void endActiveFlowSession(String outcome, MutableAttributeMap output, RequestControlContext context) {
|
||||
FlowSessionImpl session = getActiveSessionInternal();
|
||||
listeners.fireSessionEnding(context, session, output);
|
||||
session.getFlow().end(context, output);
|
||||
listeners.fireSessionEnding(context, session, outcome, output);
|
||||
session.getFlow().end(context, outcome, output);
|
||||
flowSessions.removeLast();
|
||||
listeners.fireSessionEnded(context, session, output);
|
||||
if (hasEnded()) {
|
||||
outcome = new Event(this, session.getState().getId(), output);
|
||||
boolean executionEnded = hasEnded();
|
||||
if (executionEnded) {
|
||||
// set the root flow execution outcome for external clients to use
|
||||
this.outcome = new FlowExecutionOutcome(outcome, output);
|
||||
}
|
||||
listeners.fireSessionEnded(context, session, outcome, output);
|
||||
if (!executionEnded) {
|
||||
// restore any variables that may have transient references
|
||||
getActiveSessionInternal().getFlow().restoreVariables(context);
|
||||
// treat the outcome as an event against the current state of the new active flow
|
||||
context.handleEvent(new Event(session.getState(), outcome, output));
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
FlowExecutionKey assignKey() {
|
||||
|
||||
@@ -202,18 +202,19 @@ class FlowExecutionListeners {
|
||||
/**
|
||||
* Notify all interested listeners that the active flow execution session is ending.
|
||||
*/
|
||||
public void fireSessionEnding(RequestContext context, FlowSession session, MutableAttributeMap output) {
|
||||
public void fireSessionEnding(RequestContext context, FlowSession session, String outcomeId,
|
||||
MutableAttributeMap output) {
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].sessionEnding(context, session, output);
|
||||
listeners[i].sessionEnding(context, session, outcomeId, output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all interested listeners that a flow execution session has ended.
|
||||
*/
|
||||
public void fireSessionEnded(RequestContext context, FlowSession session, AttributeMap output) {
|
||||
public void fireSessionEnded(RequestContext context, FlowSession session, String outcomeId, AttributeMap output) {
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].sessionEnded(context, session, output);
|
||||
listeners[i].sessionEnded(context, session, outcomeId, output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionContext;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
@@ -218,8 +217,8 @@ class RequestControlContextImpl implements RequestControlContext {
|
||||
flowExecution.start(flow, input, this);
|
||||
}
|
||||
|
||||
public FlowSession endActiveFlowSession(MutableAttributeMap output) throws IllegalStateException {
|
||||
return flowExecution.endActiveFlowSession(output, this);
|
||||
public void endActiveFlowSession(String outcome, MutableAttributeMap output) throws IllegalStateException {
|
||||
flowExecution.endActiveFlowSession(outcome, output, this);
|
||||
}
|
||||
|
||||
public boolean getAlwaysRedirectOnPause() {
|
||||
|
||||
@@ -84,10 +84,10 @@ public interface FlowExecutionContext {
|
||||
public boolean hasEnded();
|
||||
|
||||
/**
|
||||
* Returns the ending outcome event of this execution, or null if this execution has not yet ended.
|
||||
* @return the outcome event
|
||||
* Returns the outcome reached by this execution, or null if this execution has not yet ended.
|
||||
* @return the outcome, or <code>null</code> if this execution has not yet ended
|
||||
*/
|
||||
public Event getOutcome();
|
||||
public FlowExecutionOutcome getOutcome();
|
||||
|
||||
/**
|
||||
* Returns the active flow session of this flow execution. The active flow session is the currently executing
|
||||
|
||||
@@ -153,19 +153,21 @@ public interface FlowExecutionListener {
|
||||
* Called when the active flow execution session has been asked to end but before it has ended.
|
||||
* @param context the current flow request context
|
||||
* @param session the current active session that is ending
|
||||
* @param outcome the outcome reached by the ending session, generally the id of the terminating end-state
|
||||
* @param output the flow output produced by the ending session, this map may be modified by this listener to affect
|
||||
* the output returned
|
||||
*/
|
||||
public void sessionEnding(RequestContext context, FlowSession session, MutableAttributeMap output);
|
||||
public void sessionEnding(RequestContext context, FlowSession session, String outcome, MutableAttributeMap output);
|
||||
|
||||
/**
|
||||
* Called when a flow execution session ends. If the ended session was the root session of the flow execution, the
|
||||
* entire flow execution also ends.
|
||||
* @param context the current flow request context
|
||||
* @param session ending flow session
|
||||
* @param output final, unmodifiable output returned by the ended session
|
||||
* @param outcome the outcome reached by the ended session, generally the id of the terminating end-state
|
||||
* @param output the flow output returned by the ending session
|
||||
*/
|
||||
public void sessionEnded(RequestContext context, FlowSession session, AttributeMap output);
|
||||
public void sessionEnded(RequestContext context, FlowSession session, String outcome, AttributeMap output);
|
||||
|
||||
/**
|
||||
* Called when an exception is thrown during a flow execution, before the exception is handled by any registered
|
||||
|
||||
@@ -70,10 +70,10 @@ public abstract class FlowExecutionListenerAdapter implements FlowExecutionListe
|
||||
public void resuming(RequestContext context) {
|
||||
}
|
||||
|
||||
public void sessionEnding(RequestContext context, FlowSession session, MutableAttributeMap output) {
|
||||
public void sessionEnding(RequestContext context, FlowSession session, String outcome, MutableAttributeMap output) {
|
||||
}
|
||||
|
||||
public void sessionEnded(RequestContext context, FlowSession session, AttributeMap output) {
|
||||
public void sessionEnded(RequestContext context, FlowSession session, String outcome, AttributeMap output) {
|
||||
}
|
||||
|
||||
public void exceptionThrown(RequestContext context, FlowExecutionException exception) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.springframework.webflow.execution;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.CollectionUtils;
|
||||
|
||||
/**
|
||||
* An outcome returned by a flow execution when it ends.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class FlowExecutionOutcome {
|
||||
|
||||
private String id;
|
||||
|
||||
private AttributeMap output;
|
||||
|
||||
/**
|
||||
* Creates a new flow execution outcome
|
||||
* @param id the outcome id
|
||||
* @param output the output returned by the execution
|
||||
*/
|
||||
public FlowExecutionOutcome(String id, AttributeMap output) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.output = (output != null ? output : CollectionUtils.EMPTY_ATTRIBUTE_MAP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the outcome identifier.
|
||||
* @return the outcome that was reached by the flow execution
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output returned by the flow execution.
|
||||
* @return the output that was returned
|
||||
*/
|
||||
public AttributeMap getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("id", id).append("output", output).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,8 +15,7 @@
|
||||
*/
|
||||
package org.springframework.webflow.executor;
|
||||
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
|
||||
/**
|
||||
* A value object providing information about the result of a flow execution request.
|
||||
@@ -29,15 +28,12 @@ public class FlowExecutionResult {
|
||||
|
||||
private String flowExecutionKey;
|
||||
|
||||
private String outcome;
|
||||
private FlowExecutionOutcome outcome;
|
||||
|
||||
private AttributeMap output;
|
||||
|
||||
private FlowExecutionResult(String flowId, String flowExecutionKey, String outcome, AttributeMap output) {
|
||||
private FlowExecutionResult(String flowId, String flowExecutionKey, FlowExecutionOutcome outcome) {
|
||||
this.flowId = flowId;
|
||||
this.flowExecutionKey = flowExecutionKey;
|
||||
this.outcome = outcome;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +44,7 @@ public class FlowExecutionResult {
|
||||
* @return the result
|
||||
*/
|
||||
public static FlowExecutionResult createPausedResult(String flowId, String flowExecutionKey) {
|
||||
return new FlowExecutionResult(flowId, flowExecutionKey, null, null);
|
||||
return new FlowExecutionResult(flowId, flowExecutionKey, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,8 +53,8 @@ public class FlowExecutionResult {
|
||||
* @param outcome the ending execution outcome
|
||||
* @return the result
|
||||
*/
|
||||
public static FlowExecutionResult createEndedResult(String flowId, Event outcome) {
|
||||
return new FlowExecutionResult(flowId, null, outcome.getId(), outcome.getAttributes());
|
||||
public static FlowExecutionResult createEndedResult(String flowId, FlowExecutionOutcome outcome) {
|
||||
return new FlowExecutionResult(flowId, null, outcome);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,21 +91,12 @@ public class FlowExecutionResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flow execution outcome when ab ended result.
|
||||
* Returns the flow execution outcome when an ended result.
|
||||
* @see #ended()
|
||||
* @return the ended outcome
|
||||
* @return the ended outcome, or <code>null</code> if this is not an ended result
|
||||
*/
|
||||
public String getEndedOutcome() {
|
||||
public FlowExecutionOutcome getOutcome() {
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output returned from the flow execution when an ended result.
|
||||
* @see #ended()
|
||||
* @return the ended output
|
||||
*/
|
||||
public AttributeMap getEndedOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,8 +21,8 @@ import javax.portlet.RenderResponse;
|
||||
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
|
||||
/**
|
||||
* Trivial flow handler base class that simply returns null for all operations. Subclasses should extend and override
|
||||
@@ -44,7 +44,7 @@ public class AbstractFlowHandler implements FlowHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, RenderResponse response) {
|
||||
public String handleFlowOutcome(FlowExecutionOutcome outcome, RenderRequest request, RenderResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ import javax.portlet.RenderResponse;
|
||||
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
|
||||
/**
|
||||
* A controller helper used for customizing access to a <i>single</i> flow definition. This helper is used to:
|
||||
@@ -55,13 +55,12 @@ public interface FlowHandler {
|
||||
/**
|
||||
* Handles a specific flow execution outcome. Used to select a new view to render after the flow ends.
|
||||
* @param outcome the outcome that was reached
|
||||
* @param output the output returned by the flow execution
|
||||
* @param request the current render request
|
||||
* @param response the current render response
|
||||
* @return the id of the flow to start after handling the outcome, or null if the outcome should be handled by the
|
||||
* caller
|
||||
*/
|
||||
public String handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request, RenderResponse response);
|
||||
public String handleFlowOutcome(FlowExecutionOutcome outcome, RenderRequest request, RenderResponse response);
|
||||
|
||||
/**
|
||||
* Handles a flow exception that was not handled by the Web Flow system. Used by a Controller to handle a specific
|
||||
|
||||
@@ -34,9 +34,9 @@ import org.springframework.webflow.context.portlet.DefaultFlowUrlHandler;
|
||||
import org.springframework.webflow.context.portlet.FlowUrlHandler;
|
||||
import org.springframework.webflow.context.portlet.PortletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
@@ -88,10 +88,8 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
.getAttribute(FLOW_EXECUTION_RESULT_ATTRIBUTE);
|
||||
if (result != null) {
|
||||
session.removeAttribute(FLOW_EXECUTION_RESULT_ATTRIBUTE);
|
||||
String outcome = result.getEndedOutcome();
|
||||
AttributeMap output = result.getEndedOutput();
|
||||
String flowId = flowHandler.handleFlowOutcome(outcome, output, request, response);
|
||||
return defaultHandleFlowOutcome(flowHandler, outcome, output, flowId, request, response);
|
||||
String flowId = flowHandler.handleFlowOutcome(result.getOutcome(), request, response);
|
||||
return defaultHandleFlowOutcome(flowHandler, result.getOutcome(), flowId, request, response);
|
||||
} else {
|
||||
return startFlow(request, response, flowHandler);
|
||||
}
|
||||
@@ -145,7 +143,7 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
return inputMap;
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleFlowOutcome(FlowHandler flowHandler, String outcome, AttributeMap output,
|
||||
protected ModelAndView defaultHandleFlowOutcome(FlowHandler flowHandler, FlowExecutionOutcome outcome,
|
||||
String nextFlowId, RenderRequest request, RenderResponse response) throws IOException {
|
||||
if (nextFlowId == null) {
|
||||
nextFlowId = flowHandler.getFlowId();
|
||||
@@ -154,7 +152,7 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
logger.debug("Starting a new execution of flow '" + nextFlowId + "'");
|
||||
}
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
flowExecutor.launchExecution(nextFlowId, new LocalAttributeMap(output.asMap()), context);
|
||||
flowExecutor.launchExecution(nextFlowId, new LocalAttributeMap(outcome.getOutput().asMap()), context);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
|
||||
/**
|
||||
* Trivial flow handler base class that simply returns null for all operations. Subclasses should extend and override
|
||||
@@ -38,7 +38,7 @@ public class AbstractFlowHandler implements FlowHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
@@ -195,14 +196,14 @@ public class FlowController extends AbstractController {
|
||||
return inputMap;
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleFlowOutcome(String flowId, String outcome, AttributeMap endedOutput,
|
||||
protected ModelAndView defaultHandleFlowOutcome(String flowId, FlowExecutionOutcome outcome,
|
||||
HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
if (!response.isCommitted()) {
|
||||
// by default, just start the flow over passing the output as input
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Restarting a new execution of ended flow '" + flowId + "'");
|
||||
}
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, endedOutput, request));
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, outcome.getOutput(), request));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -269,8 +270,7 @@ public class FlowController extends AbstractController {
|
||||
sendRedirect(context, request, response, context.getExternalRedirectUrl());
|
||||
return null;
|
||||
} else {
|
||||
return handleFlowOutcome(result.getFlowId(), result.getEndedOutcome(), result.getEndedOutput(),
|
||||
request, response);
|
||||
return handleFlowOutcome(result.getFlowId(), result.getOutcome(), request, response);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Execution result should have been one of [paused] or [ended]");
|
||||
@@ -295,15 +295,15 @@ public class FlowController extends AbstractController {
|
||||
}
|
||||
}
|
||||
|
||||
private ModelAndView handleFlowOutcome(String flowId, String outcome, AttributeMap endedOutput,
|
||||
HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
private ModelAndView handleFlowOutcome(String flowId, FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException {
|
||||
FlowHandler handler = getFlowHandler(flowId);
|
||||
if (handler != null) {
|
||||
String location = handler.handleExecutionOutcome(outcome, endedOutput, request, response);
|
||||
String location = handler.handleExecutionOutcome(outcome, request, response);
|
||||
return location != null ? createRedirectView(location, request) : defaultHandleFlowOutcome(flowId, outcome,
|
||||
endedOutput, request, response);
|
||||
request, response);
|
||||
} else {
|
||||
return defaultHandleFlowOutcome(flowId, outcome, endedOutput, request, response);
|
||||
return defaultHandleFlowOutcome(flowId, outcome, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
|
||||
/**
|
||||
* A controller helper used for customizing access to a <i>single</i> flow definition. This helper is used to:
|
||||
@@ -59,13 +59,12 @@ public interface FlowHandler {
|
||||
* to the current servlet path.
|
||||
*
|
||||
* @param outcome the outcome that was reached
|
||||
* @param output the output returned by the flow execution
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
* @return the location of the new resource to redirect to, or null if the execution outcome was not handled and
|
||||
* should be handled by the caller
|
||||
*/
|
||||
public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response);
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
@@ -159,14 +160,14 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H
|
||||
return inputMap;
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleFlowOutcome(String flowId, String outcome, AttributeMap endedOutput,
|
||||
protected ModelAndView defaultHandleFlowOutcome(String flowId, FlowExecutionOutcome outcome,
|
||||
HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
if (!response.isCommitted()) {
|
||||
// by default, just start the flow over passing the output as input
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Restarting a new execution of ended flow '" + flowId + "'");
|
||||
}
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, endedOutput, request));
|
||||
response.sendRedirect(urlHandler.createFlowDefinitionUrl(flowId, outcome.getOutput(), request));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -225,10 +226,9 @@ public class FlowHandlerAdapter extends WebApplicationObjectSupport implements H
|
||||
sendRedirect(context, request, response, context.getExternalRedirectUrl());
|
||||
return null;
|
||||
} else {
|
||||
String location = handler.handleExecutionOutcome(result.getEndedOutcome(), result.getEndedOutput(),
|
||||
request, response);
|
||||
String location = handler.handleExecutionOutcome(result.getOutcome(), request, response);
|
||||
return location != null ? createRedirectView(location, request) : defaultHandleFlowOutcome(result
|
||||
.getFlowId(), result.getEndedOutcome(), result.getEndedOutput(), request, response);
|
||||
.getFlowId(), result.getOutcome(), request, response);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Execution result should have been one of [paused] or [ended]");
|
||||
|
||||
@@ -131,7 +131,7 @@ public class HibernateFlowExecutionListener extends FlowExecutionListenerAdapter
|
||||
}
|
||||
}
|
||||
|
||||
public void sessionEnded(RequestContext context, FlowSession session, AttributeMap output) {
|
||||
public void sessionEnded(RequestContext context, FlowSession session, String outcome, AttributeMap output) {
|
||||
if (isPersistenceContext(session.getDefinition())) {
|
||||
final Session hibernateSession = (Session) session.getScope().remove(HIBERNATE_SESSION_ATTRIBUTE);
|
||||
Boolean commitStatus = session.getState().getAttributes().getBoolean("commit");
|
||||
|
||||
@@ -119,7 +119,7 @@ public class JpaFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public void sessionEnded(RequestContext context, FlowSession session, AttributeMap output) {
|
||||
public void sessionEnded(RequestContext context, FlowSession session, String outcome, AttributeMap output) {
|
||||
if (isPersistenceContext(session.getDefinition())) {
|
||||
final EntityManager em = (EntityManager) session.getScope().remove(ENTITY_MANAGER_ATTRIBUTE);
|
||||
Boolean commitStatus = session.getState().getAttributes().getBoolean("commit");
|
||||
|
||||
@@ -42,11 +42,24 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
*/
|
||||
public class SecurityFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
|
||||
AccessDecisionManager accessDecisionManager;
|
||||
private AccessDecisionManager accessDecisionManager;
|
||||
|
||||
/**
|
||||
* Check security authorization when flow session starts
|
||||
* Get the access decision manager that makes flow authorization decisions.
|
||||
* @return the decision manager
|
||||
*/
|
||||
public AccessDecisionManager getAccessDecisionManager() {
|
||||
return accessDecisionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the access decision manager that makes flow authorization decisions.
|
||||
* @param accessDecisionManager the decision manager to user
|
||||
*/
|
||||
public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
|
||||
this.accessDecisionManager = accessDecisionManager;
|
||||
}
|
||||
|
||||
public void sessionCreating(RequestContext context, FlowDefinition definition) {
|
||||
SecurityRule rule = (SecurityRule) definition.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
if (rule != null) {
|
||||
@@ -54,9 +67,6 @@ public class SecurityFlowExecutionListener extends FlowExecutionListenerAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check security authorization when entering state
|
||||
*/
|
||||
public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException {
|
||||
SecurityRule rule = (SecurityRule) state.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
if (rule != null) {
|
||||
@@ -64,9 +74,6 @@ public class SecurityFlowExecutionListener extends FlowExecutionListenerAdapter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check security authorization on transition
|
||||
*/
|
||||
public void transitionExecuting(RequestContext context, TransitionDefinition transition) {
|
||||
SecurityRule rule = (SecurityRule) transition.getAttributes().get(SecurityRule.SECURITY_ATTRIBUTE_NAME);
|
||||
if (rule != null) {
|
||||
@@ -81,7 +88,7 @@ public class SecurityFlowExecutionListener extends FlowExecutionListenerAdapter
|
||||
* @param rule the rule to base the decision
|
||||
* @param object the execution listener phase
|
||||
*/
|
||||
public void decide(SecurityRule rule, Object object) {
|
||||
protected void decide(SecurityRule rule, Object object) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
ConfigAttributeDefinition config = new ConfigAttributeDefinition(getConfigAttributes(rule));
|
||||
if (accessDecisionManager != null) {
|
||||
@@ -115,21 +122,4 @@ public class SecurityFlowExecutionListener extends FlowExecutionListenerAdapter
|
||||
}
|
||||
return configAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get decision manager
|
||||
* @return the decision manager
|
||||
*/
|
||||
public AccessDecisionManager getAccessDecisionManager() {
|
||||
return accessDecisionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set decision manager
|
||||
* @param accessDecisionManager the decision manager to user
|
||||
*/
|
||||
public void setAccessDecisionManager(AccessDecisionManager accessDecisionManager) {
|
||||
this.accessDecisionManager = accessDecisionManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionContext;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
|
||||
/**
|
||||
@@ -34,6 +34,8 @@ import org.springframework.webflow.execution.FlowSession;
|
||||
*/
|
||||
public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
|
||||
private boolean started;
|
||||
|
||||
private FlowExecutionKey key;
|
||||
|
||||
private FlowDefinition flow;
|
||||
@@ -46,14 +48,14 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
|
||||
private MutableAttributeMap attributes = new LocalAttributeMap();
|
||||
|
||||
private Event outcome;
|
||||
private FlowExecutionOutcome outcome;
|
||||
|
||||
/**
|
||||
* Creates a new mock flow execution context -- automatically installs a root flow definition and active flow
|
||||
* session.
|
||||
*/
|
||||
public MockFlowExecutionContext() {
|
||||
activeSession = new MockFlowSession();
|
||||
setActiveSession(new MockFlowSession());
|
||||
this.flow = activeSession.getDefinition();
|
||||
}
|
||||
|
||||
@@ -68,8 +70,8 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
* Creates a new mock flow execution context for the specified active flow session.
|
||||
*/
|
||||
public MockFlowExecutionContext(FlowSession flowSession) {
|
||||
setActiveSession(flowSession);
|
||||
this.flow = flowSession.getDefinition();
|
||||
this.activeSession = flowSession;
|
||||
}
|
||||
|
||||
public FlowExecutionKey getKey() {
|
||||
@@ -87,7 +89,7 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
}
|
||||
|
||||
public boolean hasStarted() {
|
||||
return isActive();
|
||||
return started;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
@@ -117,7 +119,7 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public Event getOutcome() {
|
||||
public FlowExecutionOutcome getOutcome() {
|
||||
return outcome;
|
||||
}
|
||||
|
||||
@@ -148,6 +150,9 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
*/
|
||||
public void setActiveSession(FlowSession activeSession) {
|
||||
this.activeSession = activeSession;
|
||||
if (!started && activeSession != null) {
|
||||
started = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,9 +171,9 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
|
||||
|
||||
/**
|
||||
* Sets the result of this flow ending.
|
||||
* @param outcome the ending outcome event.
|
||||
* @param outcome the ended outcome
|
||||
*/
|
||||
public void setOutcome(Event outcome) {
|
||||
public void setOutcome(FlowExecutionOutcome outcome) {
|
||||
this.outcome = outcome;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.webflow.engine.TransitionableState;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionContext;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
@@ -113,11 +112,13 @@ public class MockRequestControlContext extends MockRequestContext implements Req
|
||||
flow.start(this, input);
|
||||
}
|
||||
|
||||
public FlowSession endActiveFlowSession(MutableAttributeMap output) throws IllegalStateException {
|
||||
public void endActiveFlowSession(String outcome, MutableAttributeMap output) throws IllegalStateException {
|
||||
MockFlowSession endingSession = getMockFlowExecutionContext().getMockActiveSession();
|
||||
endingSession.getDefinitionInternal().end(this, output);
|
||||
endingSession.getDefinitionInternal().end(this, outcome, output);
|
||||
getMockFlowExecutionContext().setActiveSession(endingSession.getParent());
|
||||
return endingSession;
|
||||
if (!getMockFlowExecutionContext().hasEnded()) {
|
||||
handleEvent(new Event(endingSession.getState(), outcome, output));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getAlwaysRedirectOnPause() {
|
||||
|
||||
@@ -23,10 +23,10 @@ import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImpl;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
|
||||
/**
|
||||
@@ -70,7 +70,7 @@ public abstract class AbstractFlowExecutionTests extends TestCase {
|
||||
/**
|
||||
* The outcome that was reached when the flow ends; initially null.
|
||||
*/
|
||||
private Event flowExecutionOutcome;
|
||||
private FlowExecutionOutcome flowExecutionOutcome;
|
||||
|
||||
/**
|
||||
* Constructs a default flow execution test.
|
||||
@@ -168,7 +168,7 @@ public abstract class AbstractFlowExecutionTests extends TestCase {
|
||||
* Returns the flow execution outcome that was reached.
|
||||
* @return the flow execution outcome, or null if the flow execution has not ended
|
||||
*/
|
||||
protected Event getFlowExecutionOutcome() {
|
||||
protected FlowExecutionOutcome getFlowExecutionOutcome() {
|
||||
return flowExecutionOutcome;
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,10 @@ public class FlowDefinitionRegistryImplTests extends TestCase {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getPossibleOutcomes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return null;
|
||||
}
|
||||
@@ -143,6 +147,10 @@ public class FlowDefinitionRegistryImplTests extends TestCase {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getPossibleOutcomes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -144,6 +144,14 @@ public class FlowTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetPossibleOutcomes() {
|
||||
Flow flow = new Flow("myFlow");
|
||||
new EndState(flow, "myState1");
|
||||
new EndState(flow, "myState2");
|
||||
assertEquals("myState1", flow.getPossibleOutcomes()[0]);
|
||||
assertEquals("myState2", flow.getPossibleOutcomes()[1]);
|
||||
}
|
||||
|
||||
public void testAddActions() {
|
||||
flow.getStartActionList().add(new TestMultiAction());
|
||||
flow.getStartActionList().add(new TestMultiAction());
|
||||
@@ -299,7 +307,7 @@ public class FlowTests extends TestCase {
|
||||
flow.getEndActionList().add(action);
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
LocalAttributeMap sessionOutput = new LocalAttributeMap();
|
||||
flow.end(context, sessionOutput);
|
||||
flow.end(context, "finish", sessionOutput);
|
||||
assertEquals(1, action.getExecutionCount());
|
||||
}
|
||||
|
||||
@@ -314,7 +322,7 @@ public class FlowTests extends TestCase {
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
context.getFlowScope().put("attr", "foo");
|
||||
LocalAttributeMap sessionOutput = new LocalAttributeMap();
|
||||
flow.end(context, sessionOutput);
|
||||
flow.end(context, "finish", sessionOutput);
|
||||
assertEquals("foo", sessionOutput.get("attr"));
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
|
||||
import org.springframework.webflow.engine.support.ActionExecutingViewFactory;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.security.SecurityRule;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
@@ -137,14 +137,14 @@ public class FlowModelFlowBuilderTests extends TestCase {
|
||||
map.put("number", "3");
|
||||
map.put("required", "9");
|
||||
execution.start(map, context);
|
||||
Event outcome = execution.getOutcome();
|
||||
FlowExecutionOutcome outcome = execution.getOutcome();
|
||||
assertEquals("end", outcome.getId());
|
||||
assertEquals("bar", outcome.getAttributes().get("foo"));
|
||||
assertEquals("bar", outcome.getAttributes().get("differentName"));
|
||||
assertEquals(new Integer(3), outcome.getAttributes().get("number"));
|
||||
assertEquals(new Integer(3), outcome.getAttributes().get("required"));
|
||||
assertEquals("a literal", outcome.getAttributes().get("literal"));
|
||||
assertNull(outcome.getAttributes().get("notReached"));
|
||||
assertEquals("bar", outcome.getOutput().get("foo"));
|
||||
assertEquals("bar", outcome.getOutput().get("differentName"));
|
||||
assertEquals(new Integer(3), outcome.getOutput().get("number"));
|
||||
assertEquals(new Integer(3), outcome.getOutput().get("required"));
|
||||
assertEquals("a literal", outcome.getOutput().get("literal"));
|
||||
assertNull(outcome.getOutput().get("notReached"));
|
||||
}
|
||||
|
||||
public void testFlowRequiredInputMapping() {
|
||||
|
||||
@@ -273,13 +273,13 @@ public class MockFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
resumingCount++;
|
||||
}
|
||||
|
||||
public void sessionEnding(RequestContext context, FlowSession session, MutableAttributeMap output) {
|
||||
public void sessionEnding(RequestContext context, FlowSession session, String outcome, MutableAttributeMap output) {
|
||||
sessionEnding = true;
|
||||
sessionEndingCount++;
|
||||
flowNestingLevel--;
|
||||
}
|
||||
|
||||
public void sessionEnded(RequestContext context, FlowSession session, AttributeMap output) {
|
||||
public void sessionEnded(RequestContext context, FlowSession session, String outcome, AttributeMap output) {
|
||||
assertStarted();
|
||||
Assert.state(sessionEnding, "Should have been ending");
|
||||
sessionEnding = false;
|
||||
|
||||
@@ -8,10 +8,10 @@ import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.FlowExecutionLock;
|
||||
import org.springframework.webflow.execution.repository.FlowExecutionRepository;
|
||||
import org.springframework.webflow.test.GeneratedFlowExecutionKey;
|
||||
@@ -65,8 +65,7 @@ public class FlowExecutorImplTests extends TestCase {
|
||||
assertTrue(result.paused());
|
||||
assertEquals("12345", result.getPausedKey());
|
||||
assertFalse(result.ended());
|
||||
assertNull(result.getEndedOutcome());
|
||||
assertNull(result.getEndedOutput());
|
||||
assertNull(result.getOutcome());
|
||||
assertNull(ExternalContextHolder.getExternalContext());
|
||||
verifyMocks();
|
||||
}
|
||||
@@ -86,14 +85,14 @@ public class FlowExecutorImplTests extends TestCase {
|
||||
|
||||
EasyMock.expect(execution.getDefinition()).andReturn(definition);
|
||||
EasyMock.expect(definition.getId()).andReturn("foo");
|
||||
EasyMock.expect(execution.getOutcome()).andReturn(new Event(execution, "finish", null));
|
||||
EasyMock.expect(execution.getOutcome()).andReturn(new FlowExecutionOutcome("finish", null));
|
||||
|
||||
replayMocks();
|
||||
|
||||
FlowExecutionResult result = flowExecutor.launchExecution("foo", null, context);
|
||||
assertTrue(result.ended());
|
||||
assertEquals("finish", result.getEndedOutcome());
|
||||
assertTrue(result.getEndedOutput().isEmpty());
|
||||
assertEquals("finish", result.getOutcome().getId());
|
||||
assertTrue(result.getOutcome().getOutput().isEmpty());
|
||||
assertFalse(result.paused());
|
||||
assertNull(result.getPausedKey());
|
||||
assertNull(ExternalContextHolder.getExternalContext());
|
||||
@@ -131,8 +130,7 @@ public class FlowExecutorImplTests extends TestCase {
|
||||
assertTrue(result.paused());
|
||||
assertEquals("12345", result.getPausedKey());
|
||||
assertFalse(result.ended());
|
||||
assertNull(result.getEndedOutcome());
|
||||
assertNull(result.getEndedOutput());
|
||||
assertNull(result.getOutcome());
|
||||
assertNull(ExternalContextHolder.getExternalContext());
|
||||
verifyMocks();
|
||||
|
||||
@@ -159,7 +157,7 @@ public class FlowExecutorImplTests extends TestCase {
|
||||
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("foo", "bar");
|
||||
EasyMock.expect(execution.getOutcome()).andReturn(new Event(execution, "finish", output));
|
||||
EasyMock.expect(execution.getOutcome()).andReturn(new FlowExecutionOutcome("finish", output));
|
||||
|
||||
repository.removeFlowExecution(execution);
|
||||
|
||||
@@ -169,8 +167,8 @@ public class FlowExecutorImplTests extends TestCase {
|
||||
|
||||
FlowExecutionResult result = flowExecutor.resumeExecution(flowExecutionKey, context);
|
||||
assertTrue(result.ended());
|
||||
assertEquals("finish", result.getEndedOutcome());
|
||||
assertEquals(output, result.getEndedOutput());
|
||||
assertEquals("finish", result.getOutcome().getId());
|
||||
assertEquals(output, result.getOutcome().getOutput());
|
||||
assertFalse(result.paused());
|
||||
assertNull(result.getPausedKey());
|
||||
assertNull(ExternalContextHolder.getExternalContext());
|
||||
|
||||
@@ -20,10 +20,9 @@ import org.springframework.web.portlet.ModelAndView;
|
||||
import org.springframework.webflow.context.portlet.DefaultFlowUrlHandler;
|
||||
import org.springframework.webflow.context.portlet.PortletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
@@ -85,8 +84,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public String handleFlowOutcome(String outcome, AttributeMap output, RenderRequest request,
|
||||
RenderResponse response) {
|
||||
public String handleFlowOutcome(FlowExecutionOutcome outcome, RenderRequest request, RenderResponse response) {
|
||||
if (handleExecutionOutcome) {
|
||||
return "home";
|
||||
} else {
|
||||
@@ -174,7 +172,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
renderRequest.setContextPath("/springtravel");
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
PortletSession session = renderRequest.getPortletSession();
|
||||
session.setAttribute("flowExecutionResult", result);
|
||||
|
||||
@@ -16,10 +16,9 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.webflow.context.servlet.ServletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
@@ -77,7 +76,7 @@ public class FlowControllerTests extends TestCase {
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -117,7 +116,7 @@ public class FlowControllerTests extends TestCase {
|
||||
executor.resumeExecution("12345", context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -207,7 +206,7 @@ public class FlowControllerTests extends TestCase {
|
||||
executor.launchExecution("foo", new LocalAttributeMap(parameters), context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -289,7 +288,7 @@ public class FlowControllerTests extends TestCase {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
@@ -324,10 +323,10 @@ public class FlowControllerTests extends TestCase {
|
||||
return input;
|
||||
}
|
||||
|
||||
public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
assertEquals("finish", outcome);
|
||||
assertEquals("baz", output.get("bar"));
|
||||
assertEquals("finish", outcome.getId());
|
||||
assertEquals("baz", outcome.getOutput().get("bar"));
|
||||
assertEquals(FlowControllerTests.this.request, request);
|
||||
assertEquals(FlowControllerTests.this.response, response);
|
||||
return null;
|
||||
@@ -345,7 +344,7 @@ public class FlowControllerTests extends TestCase {
|
||||
executor.launchExecution("foo", input, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -368,7 +367,7 @@ public class FlowControllerTests extends TestCase {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,9 @@ import org.springframework.web.context.support.StaticWebApplicationContext;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.webflow.context.servlet.ServletExternalContext;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
|
||||
import org.springframework.webflow.executor.FlowExecutionResult;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
@@ -61,7 +60,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public String handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request,
|
||||
public String handleExecutionOutcome(FlowExecutionOutcome outcome, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
if (handleExecutionOutcome) {
|
||||
return "/home";
|
||||
@@ -107,7 +106,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
executor.launchExecution("foo", flowInput, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -147,7 +146,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
executor.resumeExecution("12345", context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -191,7 +190,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
executor.launchExecution("foo", flowInput, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
@@ -271,7 +270,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
executor.launchExecution("foo", flowInput, context);
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
Event outcome = new Event(this, "finish", output);
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
EasyMock.expectLastCall().andReturn(result);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
|
||||
@@ -118,7 +118,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
|
||||
endState.getAttributes().put("commit", Boolean.TRUE);
|
||||
flowSession.setState(endState);
|
||||
|
||||
hibernateListener.sessionEnded(context, flowSession, null);
|
||||
hibernateListener.sessionEnded(context, flowSession, "success", null);
|
||||
assertEquals("Table should only have two rows", 2, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertSessionNotBound();
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
@@ -149,7 +149,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
|
||||
endState.getAttributes().put("commit", Boolean.TRUE);
|
||||
flowSession.setState(endState);
|
||||
|
||||
hibernateListener.sessionEnded(context, flowSession, null);
|
||||
hibernateListener.sessionEnded(context, flowSession, "success", null);
|
||||
assertEquals("Table should only have three rows", 3, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
|
||||
@@ -174,7 +174,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
|
||||
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
|
||||
endState.getAttributes().put("commit", Boolean.FALSE);
|
||||
flowSession.setState(endState);
|
||||
hibernateListener.sessionEnded(context, flowSession, null);
|
||||
hibernateListener.sessionEnded(context, flowSession, "cancel", null);
|
||||
assertEquals("Table should only have two rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertSessionNotBound();
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
@@ -192,7 +192,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
|
||||
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
|
||||
flowSession.setState(endState);
|
||||
|
||||
hibernateListener.sessionEnded(context, flowSession, null);
|
||||
hibernateListener.sessionEnded(context, flowSession, "cancel", null);
|
||||
assertEquals("Table should only have three rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
|
||||
endState.getAttributes().put("commit", Boolean.TRUE);
|
||||
flowSession.setState(endState);
|
||||
|
||||
jpaListener.sessionEnded(context, flowSession, null);
|
||||
jpaListener.sessionEnded(context, flowSession, "success", null);
|
||||
assertEquals("Table should only have two rows", 2, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertSessionNotBound();
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
@@ -99,7 +99,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
|
||||
endState.getAttributes().put("commit", Boolean.TRUE);
|
||||
flowSession.setState(endState);
|
||||
|
||||
jpaListener.sessionEnded(context, flowSession, null);
|
||||
jpaListener.sessionEnded(context, flowSession, "success", null);
|
||||
assertEquals("Table should only have three rows", 3, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
|
||||
@@ -123,7 +123,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
|
||||
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
|
||||
endState.getAttributes().put("commit", Boolean.FALSE);
|
||||
flowSession.setState(endState);
|
||||
jpaListener.sessionEnded(context, flowSession, null);
|
||||
jpaListener.sessionEnded(context, flowSession, "cancel", null);
|
||||
assertEquals("Table should only have two rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertSessionNotBound();
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
@@ -141,7 +141,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
|
||||
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
|
||||
flowSession.setState(endState);
|
||||
|
||||
jpaListener.sessionEnded(context, flowSession, null);
|
||||
jpaListener.sessionEnded(context, flowSession, "cancel", null);
|
||||
assertEquals("Table should only have three rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
|
||||
assertFalse(flowSession.getScope().contains("hibernate.session"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user