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

  1. 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.

  2. 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

  1. Create a webflow unit test per usual.
  2. 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".

  3. 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.