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: 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"
  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">
    
    <!-- By default, the first state is the start state. -->
    <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:

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"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html>
    <head>
        <title>Products for Geeks - GeekWarez</title>
    </head>
    <body>
        <h1>Welcome to GeekWarez</h1>
        
        <div><a href="account/register.do">Register</a></div>
    </body>
</html>

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"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html>
    <head>
        <title>Register - GeekWarez</title>
    </head>
    <body>
        <h1>Register</h1>
        
        <div>
            <a href="${flowExecutionUrl}&_eventId=submitRegistration">Submit</a> |
            <a href="${flowExecutionUrl}&_eventId=cancelRegistration">Cancel</a>
        </div>
    </body>
</html>

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!

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.