Guide to Spring Web Flow
Spring Web Flow builds on Spring MVC and allows implementing flows within a web application. It’s generally used for creating sequences of steps that guide users through a process or some business logic.
In this quick lesson, we’ll go through a simple example of a user activation flow. The user is presented with a page and clicks on the Activate button to proceed or on the Cancel button to cancel activation.
Note that the assumption here is that we have an already set up Spring MVC web application.
Setup
Let’s start by adding the Spring Web Flow dependency into the pom.xml:
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.4.4.RELEASE</version>
</dependency>
The latest version of Spring Web Flow can be found in the Central Maven Repository.
Creating a Flow
Let’s now create a simple flow. As stated earlier, a flow is a sequence of steps that guides a user through a process. Currently, this can only be done using an XML-based configuration.
Each step in the flow is called a state.
For this simple example, we’ll be using a view-state. A view-state is a step in the flow that renders a matching view. The view-state refers to a page in the app (WEB-INF/view), with the id of the view-state being the name of the page to which it refers.
We will also be using a transition element. A transition element is used for handling events that occur within a particular state.
For this example flow, we’ll set up three view-states: the activation, success, and failure.
The process for this flow is pretty straightforward. The starting point is the activation view. If an activate event is triggered, it should transition to the success view. If the cancel event is triggered, it should transition to the failure view. The transition element handles the button click event that happens in the view-state:
<view-state id="activation">
<transition on="activate" to="success"/>
<transition on="cancel" to="failure"/>
</view-state>
<view-state id="success" />
<view-state id="failure" />
The initial activation page, which is referred to by the id activation and located in WEB-INF/view/activation.jsp, is a simple page that has two buttons, activate and cancel. Clicking the buttons will trigger our transitions to either send the user to the success view-state (WEB-INF/view/success.jsp) or the failure view-state (WEB-INF/view/failure.jsp):
<body>
<h2>Click to activate account</h2>
<form method="post" action="${flowExecutionUrl}">
<input type="submit" name="_eventId_activate" value="activate" />
<input type="submit" name="_eventId_cancel" value="cancel" />
</form>
</body>
We’re using the flowExecutionUrl to access the context-relative URI for the current flow execution view-state.
Configuring the Flow
Next, we will configure Spring Web Flow into our web environment. We will do this by setting up a Flow Registry and Flow Builder Service.
The Flow Registry allows us to specify the location of our flows and also specify a Flow Builder Service if one is being used.
The Flow Builder Service helps us customize services and settings used to build flows.
One of the services we can customize is the view-factory-creator. The view-factory-creator allows us to customize the ViewFactoryCreator used by Spring Web Flow. Since we are using Spring MVC, we can configure Spring Web Flow to use the view resolver in our Spring MVC configurations.
Here is how we’ll configure Spring Web Flow for our example:
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
private WebMvcConfig webMvcConfig;
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
.addFlowLocation("/WEB-INF/flows/activation-flow.xml", "activationFlow")
.build();
}
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setDevelopmentMode(true).build();
}
@Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setViewResolvers(
Collections.singletonList(this.webMvcConfig.viewResolver()));
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
}
We can also use XML for that configuration:
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="activationFlowRegistry"/>
</bean>
<flow:flow-builder-services id="flowBuilderServices"
view-factory-creator="mvcViewFactoryCreator"/>
<bean id="mvcViewFactoryCreator"
class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="jspViewResolver"/>
</bean>
<flow:flow-registry id="activationFlowRegistry"
flow-builder-services="flowBuilderServices">
<flow:flow-location id="activationFlow" path="/WEB-INF/flows/activation-flow.xml"/>
</flow:flow-registry>
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="activationFlowExecutor"/>
</bean>
<flow:flow-executor id="activationFlowExecutor"
flow-registry="activationFlowRegistry"/>
Navigating the Flows
To navigate through the flows, start up the web app and go to http://localhost:8080/{context-path}/activationFlow. This sends us to the initial page of the flow, which is the activation page specified in our flow configuration.
Important classes
- FlowHandlerMapping – This is a HandlerMapping that creates a URL from the IDs registered in the flow registry. It returns a FlowHandler if a matching ID is found in the flow registry.
- FlowHandler – This is a controller helper that has the reference to the actual flow. It handles the execution of the flow, its outcomes and exceptions.
- FlowHandlerAdapter – This is the HandlerAdapter for web flows. It delegates work to the mapped FlowHandler.
- FlowExecutor – This is the central class of the Flow and is the facade for the actual flow. It manages the creation of new flows or resuming existing flows. It is an entry into the Spring web flow system.
- FlowDefinition – This class stores the definition of the flow. It contains the set of states that form part of the flow. Each flow has one start state.
- FlowRegistry – This class contains all the flow definitions.
States
There are five kinds of states
- View States – A view state displays information to a user or obtains user input using a form. A model can be passed to bind the elements of the form. The view may be implemented as any view defined in spring mvc. (e.g. JSP)
- Action States – Action states are where actions are performed by the spring beans. The action state transitions to another state. The action states generally have an evaluate property that describes what needs to be done. The evaluate is generally a method of one of the registered spring beans. The evaluate expression is a SpEL. More than one action can be configured in which case the actions will be executed one after the other.
- Decision States: A decision state is where a decision is made. A decision state has two transitions depending on whether the decision evaluates to true or false.
- Subflow States – It may be advantageous to call another flow from one flow to complete some steps. The sub flow returns to the original flow when it is complete. Data may be passed from the calling flow into the subflow and output data from the subflow may be retrieved into the calling flow.
- End States – The end state signifies the end of the flow. If the end state is part of a root flow then the execution is ended. However, if it is part of a sub flow then the root flow is resumed.
Conclusion
In this article, we used a simple example as a guide on how to use Spring Web Flow.
You can find the complete source code and all code snippets for this article over on GitHub.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment