del.icio.us Digg DZone Reddit StumbleUpon
Tutorial: Build a Shopping Cart with Spring Web Flow 2.0 - Willie Wheeler
« Previous | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Next »

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"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:flow="http://www.springframework.org/schema/webflow-config"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/webflow-config
    http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">


    <!-- SPRING MVC STUFF -->

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

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

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

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

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon
« Previous | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Next »
Show comments (62)

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Please help us prevent comment spam:

What's New?

2008-10-20 - I've added a new mailing list feature to the site. Sign up to receive e-mail updates about new articles.
2008-09-30 - We've released chapter 4 (User registration) and chapter 5 (Authentication) of Spring in Practice.
2008-09-11 - By popular demand, I've added an RSS feed to the site.
Home | Consulting | Tech Articles | Mailing List | About | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.