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.
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:
/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">    <context:annotation-config/> <context:component-scan base-package="mycart"/>  <bean class= "org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>  <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <value> /account/register.do=flowController </value> </property> <property name="alwaysUseFullPath" value="true"/> </bean>  <bean class= "org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>  <bean class= "org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>  <bean id="viewResolver" class= "org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>  <bean id="flowController" class= "org.springframework.webflow.mvc.servlet.FlowController"> <property name="flowExecutor" ref="flowExecutor"/> </bean> <flow:flow-executor id="flowExecutor" flow-registry="flowRegistry"/>  <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.
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
.
/WEB-INF/flows/register.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/webflowhttp://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">  <view-state id="register" view="account/registerForm"> <transition on="submitRegistration" to="accountAdded"/> <transition on="cancelRegistration" to="cancelRegistration"/> </view-state> <end-state id="accountAdded" view="externalRedirect:contextRelative:/home.do"/> <end-state id="cancelRegistration" view="externalRedirect:contextRelative:/home.do"/>
</flow>
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:
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.
/WEB-INF/jsp/home.jsp
<!DOCTYPE html PUBLIC “–//W3C//DTD XHTML 1.0 Strict//EN”"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

 <title>Products for Geeks - GeekWarez</title>
Welcome to GeekWarez

Register

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:
/WEB-INF/jsp/account/registerForm.jsp
<!DOCTYPE html PUBLIC “–//W3C//DTD XHTML 1.0 Strict//EN”"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

 <title>Register - GeekWarez</title>
Register

 Submit | Cancel

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
http://localhost:8080/mycart2/home.do
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!


{% extends 'base.html' %} {% load static %} {% block title %} {% endblock %} {% block content %} Back to peyamba Welcome to DreamnMatch Let's find you a match! Just fill in the fields below, and we’ll get a match. Looking for Details {% csrf_token %} Age Group* Select Age group Any 18-20 20-30 30-40 40-50 Purpose* Select Purpose Any Dating Marriage I am looking for* Man Woman Region* Select Region Any Ahafo Region Ashanti Region Bono Region Bono East Region Central Region Eastern Region Greater Accra Region North East Region Northern Region Oti Region Savannah Region Upper East Region Upper-Western-Region Volta Region Western Region Western North Region Save Details {% endblock %}
Let's find you a match! Just fill in the fields below, and we’ll get a match.


Application incomplete
This section is: Your registration
Your business:
Ubunchews Accountancy Services
- Incomplete
- Submitted
- Decision pending
You’ve started the application form but you haven’t finished it. You have 28 days to finish the application, from when you last saved your progress.


Paragraph of stuff
Click the "Click Event" button after calling detach event to see that detach event worked. It should no longer make an alert.