OPEN - issue SWF-487: Add transitionExecuting flow execution listener hook.
http://jira.springframework.org/browse/SWF-487
This commit is contained in:
@@ -350,6 +350,7 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
|
||||
}
|
||||
|
||||
void execute(Transition transition, RequestControlContext context) {
|
||||
listeners.fireTransitionExecuting(context, transition);
|
||||
transition.execute(getCurrentState(), context);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionListener;
|
||||
@@ -32,6 +33,7 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
class FlowExecutionListeners {
|
||||
|
||||
@@ -151,6 +153,15 @@ class FlowExecutionListeners {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all interested listeners that a transition is being entered in the flow execution.
|
||||
*/
|
||||
public void fireTransitionExecuting(RequestContext context, TransitionDefinition transition) {
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].transitionExecuting(context, transition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all interested listeners that a flow session was paused in the flow execution.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
|
||||
|
||||
/**
|
||||
@@ -46,6 +47,7 @@ import org.springframework.webflow.engine.FlowExecutionExceptionHandler;
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public interface FlowExecutionListener {
|
||||
|
||||
@@ -92,10 +94,17 @@ public interface FlowExecutionListener {
|
||||
/**
|
||||
* Called when an event is signaled in the current state, but prior to any state transition.
|
||||
* @param context the source of the event
|
||||
* @param event the event that occured
|
||||
* @param event the event that occurred
|
||||
*/
|
||||
public void eventSignaled(RequestContext context, Event event);
|
||||
|
||||
/**
|
||||
* Called when a transition is matched but before the transition occurs.
|
||||
* @param context the source of the event
|
||||
* @param transition the proposed transition
|
||||
*/
|
||||
public void transitionExecuting(RequestContext context, TransitionDefinition transition);
|
||||
|
||||
/**
|
||||
* Called when a state transitions, after the transition is matched but before the transition occurs.
|
||||
* @param context the source of the event
|
||||
@@ -105,7 +114,7 @@ public interface FlowExecutionListener {
|
||||
public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException;
|
||||
|
||||
/**
|
||||
* Called when a state transitions, after the transition occured.
|
||||
* Called when a state transitions, after the transition occurred.
|
||||
* @param context the source of the event
|
||||
* @param previousState <i>from</i> state of the transition
|
||||
* @param state <i>to</i> state of the transition
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
|
||||
/**
|
||||
* An abstract adapter class for listeners (observers) of flow execution lifecycle events. The methods in this class are
|
||||
@@ -26,6 +27,7 @@ import org.springframework.webflow.definition.StateDefinition;
|
||||
*
|
||||
* @author Erwin Vervaet
|
||||
* @author Keith Donald
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public abstract class FlowExecutionListenerAdapter implements FlowExecutionListener {
|
||||
|
||||
@@ -47,6 +49,9 @@ public abstract class FlowExecutionListenerAdapter implements FlowExecutionListe
|
||||
public void eventSignaled(RequestContext context, Event event) {
|
||||
}
|
||||
|
||||
public void transitionExecuting(RequestContext context, TransitionDefinition transition) {
|
||||
}
|
||||
|
||||
public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException {
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@ import org.springframework.webflow.engine.Flow;
|
||||
import org.springframework.webflow.engine.RequestControlContext;
|
||||
import org.springframework.webflow.engine.State;
|
||||
import org.springframework.webflow.engine.StubViewFactory;
|
||||
import org.springframework.webflow.engine.Transition;
|
||||
import org.springframework.webflow.engine.ViewState;
|
||||
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionKey;
|
||||
@@ -72,6 +74,7 @@ public class FlowExecutionImplTests extends TestCase {
|
||||
assertEquals(1, mockListener.getSessionEndingCount());
|
||||
assertEquals(1, mockListener.getSessionEndedCount());
|
||||
assertEquals(0, mockListener.getEventSignaledCount());
|
||||
assertEquals(0, mockListener.getTransitionExecutingCount());
|
||||
assertEquals(0, mockListener.getPausedCount());
|
||||
assertEquals(0, mockListener.getResumingCount());
|
||||
assertEquals(0, mockListener.getExceptionThrownCount());
|
||||
@@ -282,6 +285,29 @@ public class FlowExecutionImplTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testExecuteTransition() {
|
||||
Flow flow = new Flow("flow");
|
||||
ViewState state = new ViewState(flow, "view", new StubViewFactory()) {
|
||||
public void resume(RequestControlContext context) {
|
||||
context.execute(getRequiredTransition(context));
|
||||
}
|
||||
};
|
||||
state.getTransitionSet().add(new Transition(new DefaultTargetStateResolver("finish")));
|
||||
EndState end = new EndState(flow, "finish");
|
||||
MockFlowExecutionListener mockListener = new MockFlowExecutionListener();
|
||||
FlowExecutionListener[] listeners = new FlowExecutionListener[] { mockListener };
|
||||
FlowExecutionImpl execution = new FlowExecutionImpl(flow);
|
||||
execution.setListeners(listeners);
|
||||
execution.setMessageContextFactory(new DefaultMessageContextFactory(new StaticMessageSource()));
|
||||
execution.setKeyFactory(new MockFlowExecutionKeyFactory());
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
execution.start(null, context);
|
||||
assertEquals(0, mockListener.getTransitionExecutingCount());
|
||||
execution.resume(context);
|
||||
assertTrue(execution.hasEnded());
|
||||
assertEquals(1, mockListener.getTransitionExecutingCount());
|
||||
}
|
||||
|
||||
public void testRequestContextManagedOnStartAndResume() {
|
||||
Flow flow = new Flow("flow");
|
||||
new ViewState(flow, "view", new StubViewFactory()) {
|
||||
|
||||
@@ -20,12 +20,14 @@ import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
import org.springframework.webflow.definition.TransitionDefinition;
|
||||
|
||||
/**
|
||||
* Mock implementation of the <code>FlowExecutionListener</code> interface for use in unit tests.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
* @author Scott Andrews
|
||||
*/
|
||||
public class MockFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
|
||||
@@ -45,6 +47,8 @@ public class MockFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
|
||||
private int stateEnteredCount;
|
||||
|
||||
private int transitionExecutingCount;
|
||||
|
||||
private int resumingCount;
|
||||
|
||||
private boolean paused;
|
||||
@@ -157,6 +161,13 @@ public class MockFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
return stateEnteredCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of transitions entered so far.
|
||||
*/
|
||||
public int getTransitionExecutingCount() {
|
||||
return transitionExecutingCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of events signaled so far.
|
||||
*/
|
||||
@@ -246,6 +257,10 @@ public class MockFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
stateEnteredCount++;
|
||||
}
|
||||
|
||||
public void transitionExecuting(RequestContext context, TransitionDefinition transition) {
|
||||
transitionExecutingCount++;
|
||||
}
|
||||
|
||||
public void paused(RequestContext context) {
|
||||
executing = false;
|
||||
paused = true;
|
||||
@@ -302,6 +317,7 @@ public class MockFlowExecutionListener extends FlowExecutionListenerAdapter {
|
||||
sessionStartedCount = 0;
|
||||
stateEnteringCount = 0;
|
||||
stateEnteredCount = 0;
|
||||
transitionExecutingCount = 0;
|
||||
eventSignaledCount = 0;
|
||||
pausedCount = 0;
|
||||
resumingCount = 0;
|
||||
|
||||
Reference in New Issue
Block a user