OPEN - issue SWF-487: Add transitionExecuting flow execution listener hook.

http://jira.springframework.org/browse/SWF-487
This commit is contained in:
Scott Andrews
2008-02-28 18:30:11 +00:00
parent 1961f26b39
commit 295f608663
6 changed files with 70 additions and 2 deletions

View File

@@ -350,6 +350,7 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
}
void execute(Transition transition, RequestControlContext context) {
listeners.fireTransitionExecuting(context, transition);
transition.execute(getCurrentState(), context);
}

View File

@@ -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.
*/

View File

@@ -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

View File

@@ -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 {
}

View File

@@ -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()) {

View File

@@ -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;