Getting Started with Spring Web Flow – Part 1
Spring Web Flow is a sub project of Spring that can be used to model user interface activities as flows. For example, consider the scenario of looking up an employee using an Employee directory application. This activity involves entering the employee’s name, filtering through the search results and viewing the details of the employee. Spring Web Flow makes it easy to define and implement such activities as flows.
In this post, I will discuss the details involved in creating a simple web flow application. This post will serve as a foundation to a much complex application we will see in a later post.
Spring Web Flow is an extension to Spring MVC. So, we start out by creating a Spring MVC web application. I have used my Spring MVC Maven Archetype to generate a basic MVC web application named “helloflow”. Here is the structure of the generated project:
The web-Context.xml file has the standard Spring MVC bean declarations:
<beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- Enables the Spring MVC @Controller programming model --> <annotation-driven /> <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <beans:property name="prefix" value="/WEB-INF/jsp/" /> <beans:property name="suffix" value=".jsp" /> </beans:bean> <context:component-scan base-package="com.inflinx.blog.helloflow.web" /> </beans:beans>
Similarly, the web.xml file contains the standard DispatcherServlet and ContextLoaderListener declarations:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:application-Context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>helloflow</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/web-Context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>helloflow</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping> </web-app>
In order to add Spring Web Flow capabilities to the application, we need to add Web Flow jars to the project. This is done by simply adding the following Maven dependency to pom.xml:
<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>spring-webflow</artifactId> <version>2.3.1.RELEASE</version> </dependency>
We will be using XML to define flows. Before we start defining flows, we need to let the Spring MVC application know about web flow so that flow requests and flow execution can be handled properly. To keep things more modular, we will declare these web flow realted beans in a separate webflow-Context.xml file under WEB-INF folder. Here is the context file with web flow namespace declarations:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.springframework.org/schema/webflow-config" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd"> </beans>
The first web flow bean that needs to be declared is the flow-registry bean:
<flow:flow-registry flow-builder-services="flowBuilderServices" id="flowRegistry" base-path="/WEB-INF/flows/"> <flow:flow-location id="hello" path="hello-flow.xml" /> </flow:flow-registry>
The flow-registry bean serves as the registry of flow definitions. In the above declaration the base-path property tells that all the flows will be under “WEB-INF/flows”. The flow-location element indicates the existence of a “hello-flow” with the id “hello”. The id is important, as we will be using it to launch a flow later.
The flow-registry bean simply loads all the flows. The actual execution of the flow is performed by the flow-executor. The flow-executor bean declaration is shown below:
<flow:flow-executor id="flowExecutor" flow-registry="flowRegistry" />
The next set of beans are the FlowHandlerAdapter and FlowHandlerMapping. The FlowHandlerAdapter bean is responsible for dispatching requests to flows where as the FlowHandlerMapping is responsible for mapping a request path to a specific flow.
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter"> <property name="flowExecutor" ref="flowExecutor" /> </bean> <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"> <property name="flowRegistry" ref="flowRegistry" /> <property name="order" value="0" /> </bean>
The final set of beans that needs to be declared are the MvcViewFactoryCreator and flow-builder-services. These beans are responsible resolving views. By default the MvcViewFactoryCreator will look for the views in the same folder as that of the flow definition.
<bean id="flowViewResolver" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator"> <property name="viewResolvers" ref="internalResourceViewResolver"/> </bean> <flow:flow-builder-services id="flowBuilderServices" view-factory-creator="flowViewResolver" />
This concludes the webflow-Context.xml definition. Here is complete context file declaration:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.springframework.org/schema/webflow-config" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd"> <!-- Registry of executable flows --> <flow:flow-registry flow-builder-services="flowBuilderServices" id="flowRegistry" base-path="/WEB-INF/flows/"> <flow:flow-location id="hello" path="hello-flow.xml" /> </flow:flow-registry> <!-- Executes flows --> <flow:flow-executor id="flowExecutor" flow-registry="flowRegistry" /> <!-- Dispatches requests to Flows --> <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter"> <property name="flowExecutor" ref="flowExecutor" /> </bean> <!-- Maps specific paths to flows. For example, /hello will look for a flow with id hello --> <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"> <property name="flowRegistry" ref="flowRegistry" /> <property name="order" value="0" /> </bean> <bean id="flowViewResolver" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator" /> <flow:flow-builder-services id="flowBuilderServices" view-factory-creator="flowViewResolver" /> </beans>
The next step is to define a flow. Each flow is made up of states where things tend to happen and transitions that takes the flow from one state to another. We will create a hello flow that has a single state. To do that, simply create a new hello-flow.xml file under WEB-INF/flows folder. Here are the contents of the file:
<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"> <view-state id="hellowebflow" /> </flow>
As you notice, the above flow has only one state: a view state with id hellowebflow. View states displays user interface and invites the user to participate in the flow. So, when the above flow gets executed, Web Flow will look for a JSP page with the name hellowebflow.jsp under WEB-INF/flows and displays it. Here are the contents of the hellowebflow.jsp page:
<html> <head> </head> <body> <h2>Welcome to Webflow</h2> </body> </html>
We are almost done with our application. We just need to make two more changes. The first change needs to be made in the web-Context.xml file to let Spring MVC know about the existence of webflow-Context.xml file. This is done by adding the following import element to web-Context.xml file:
<!-- Import the webflow definitions --> <beans:import resource="webflow-Context.xml" />
Finally, we modify the web.xml file to instruct Spring to hanlde flow requests. This is done by adding a url-pattern element to the DispatcherServlet’s servlet-mapping element.
<url-pattern>*.flow</url-pattern>
Once we have the application deployed, we can launch the flow using the URL: http:
Thanks! Great example.
very nice tutorial
Thanks for a very good example for Spring WebFlow beginners.
thanks for this tutorial.
u didnt tel anything about HomeController.java