Going hand-in-hand with the idea of multiple flows is the idea that
some flows might be subflows of other flows. In mycart3,
all four flows can be independently accessed, but in addition to that
we have the addToCart, login and
register flows being subflows to the
checkout flow. See Figure 3.

Here's the idea. The three flows we've identified as subflows are defined as separate flows because clearly there are use cases where it makes sense for them to be accessed outside of a checkout process. For example, we want to be able to add products to a shopping cart while we're browsing the product catalog. And of course we want people to be able to register and login even if they're not in a checkout process.
But those are also flows that we might want to include as part of a checkout process too. During checkout, we might want to recommend products to the customer. Or if the user hasn't yet logged in or registered, we'd want them to do that as part of the checkout process rather than forcing them to do that before they could enter the checkout process.
By defining the login, registration and add-to-cart as flows, we make them available both independently (as top-level flows) and also as part of a larger flow (like the checkout flow). That's why we have these defined as flows even though they are currently implemented as single-state flows. (It is however easy to imagine these being multi-state flows. For example, the login flow may ask you to answer a challenge question if it detects that you're coming in from an unusual IP address, or the add-to-cart flow may ask you to enter a quantity before proceeding.)
So here is the checkout flow:
/WEB-INF/flows/checkout.xml
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<!-- Get the products one time, at the beginning of the flow -->
<on-start>
<set name="flowScope.products" value="cartService.products"/>
<set name="flowScope.shippingOptions" value="cartService.shippingOptions"/>
</on-start>
<!-- If not specified, the start state is the first state specified. -->
<view-state id="viewCart" view="viewcart">
<!-- cart is available to SWF but not stored on the session under that
name when using AOP proxy -->
<on-render>
<!-- Carry cart from Spring app context to request scope -->
<set name="requestScope.shoppingCart" value="shoppingCart"/>
<set name="requestScope.recommendations" value="cartService.recommendations"/>
</on-render>
<transition on="addToCart" to="addProductToCart"/>
<transition on="register" to="register"/>
<transition on="login" to="login"/>
</view-state>
<subflow-state id="addProductToCart" subflow="addToCart">
<!-- This is where we go when the subflow returns. productAdded is
the name of an end-state. -->
<transition on="productAdded" to="viewCart"/>
</subflow-state>
<!-- New customers create a new account before moving forward -->
<subflow-state id="register" subflow="register">
<transition on="accountAdded" to="paymentAndShipmentOptions"/>
<transition on="cancelRegistration" to="viewCart"/>
</subflow-state>
<!-- Existing customers log in before moving forward -->
<subflow-state id="login" subflow="login">
<!-- This is where we go when the subflow returns. productAdded is
the name of an end-state. -->
<transition on="loginOk" to="paymentAndShipmentOptions"/>
</subflow-state>
<!-- Payment and shipment options -->
<view-state id="paymentAndShipmentOptions" view="options">
<transition on="submit" to="confirmOrder"/>
<transition on="back" to="viewCart"/>
</view-state>
<!-- Confirm order -->
<view-state id="confirmOrder" view="confirmorder">
<on-render>
<set name="requestScope.shoppingCart" value="shoppingCart"/>
</on-render>
<transition on="continue" to="thankYou">
<evaluate expression="cartService.submitOrderForPayment()"/>
</transition>
</view-state>
<!-- Thank you page -->
<view-state id="thankYou" view="thanks">
<transition on="continue" to="shop"/>
</view-state>
<!-- Exit the flow, letting the user return to shopping -->
<end-state id="shop" view="externalRedirect:contextRelative:/home.do"/>
<global-transitions>
<transition on="cancelCheckout" to="shop"/>
</global-transitions>
</flow>
In the code above, we are using the
<subflow-state> element to call a subflow from a
parent flow. The subflow attribute specifies one of the
flows you registered with the flow registry in the Spring
configuration. The flow starts at the subflow's start state, and
continues until the subflow hits an end state. The end state IDs
provide keys that you can reference from the calling flow to effect
state transitions. For example, in the flow above,
accountAdded is one of the end states for the
register flows, and so one of the
<transition> elements references that end
state.
Recall from register.xml (see page 4) that the end states
specified a view attribute. If the register
flow is called directly, then SWF will use the view
attribute to decide which view to show the user when the flow reaches
a given end state. If, however, the flow is called as part of a
subflow (instead of being called directly), SWF will ignore the
view attribute and instead follow whatever transition is
defined in the calling <subflow-state>.