Spring in Practice

Willie Wheeler's Spring blog

Build a Shopping Cart With Spring Web Flow 2, Part 2

| Comments

This post is part of a three part series: Part 1 | Part 2 | Part 3

Creating a simple flow: Spring application context configuration

Now we have Spring MVC working, so it’s time to expand on that and get Spring Web Flow working too. We’ll start by creating a very simple flow—one that has only a single view state. First we’ll look at the updated Spring application context configuration. After that we’ll look at the flow definition itself.

To make it easier for you to follow along, here’s the updated,one-state version of our shopping cart:


Dependencies for mycart2.zip

Because we’re now using SWF, we have additional dependencies. Here’s the full set so far:

These come from the Spring 2.5.4 distribution. [download]

  • spring.jar (located in /spring-framework-2.5.4/dist)
  • spring-webmvc.jar (located in /spring-framework-2.5.4/dist/modules)
  • commons-logging.jar (located in /spring-framework-2.5.4/jakarta-commons)

You will need the following JARs from the Spring Web Flow 2.0 distribution. [download]

  • spring-webflow-2.0.0.jar
  • spring-binding-2.0.0.jar
  • spring-js-2.0.0.jar

You will need the following JAR from the OGNL web site:

  • ognl-2.6.9.jar

Spring Web Flow uses either OGNL or Unified EL for parsing expressions. For this article I arbitrarily picked OGNL though you can use jboss-el.jar (currently the only Unified EL implementation that will work with SWF) too.

web.xml and mycart.CartController

For now we aren’t making any changes to either of these at all.

Figure 2. Overview of SWF components.
Figure 2. Overview of SWF components.

Spring application context overview

Before jumping into the code, let’s do a quick overview of the various components involved. Please see Figure 2.

We already saw DispatcherServlet in web.xml. (So it’s not part of mycart-servlet.xml; we’re discussing it here just to show the relationship between the servlet and the FlowController.) DispatcherServlet is the Spring MVC front controller and it receives any Spring MVC requests—including SWF requests, as SWF is based on Spring MVC—according to your web.xml configuration.

We’re using SimpleUrlHandlerMapping to map flow requests from DispatcherServlet to FlowController.

So now FlowController has the request. FlowController is just a Spring MVC controller that receives flow requests and passes them to FlowExecutor for actual processing.

FlowExecutor contains the actual logic for processing Spring Web Flow requests. Among other things it determines for any given request which flow is involved and figures out what state transition to enact, based on the request.

When FlowExecutor needs a flow, it grabs the flow from the FlowRegistry, which is responsible for loading the flow from a flow configuration file and maintaining it on behalf of the FlowExecutor.

FlowBuilderServices is just a container for various services that FlowRegistry needs when constructing flows. This includes, for example, a service to provide for the creation of view factories. In our example, we will see that we’re specifically using a MvcViewFactoryCreator, which creates view factories for Spring MVC views.

Finally, we define a ViewResolver, which is a Spring MVC interface that carries logical view names to physical resources (such as JSPs). For example, a ViewResolver might carry the logical name checkout/viewcart to the physical resource /WEB-INF/jsp/checkout/viewcart.jsp.

Spring application context configuration file

And finally here’s the configuration file itself:

Code listing: /WEB-INF/mycart-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"

    <!-- SPRING MVC STUFF -->

    <!-- This activates post-processors for annotation-based config -->
    <!-- http://www.infoq.com/articles/spring-2.5-part-1 -->

    <context:component-scan base-package="mycart"/>

    <!-- Enables POJO @Controllers (like CartController) -->
    <bean class=
    <!-- Maps flow requests from DispatcherServlet to flowController -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
        <property name="alwaysUseFullPath" value="true"/>
    <!-- Enables annotated methods on POJO @Controllers (like CartController) -->
    <bean class=
    <!-- Enables plain Controllers (e.g. FlowController) -->
    <bean class=
    <!-- Maps a logical view name to a physical resource -->
    <bean id="viewResolver" class=
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    <bean id="flowController" class=
        <property name="flowExecutor" ref="flowExecutor"/>
    <flow:flow-executor id="flowExecutor" flow-registry="flowRegistry"/>
    <!-- This creates an XmlFlowRegistryFactory bean -->
    <flow:flow-registry id="flowRegistry"
        <flow:flow-location path="/WEB-INF/flows/register.xml"/>
    <flow:flow-builder-services id="flowBuilderServices"
    <bean id="viewFactoryCreator" class=
        <property name="viewResolvers">
                <ref bean="viewResolver"/>

Now let’s look at our basic flow definition, which will initially at least be much simpler than the application context file.

Creating a Simple Flow: Flow Definition File and JSPs

We’ll now add a SWF flow definition file, update our original home page JSP, and add a new JSP for registering as a new customer.

The flow definition file

Here’s a definition for our first flow, which will be a bare-bones registration process. We’ll add more flows to the application but this is our starting point just to get SWF working. You’ll need to create a directory /WEB-INF/flows, and then add the following flow definition file to that directory, naming the file register.xml.

