The Elements of the Spring Web Flow Configuration File

Master Spring's well-designed web frameworks to develop powerful web applications

Let's take a look at the XML Schema Definition (XSD) file of the Spring Web Flow configuration file. To make the file more compact and easier to read, we have removed documentation and similar additions from the file. The complete file is downloadable from http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd.

An XSD file is a file that is used to describe an XML Schema, which in itself is a W3C recommendation to describe the structure of XML files. In this kind of definition files, you can describe which elements can or must be present in an XML file. XSD files are primarily used to check the validity of XML files that are supposed to follow a certain structure. The schema can also be used to automatically create code, using code generation tools.

The elements of the Spring configuration file are:

flow

The root element of the Spring Web Flow definition file is the flow element. It has to be present in all configurations because all other elements are sub-elements of the flow tag, which defines exactly one flow. If you want to define more than one flow, you will have to use the same number of flow tags. As every configuration file allows only one root element, you will have to define a new configuration file for every flow you want to define.

attribute

Using  the attribute tag, you can define metadata for a flow. You can use this metadata to change the behavior of the flow.

secured

The secured tag is used to secure your flow using Spring Security. The element is defined like this:

<xsd:complexType name="secured">
<xsd:attribute name="attributes"
type="xsd:string"
use="required" />
<xsd:attribute name="match"
use="optional">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="any" />
<xsd:enumeration value="all" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:complexType>

If you want to use the secured element, you will have to at least define the attributes attribute. You can use the attributes element to define roles that are allowed to access the flow, for example. The match attribute defines whether all the elements specified in the attributes attribute have to match successfully (all), or if one of them is sufficient (any).

persistence-context

The persistence-context element enables you to use a persistence provider in your flow definition. This lets you persist database objects in action-states.

To use persistence-context tag, you also have to define a data source and configure the persistence provider of your choice (for example, Hibernate or the Java Persistence API) in your Spring application context configuration file.

The persistence-context element is empty, which means that you just have to add

<persistence-context />

to your flow definition, to enable its features.

var

The var element can be used to define instance variables, which are accessible in your entire flow. These variables are quite important, so make sure that you are familiar with them. Using var elements, you can define model objects. Later, you can bind these model objects to the forms in your JSP web sites and can store them in a database using the persistence features enabled with the persistence-context element.  Nevertheless, using instance variables is not mandatory, so you do not have to define any, unless required in your flow. The element is defined as shown in the following snippet from the XSD file:

<xsd:element name="var" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="class" type="type" use="required" />
</xsd:complexType>
</xsd:element>

The element has two attributes that are both required. The instance variable you want to define needs a name, so that you can reference it later in your JSP files. Spring Web Flow also needs to know the type of the variable, so you have to define the class attribute with the class of your variable.

input

You can use the input element to pass information into a flow. When you call a flow, you can (or will have to, depending on whether the input element is required or not) pass objects into the flow. You can then use these objects to process your flow. The XML Schema definition of this element looks like this:

<xsd:complexType name="input">
<xsd:attribute name="name" type="expression" use="required" />
<xsd:attribute name="value" type="expression" />
<xsd:attribute name="type" type="type" />
<xsd:attribute name="required" type="xsd:boolean" />
</xsd:complexType>

The input element possesses certain attributes, of which only the name attribute is required. You have to specify a name for the input argument, which you can use to reference the variable in your flow. The value attribute is used to specify the value of the attribute, for example, if you want to define a default value for the variable. You can also define a type (for example int or long) for the variable if you want a specific type of information. A type conversion will be tried if the argument passed to the flow does not match the type you expect. With the required attribute, you can control if the user of your flow has to pass in a variable, or if the input attribute is optional.

output

While you can define input parameters with the input element, you can specify return values with the output element. These are variables that will be passed to your end-state as the result value of your flow. Here's the XML Schema definition of the output element:

<xsd:complexType name="output">
<xsd:attribute name="name" type="expression" use="required" />
<xsd:attribute name="value" type="expression" />
<xsd:attribute name="type" type="type" />
<xsd:attribute name="required" type="xsd:boolean" />
</xsd:attribute>
</xsd:complexType>

The definition is quite similar to the input element. You can also see that the name of the output element is required. Otherwise, you have no means of referencing the variable from your end-state. The value attribute is the value of your variable, for example, the result of a computation or a user returned from a database. Of course, you can also specify the type you expect your output variable to be. As with the input element, a type conversion will be attempted if the type of the variable does not match the type specified here. The required attribute will check if nothing was specified, or the result of a computation is null. If it is null, an error will be thrown.

 

actionTypes

Per se, this is not an element which you can use in your flow definition, but it is a very important part of the XML Schema definition, referenced by many other elements. The definition is quite complex and looks like this:

<xsd:group name="actionTypes">
<xsd:choice>
<xsd:element name="evaluate">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="expression"
type="expression"
use="required" />
<xsd:attribute name="result"
type="expression"
use="optional" />
<xsd:attribute name="result-type"
type="type"
use="optional" />
</xsd:complexType>
</xsd:element>
<xsd:element name="render">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="fragments"
type="xsd:string"
use="required" />
</xsd:complexType>
</xsd:element>
<xsd:element name="set">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="name"
type="expression"
use="required" />
<xsd:attribute name="value"
type="expression"
use="required" />
<xsd:attribute name="type" type="type" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:group>

actionTypes is a group of sub-elements, namely evaluate, render, and set. Let's go through the single elements to understand how the whole definition works.

evaluate

With the evaluate element, you can execute code based on the expression languages. As described by the above source code, the element has three attributes; one of them is required. The expression attribute is required and executes the code that you want to run. The result value of the expression, if present, can be stored in the result attribute. Using the result-type attribute, you can convert the result value in the specified type, if needed. Additionally, you can define attributes using a sub-element of the attribute element.

render

Use the render element to partially render content of a web site. Using the required fragments attribute, you can define which fragments should be rendered. When the link on a web site is clicked the entire web site is not a re-load. Spring JavaScript allows you to update chosen parts of your web page. The remaining web site will not be reloaded, which can greatly enhance the performance of your web application. As is the case with the evaluate element, you can also specify additional attributes using the attribute sub-element.

set

The set element can be used to set attributes in one of the Spring Web Flows scopes. With the name attribute you can define where (in which scope) you want to define the attribute, and how it should be called. The following short source code illustrates how the set element works:

<set name="flowScope.myVariable" value="myValue" type="long" />

As you can see, the name consists of the name of the scope and the name of your variable, delimited by a dot (.). Both the name attribute and the value attribute are required. The value is the actual value of your variable. The type attribute is optional and describes the type of your variable. As before, you can also define additional attributes using the attribute sub-element.

view-state

The view-state element is very complex. Therefore, the definition in the XML Schema file is also quite long. As it is one of the most important and heavily used elements in Spring Web Flow, we quote the definition here. Because it is so long, we will split the definition into pieces and explain it step-by-step.

<xsd:element name="view-state">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="secured" type="secured" minOccurs="0" />
<xsd:element name="var"
minOccurs="0"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="name"
type="xsd:string"
use="required" />
<xsd:attribute name="class"
type="type"
use="required" />
</xsd:complexType>
</xsd:element>

This should not be completely new to you. The view-state element has several sub-elements. Three of them are: the attribute , the secured, and the var elements, which we have already explained earlier in this article. You can secure not only the entire flow, but also single states, using a secured tag in your state. The same is also true for attributes and variables. They are local in this state. As such, they are created as soon as the flow enters the state and destroyed as soon as the state ends.

<xsd:element name="binder" 
minOccurs="0"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="binding"
minOccurs="1"
maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="property"
type="xsd:string"
use="required" />
<xsd:attribute name="converter"
type="xsd:string" />
<xsd:attribute name="required"
type="xsd:boolean" />
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

The binder element is a new element which we haven't described yet. Using the binder element, you can configure how and what properties from your model are bound to the UI of your view. The binder element itself has one sub-element called binding. The binding element has three properties: property, converter, and required.  The property attribute is required. This attribute is used to specify which property of the model you want to bind the values of your UI to. Using the converter attribute, you can define how the model property should appear in the UI. Custom converters can be registered using an implementation of the ConversionInterface. Spring Web Flow already includes a default implementation called GenericConversionService. This class includes an addConverter() method that takes an ID for the converter and an object of type Converter:

Spring Web Flow 2 Web Development

As you can see, the Converter interface is not very difficult to implement and performs a conversion between two objects.

Last, but not the least, the required attribute tells Spring Web Flow to check if the object bound to the property is empty or null. If the attribute is set to true and the value is empty or null, an error will occur.

<xsd:element name="on-entry" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>
<xsd:element name="on-render" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>
<xsd:element name="transition"
type="viewTransition"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="on-exit" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>

All the sub-elements have additional sub-elements of the actionTypes group including evaluate, render and set, explained earlier in this article. You can use the on-entry element to execute actions as soon as the flow enters this state. The on-render element is called shortly before the view is finally rendered. We have already explained the transition element, which lets the flow continue to the next state. Before the state is left and the flow continues, the on-exit-element, if present, is called:

        <xsd:element name="exception-handler" 
type="exception-handler"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>

This element helps you to define custom exception handlers, specific to this state.

    <xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attribute name="parent" type="stateParent" />
<xsd:attribute name="view" type="viewFactory" />
<xsd:attribute name="redirect" type="xsd:boolean" />
<xsd:attribute name="popup" type="xsd:boolean" />
<xsd:attribute name="model" type="expression" />
</xsd:complexType>
</xsd:element>

The remaining attributes are very straightforward, and are explained in the following table:

Attribute name

Description

id

The ID of this state; each state needs a unique name that enables referencing, for example, referencing this state in transition elements

parent

Use this attribute to define a parent state for your view-state

