How To Use Subflow
Introduction
Spring Web Flow has something called subflow which allows one webflow to invoke another webflow (possibly defined in a different module). When designed properly, webflow allows collaboration of disparate modules.
Get started with subflow
- Define a subflow-state
<!-- id: handle for this subflow. subflow: registered webflow name. by convention, spring names webflow by using the XML definition filename minus .xml. --> <subflow-state id="questionGroupStep" subflow="questionnaire"> <transition on="viewClientDetails" to="selectCustomerStep"></transition> </subflow-state>
In this example, the subflow is called "questionGroupStep". It will invoke the "questionnaire" webflow when a state transition to "questionGroupStep" occurs. When the subflow exits, a transition to "selectCustomerStep" state will occur.
- To invoke the subflow, simply use the subflow's ID as the target of state transition:
<view-state id="customerSearchStep" view="createSavingsAccountCustomerSearch" model="savingsAccountFormBean"> <transition on="searchTermEntered" to="questionGroupStep" validate="true"></transition> </view-state>
In this example, when event "searchTermEntered" is triggered, webflow will make a transition to "questionGroupStep" - our subflow.
Webflow unit test with subflow
- Create a webflow unit test per usual.
- In configureFlowBuilderContext(), create a stub subflow and register it with builder context:
@Override protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) { ... // setup questionnaire subflow Flow questionnaire = new Flow("questionnaire"); State start = new State(questionnaire, "selectQuestionnaire") { @Override protected void doEnter(RequestControlContext context) throws FlowExecutionException { // empty } }; questionnaire.setStartState(start); builderContext.registerSubflow(questionnaire); }
In this example, a new (stub) Flow is instantiated with a name of "questionnaire". This is the name of the webflow you designated as subflow above. The flow will have a start state of "selectQuestionnaire".
- When you verify the state, you will be using subflow's state.
@Test public void testCustomerSearchStep_SearchTermEntered() { setCurrentState("customerSearchStep"); MockExternalContext context = new MockExternalContext(); context.setEventId("searchTermEntered"); resumeFlow(context); assertCurrentStateEquals("selectQuestionnaire"); }
Note: you do not need to import webflow definition for the subflow. It is merely stubbed out because you are only testing the root webflow.