Code listing: /WEB-INF/flows/register.xml
<?xml version=“1.0” encoding=“UTF-8”?>
<flow xmlns=“http://www.springframework.org/schema/webflow”


&lt;!-- By default, the first state is the start state. --&gt;
&lt;view-state id="register" view="account/registerForm"&gt;
    &lt;transition on="submitRegistration" to="accountAdded"/&gt;
    &lt;transition on="cancelRegistration" to="cancelRegistration"/&gt;

&lt;end-state id="accountAdded"
&lt;end-state id="cancelRegistration"


Here we have a single state, called a view state, and all it does is show us the hardcoded JSP that we created earlier. We’re identifying the state itself as register, and the logical view name associated with this view state is account/registerForm. This is the name that the view resolver we defined in the Spring app context file will map to a physical location; in this case the physical location will be /WEB-INF/jsp/account/registerForm.jsp.

By default, SWF interprets the first state in the file as being the start state, or entry point into the flow. There must be exactly one start state. The flow itself is called register (this is because we’ve named the flow definition file register.xml). As it happens we’ve also named the first state register though there’s no requirement for the start state to have the same name as the flow.

I’ve defined a couple of transitions out of the register state. One transition, submitRegistration, responds to registration submission events on the user interface, such as the user clicking a submit button on a registration form. The other transition, cancelRegistration, responds to cancelation events on the UI, such as the user clicking a cancel link. Each of these transitions leads to another state in the flow. In this case, both of the transitions lead to end states, which are exits out of the flow, but transitions can lead to other view states (or even other sorts of state) as well. As shown there can be multiple end states for a flow. Here my end states happen to be doing the same thing; they’re redirecting the user to a context-relative (as in relative to the servlet context) path /home.do, which you will recall is just the home page. There are some other relativizations you can do as well:

Relativization Example
Servlet mapping-relative externalRedirect:/hotels/index
Servlet-relative path externalRedirect:servletRelative:/hotels/index
Context-relative path externalRedirect:contextRelative:/dispatcher/hotels/index
Server-relative path externalRedirect:serverRelative:/springtravel/dispatcher/hotels/index
Absolute URL externalRedirect:http://www.paypal.com/
Table 1. Relativizations for externalRedirect.

Anyway we’re doing the context-relative redirection in this case. This is how we jump out of SWF and return control to the application. (Or how we return control to a calling flow, but we’ll get to that.)

The JSPs

Now let’s revisit our home page JSP. It’s still pretty similar but I’m adding a registration link.

Code listing: /WEB-INF/jsp/home.jsp
<!DOCTYPE html PUBLIC “–//W3C//DTD XHTML 1.0 Strict//EN”



    &lt;title&gt;Products for Geeks - GeekWarez&lt;/title&gt;
    &lt;h1&gt;Welcome to GeekWarez&lt;/h1&gt;

    &lt;div&gt;&lt;a href="account/register.do"&gt;Register&lt;/a&gt;&lt;/div&gt;


The registration link takes us into the register flow,since the last path segment is register.do. In our Spring app context we told the flow registry about register.xml, so SWF will know to map requests for /account/register.do to the register flow.

Now we need a registration form. The following page is our current version of a registration “form”, but as you can see it isn’t really a form at all (yet). It is just a couple of links:

Code listing: /WEB-INF/jsp/account/registerForm.jsp
<!DOCTYPE html PUBLIC “–//W3C//DTD XHTML 1.0 Strict//EN”



    &lt;title&gt;Register - GeekWarez&lt;/title&gt;

        &lt;a href="${flowExecutionUrl}&amp;_eventId=submitRegistration"&gt;Submit&lt;/a&gt; |
        &lt;a href="${flowExecutionUrl}&amp;_eventId=cancelRegistration"&gt;Cancel&lt;/a&gt;


The point of the two links is to give the user a way to generate submitRegistration and cancelRegistration events. We saw in the flow definition that these two events trigger state transitions. Of special importance is the URL for each of these links. Notice that by using ${flowExecutionUrl}, we’re still pointing the user at the same /account/register.do servlet path. That’s because we’re still working within the register flow. The ${flowExecutionUrl} URL includes an execution HTTP parameter whose value is a key that SWF uses for flow-tracking purposes. In addition we add an _eventId parameter that we use to drive state transitions. The event IDs are what we’re referencing when we define transitions in the flow definition file.

So really so far all we can do at this point is move back and forth between the home page and the registration page, but we’re doing it with Spring Web Flow.

Milestone 2: Spring Web Flow is working

Point your web browser at


making any adjustments you need to make for the port or application context. Also note that the context is now mycart2 instead of mycart1 like it was in the first version of the code. If you’re able to click back and forth between the home page and the registration page, then congrats, Spring Web Flow 2.0 is working! Celebrate!

This post is part of a three part series: Part 1 | Part 2 | Part 3

Post migrated from my Wheeler Software site.