view rendering listener hooks
This commit is contained in:
@@ -22,6 +22,7 @@ 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;
|
||||
|
||||
/**
|
||||
* Mutable control interface used to manipulate an ongoing flow execution in the context of one client request.
|
||||
@@ -60,19 +61,16 @@ public interface RequestControlContext extends RequestContext {
|
||||
public FlowExecutionKey assignFlowExecutionKey();
|
||||
|
||||
/**
|
||||
* Update the current flow execution snapshot to save the current state.
|
||||
* Called when a view is about to be rendered in the current view state.
|
||||
* @param view the view to be rendered
|
||||
*/
|
||||
public void updateCurrentFlowExecutionSnapshot();
|
||||
public void viewRendering(View view);
|
||||
|
||||
/**
|
||||
* Remove the current flow execution snapshot to invalidate the current state.
|
||||
* Called when a view has completed rendering in the current view state.
|
||||
* @param view the view that rendered
|
||||
*/
|
||||
public void removeCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove all flow execution snapshots associated with the ongoing conversation. Invalidates previous states.
|
||||
*/
|
||||
public void removeAllFlowExecutionSnapshots();
|
||||
public void viewRendered(View view);
|
||||
|
||||
/**
|
||||
* Signals the occurrence of an event in the current state of this flow execution request context. This method
|
||||
@@ -102,6 +100,21 @@ public interface RequestControlContext extends RequestContext {
|
||||
*/
|
||||
public void setCurrentTransition(Transition transition);
|
||||
|
||||
/**
|
||||
* Update the current flow execution snapshot to save the current state.
|
||||
*/
|
||||
public void updateCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove the current flow execution snapshot to invalidate the current state.
|
||||
*/
|
||||
public void removeCurrentFlowExecutionSnapshot();
|
||||
|
||||
/**
|
||||
* Remove all flow execution snapshots associated with the ongoing conversation. Invalidates previous states.
|
||||
*/
|
||||
public void removeAllFlowExecutionSnapshots();
|
||||
|
||||
/**
|
||||
* Spawn a new flow session and activate it in the currently executing flow. Also transitions the spawned flow to
|
||||
* its start state. This method should be called by clients that wish to spawn new flows, such as subflow states.
|
||||
|
||||
@@ -263,6 +263,7 @@ public class ViewState extends TransitionableState {
|
||||
logger.debug(" Flash scope = " + context.getFlashScope());
|
||||
logger.debug(" Messages = " + context.getMessageContext());
|
||||
}
|
||||
context.viewRendering(view);
|
||||
renderActionList.execute(context);
|
||||
try {
|
||||
view.render();
|
||||
@@ -271,6 +272,7 @@ public class ViewState extends TransitionableState {
|
||||
}
|
||||
context.getMessageContext().clearMessages();
|
||||
context.getFlashScope().clear();
|
||||
context.viewRendered(view);
|
||||
}
|
||||
|
||||
private void restoreVariables(RequestContext context) {
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.springframework.webflow.execution.FlowExecutionListener;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.RequestContextHolder;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
* Default implementation of FlowExecution that uses a stack-based data structure to manage spawned flow sessions. This
|
||||
@@ -368,6 +369,14 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
|
||||
listeners.fireStateEntered(context, previousState);
|
||||
}
|
||||
|
||||
public void viewRendering(View view, RequestContext context) {
|
||||
listeners.fireViewRendering(context, view);
|
||||
}
|
||||
|
||||
public void viewRendered(View view, RequestContext context) {
|
||||
listeners.fireViewRendered(context, view);
|
||||
}
|
||||
|
||||
boolean handleEvent(Event event, RequestControlContext context) {
|
||||
listeners.fireEventSignaled(context, event);
|
||||
return getActiveSessionInternal().getFlow().handleEvent(context);
|
||||
@@ -637,4 +646,5 @@ public class FlowExecutionImpl implements FlowExecution, Externalizable {
|
||||
State currentState = (State) session.getState();
|
||||
return currentState;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionListener;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.View;
|
||||
|
||||
/**
|
||||
* A helper that aids in publishing events to an array of <code>FlowExecutionListener</code> objects.
|
||||
@@ -153,6 +154,24 @@ class FlowExecutionListeners {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all interested listeners that a flow execution view is rendering.
|
||||
*/
|
||||
public void fireViewRendering(RequestContext context, View view) {
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].viewRendering(context, view, context.getCurrentState());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all interested listeners that a flow execution has rendered.
|
||||
*/
|
||||
public void fireViewRendered(RequestContext context, View view) {
|
||||
for (int i = 0; i < listeners.length; i++) {
|
||||
listeners[i].viewRendered(context, view, context.getCurrentState());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all interested listeners that a transition is being entered in the flow execution.
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ 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;
|
||||
|
||||
/**
|
||||
* Default request control context implementation used internally by the web flow system. This class is closely coupled
|
||||
@@ -187,14 +188,31 @@ class RequestControlContextImpl implements RequestControlContext {
|
||||
flowExecution.setCurrentState(state, this);
|
||||
}
|
||||
|
||||
public void setCurrentTransition(Transition transition) {
|
||||
this.currentTransition = transition;
|
||||
}
|
||||
|
||||
public FlowExecutionKey assignFlowExecutionKey() {
|
||||
return flowExecution.assignKey();
|
||||
}
|
||||
|
||||
public void viewRendering(View view) {
|
||||
flowExecution.viewRendering(view, this);
|
||||
}
|
||||
|
||||
public void viewRendered(View view) {
|
||||
flowExecution.viewRendered(view, this);
|
||||
}
|
||||
|
||||
public boolean handleEvent(Event event) throws FlowExecutionException {
|
||||
this.currentEvent = event;
|
||||
return flowExecution.handleEvent(event, this);
|
||||
}
|
||||
|
||||
public boolean execute(Transition transition) {
|
||||
return flowExecution.execute(transition, this);
|
||||
}
|
||||
|
||||
public void setCurrentTransition(Transition transition) {
|
||||
this.currentTransition = transition;
|
||||
}
|
||||
|
||||
public void updateCurrentFlowExecutionSnapshot() {
|
||||
flowExecution.updateCurrentFlowExecutionSnapshot();
|
||||
}
|
||||
@@ -207,20 +225,6 @@ class RequestControlContextImpl implements RequestControlContext {
|
||||
flowExecution.removeAllFlowExecutionSnapshots();
|
||||
}
|
||||
|
||||
public boolean getAlwaysRedirectOnPause() {
|
||||
Boolean redirectOnPause = flowExecution.getAttributes().getBoolean("alwaysRedirectOnPause");
|
||||
return redirectOnPause != null ? redirectOnPause.booleanValue() : false;
|
||||
}
|
||||
|
||||
public boolean handleEvent(Event event) throws FlowExecutionException {
|
||||
this.currentEvent = event;
|
||||
return flowExecution.handleEvent(event, this);
|
||||
}
|
||||
|
||||
public boolean execute(Transition transition) {
|
||||
return flowExecution.execute(transition, this);
|
||||
}
|
||||
|
||||
public void start(Flow flow, MutableAttributeMap input) throws FlowExecutionException {
|
||||
flowExecution.start(flow, input, this);
|
||||
}
|
||||
@@ -229,6 +233,11 @@ class RequestControlContextImpl implements RequestControlContext {
|
||||
return flowExecution.endActiveFlowSession(output, this);
|
||||
}
|
||||
|
||||
public boolean getAlwaysRedirectOnPause() {
|
||||
Boolean redirectOnPause = flowExecution.getAttributes().getBoolean("alwaysRedirectOnPause");
|
||||
return redirectOnPause != null ? redirectOnPause.booleanValue() : false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("externalContext", externalContext)
|
||||
.append("requestScope", requestScope).append("attributes", attributes).append("flowExecution",
|
||||
|
||||
@@ -54,7 +54,7 @@ public interface FlowExecutionListener {
|
||||
/**
|
||||
* Called when any client request is submitted to manipulate this flow execution. This call happens before request
|
||||
* processing.
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
*/
|
||||
public void requestSubmitted(RequestContext context);
|
||||
|
||||
@@ -68,7 +68,7 @@ public interface FlowExecutionListener {
|
||||
* Called to indicate a new flow definition session is about to be created. Called before the session is created. An
|
||||
* exception may be thrown from this method to veto the start operation. Any type of runtime exception can be used
|
||||
* for this purpose.
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
* @param definition the flow for which a new session is starting
|
||||
*/
|
||||
public void sessionCreating(RequestContext context, FlowDefinition definition);
|
||||
@@ -76,7 +76,7 @@ public interface FlowExecutionListener {
|
||||
/**
|
||||
* Called after a new flow session has been created but before it starts. Useful for setting arbitrary attributes in
|
||||
* the session before the flow starts.
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
* @param session the session that was created
|
||||
* @param input a mutable input map - attributes placed in this map are eligible for input mapping by the flow
|
||||
* definition at startup
|
||||
@@ -86,36 +86,44 @@ public interface FlowExecutionListener {
|
||||
/**
|
||||
* Called after a new flow session has started. At this point the flow's start state has been entered and any other
|
||||
* startup behaviors have been executed.
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
* @param session the session that was started
|
||||
*/
|
||||
public void sessionStarted(RequestContext context, FlowSession session);
|
||||
|
||||
/**
|
||||
* Called when an event is signaled in the current state, but prior to any state transition.
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
* @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 context the current flow request context
|
||||
* @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
|
||||
* @param context the current flow request context
|
||||
* @param state the proposed state to transition to
|
||||
* @throws EnterStateVetoException when entering the state is not allowed
|
||||
*/
|
||||
public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException;
|
||||
|
||||
/**
|
||||
* Called when a state transitions, after the transition occurred.
|
||||
* @param context the current flow request context
|
||||
* @param previousState <i>from</i> state of the transition
|
||||
* @param state <i>to</i> state of the transition
|
||||
*/
|
||||
public void stateEntered(RequestContext context, StateDefinition previousState, StateDefinition state);
|
||||
|
||||
/**
|
||||
* Called when a view is about to render in a view-state, before any render actions are executed.
|
||||
* @param context the current request context
|
||||
* @param context the current flow request context
|
||||
* @param view the view that is about to render
|
||||
* @param viewState the current view state
|
||||
*/
|
||||
@@ -123,35 +131,27 @@ public interface FlowExecutionListener {
|
||||
|
||||
/**
|
||||
* Called after a view has completed rendering.
|
||||
* @param context the current request context
|
||||
* @param context the current flow request context
|
||||
* @param view the view that rendered
|
||||
* @param viewState the current view state
|
||||
*/
|
||||
public void viewRendered(RequestContext context, View view, StateDefinition viewState);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public void stateEntered(RequestContext context, StateDefinition previousState, StateDefinition state);
|
||||
|
||||
/**
|
||||
* Called when a flow execution is paused, for instance when it is waiting for user input (after event processing).
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
*/
|
||||
public void paused(RequestContext context);
|
||||
|
||||
/**
|
||||
* Called after a flow execution is successfully reactivated after pause (but before event processing).
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
*/
|
||||
public void resuming(RequestContext context);
|
||||
|
||||
/**
|
||||
* Called when the active flow execution session has been asked to end but before it has ended.
|
||||
* @param context the source of the event
|
||||
* @param context the current flow request context
|
||||
* @param session the current active session that is ending
|
||||
* @param output the flow output produced by the ending session, this map may be modified by this listener to affect
|
||||
* the output returned
|
||||
@@ -161,7 +161,7 @@ public interface FlowExecutionListener {
|
||||
/**
|
||||
* 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 source of the event
|
||||
* @param context the current flow request context
|
||||
* @param session ending flow session
|
||||
* @param output final, unmodifiable output returned by the ended session
|
||||
*/
|
||||
@@ -170,7 +170,7 @@ public interface FlowExecutionListener {
|
||||
/**
|
||||
* Called when an exception is thrown during a flow execution, before the exception is handled by any registered
|
||||
* {@link FlowExecutionExceptionHandler handler}.
|
||||
* @param context the source of the exception
|
||||
* @param context the current flow request context
|
||||
* @param exception the exception that occurred
|
||||
*/
|
||||
public void exceptionThrown(RequestContext context, FlowExecutionException exception);
|
||||
|
||||
@@ -25,6 +25,7 @@ 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;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link RequestControlContext} interface to facilitate standalone Flow and State unit
|
||||
@@ -76,6 +77,21 @@ public class MockRequestControlContext extends MockRequestContext implements Req
|
||||
return key;
|
||||
}
|
||||
|
||||
public void viewRendering(View view) {
|
||||
}
|
||||
|
||||
public void viewRendered(View view) {
|
||||
}
|
||||
|
||||
public boolean handleEvent(Event event) {
|
||||
setCurrentEvent(event);
|
||||
return ((Flow) getActiveFlow()).handleEvent(this);
|
||||
}
|
||||
|
||||
public boolean execute(Transition transition) {
|
||||
return transition.execute((TransitionableState) getCurrentState(), this);
|
||||
}
|
||||
|
||||
public void removeAllFlowExecutionSnapshots() {
|
||||
|
||||
}
|
||||
@@ -88,15 +104,6 @@ public class MockRequestControlContext extends MockRequestContext implements Req
|
||||
|
||||
}
|
||||
|
||||
public boolean handleEvent(Event event) {
|
||||
setCurrentEvent(event);
|
||||
return ((Flow) getActiveFlow()).handleEvent(this);
|
||||
}
|
||||
|
||||
public boolean execute(Transition transition) {
|
||||
return transition.execute((TransitionableState) getCurrentState(), this);
|
||||
}
|
||||
|
||||
public void start(Flow flow, MutableAttributeMap input) throws IllegalStateException {
|
||||
MockFlowSession session = new MockFlowSession(flow, input);
|
||||
if (getFlowExecutionContext().isActive()) {
|
||||
|
||||
@@ -278,9 +278,19 @@ public class XmlFlowModelBuilderTests extends TestCase {
|
||||
FlowExecutionImplFactory factory = new FlowExecutionImplFactory();
|
||||
factory.setExecutionListenerLoader(new StaticFlowExecutionListenerLoader(new FlowExecutionListenerAdapter() {
|
||||
public void viewRendering(RequestContext context, View view, StateDefinition viewState) {
|
||||
BindingResult result = (BindingResult) context.getFlashScope().get(
|
||||
"org.springframework.validation.BindingResult.formBean");
|
||||
assertEquals(1, result.getErrorCount());
|
||||
if (context.getCurrentEvent() != null && context.getCurrentEvent().getId().equals("submit")) {
|
||||
BindingResult result = (BindingResult) context.getFlashScope().get(
|
||||
"org.springframework.validation.BindingResult.formBean");
|
||||
assertEquals(1, result.getErrorCount());
|
||||
}
|
||||
}
|
||||
|
||||
public void viewRendered(RequestContext context, View view, StateDefinition viewState) {
|
||||
if (context.getCurrentEvent() != null && context.getCurrentEvent().getId().equals("submit")) {
|
||||
BindingResult result = (BindingResult) context.getFlashScope().get(
|
||||
"org.springframework.validation.BindingResult.formBean");
|
||||
assertNull(result);
|
||||
}
|
||||
}
|
||||
}));
|
||||
FlowExecution execution = factory.createFlowExecution(flow);
|
||||
|
||||
Reference in New Issue
Block a user