view

This is the name of the view (or the file) that Spring Web Flow is supposed to render, for example, welcomePage.jsp; the view can also be an evaluated expression

redirect

It will trigger a redirect before the view-state is rendered

model

The model object to be used in this view; it can be used together with form-binding to display values from the object, and to change the values of the model object

popup

Opens a new pop up dialog and displays the view in this dialog

decision-state

The decision state can be used as a simple if-else construct in your flow definition if you have to make evaluation dependent decisions in your flow.

<xsd:element name="decision-state">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="secured" type="secured" minOccurs="0" />
<xsd:element name="on-entry" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>

These are the same elements that were used in the view-state element. Read the paragraph concerning the view-state for details about these tags.

<xsd:element name="if" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="test"
type="expression"
use="required" />
<xsd:attribute name="then"
type="targetStateResolver"
use="required">
<xsd:attribute name="else"
type="targetStateResolver">
</xsd:complexType>
</xsd:element>

This is the most important definition in the decision-state. It has a sub-element called if that has three attributes, of which two of them are required (test and then). The test attribute executes an expression that checks a certain condition. If the condition is evaluated to true, the then attribute will be executed. As it is of type, targetStateResolver, you can enter the name of any state here. The flow will transition to this state. You can specify an else attribute if the condition is evaluated to false; it will transition the flow to a different state.

<xsd:element name="on-exit" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>
<xsd:element name="exception-handler"
type="exception-handler"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attribute name="parent" type="stateParent" />
</xsd:complexType>
</xsd:element>

These elements are identical to the ones found in the view-state.

subflow-state

 

The subflow-state is used to create a reference to another flow, which is then executed as a subflow. The XML Schema definition is again quite similar to the one of the states we have seen earlier:

<xsd:element name="subflow-state">
<xsd:complexType>
<xsd:sequence minOccurs="0" >
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="secured" type="secured" minOccurs="0" />
<xsd:element name="on-entry" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>

These are the same elements used in the view-state element. Refer to the paragraph concerning the view-state for details about these tags.

<xsd:element name="input" 
type="input"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="output"
type="output"
minOccurs="0"
maxOccurs="unbounded" />

These elements of the subflow-state are used to create input and output variables. Every input variable you define will be accessible from the subflow. When the subflow returns, it can return multiple results. These subflow results can be saved in the variables specified by the output elements, and are accessible in the remaining flow.

<xsd:element name="transition" 
type="transition"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="on-exit" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>
<xsd:element name="exception-handler"
type="exception-handler"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attribute name="parent" type="stateParent" />

These elements are identical to the ones found in the view-state.

      <xsd:attribute name="subflow" type="flowId" />
<xsd:attribute name="subflow-attribute-mapper"
type="beanName" />
</xsd:complexType>
</xsd:element>

Finally, you can specify which flow should be executed as subflow by using the subflow attribute. It is of type flowId, which can be any flow you have in your application. Instead of input and output elements, you can also use a so-called SubflowAttributeMapper to give attributes to the subflow and receive return values from the subflow. SubflowAttributeMapper is an interface which looks like this:

Spring Web Flow 2 Web Development

In  the createSubflowInput() method, you can get the data you want to pass into the subflow from the RequestContext argument. From this data, you have to create a map which you can return afterwards. The method returns an object of type, MutableAttributeMap, which is another interface that you have to implement. You can also use the default implementation LocalAttributeMap, which is included in Spring Web Flow.

The mapSubflowOutput() method works in the opposite direction. You get the return values from the subflow in the first parameter from the method and can save them in the RequestContext.

 

end-state

Every flow definition can have one or more end-states. An end-state defines a possible ending point of your flow.

<xsd:element name="end-state">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="attribute"
type="attribute"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="secured" type="secured" minOccurs="0" />
<xsd:element name="on-entry" minOccurs="0">
<xsd:complexType>
<xsd:group ref="actionTypes" maxOccurs="unbounded" />
</xsd:complexType>
</xsd:element>
<xsd:element name="output"
type="output"
minOccurs="0"
maxOccurs="unbounded" />
<xsd:element name="exception-handler"
type="exception-handler"
minOccurs="0"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID" use="required" />
<xsd:attribute name="parent" type="stateParent" />
<xsd:attribute name="view" type="viewFactory" />
<xsd:attribute name="commit" type="xsd:string" />
</xsd:complexType>
</xsd:element>

Most of the end-state elements have already been explained. Only one attribute is new: the commit attribute of the end-state element. If you are using a persistence-context in your flow, and the commit attribute is set to true, all changes made to entities will be flushed to the database. If the attribute is set to false, no flush to the database will happen.

Summary

In this article, we delved into the depth of the flow configuration file by explaining all the important elements of the Spring Web Flow XML Schema. While configuring a flow the information about the elements of this XSD file will be very useful; this article can be used as reference.

 

If you have read this article you may be interested to view :

 

Books to Consider

comments powered by Disqus
X

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free