Integrating Spring Web Flow with JSF

November 11, 2010

Java Server Faces (JSF)

«»

Introduction

Spring Web Flow is a framework that provides abilities to developers to capture the workflow of a web application in the form of configurational constructs called Flows. JSF is a UI framework that provides support for developing complex user interface components along with simplified page navigation rules and event handling. In this article we will discuss about the integration techniques between Spring Web Flow and JSF with the assumption that the readers have a good understanding of these two technologies.

Download Source Code

If you are not familiar with Java Server Faces, first read our list of articles on Java Server Faces (JSF) including Introduction to Java Server Faces by Raja. We have also listed some of the popular JSF Books in our Java Book Store.

Test application

In this section, we will see the basic artifacts necessary for integrating Spring Web flow with JSF by developing a simple application. Because the idea is to illustrate the integration between Spring Web Flow and JSF, the application does nothing other than displaying a simple JSF invoked from Spring Web Flow. In the later sections of the article, we will see how to use services that makes use of database.

Web application deployment descriptor

We will start with defining the deployment descriptor of the application which is given below. Note that the following code snippet contains declarations specific to Spring Web Flow as well as JSF.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
	version="2.4">
 
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/config/spring-fc-config.xml
		</param-value>
	</context-param>
 
	<context-param>
		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
		<param-value>.xhtml</param-value>
	</context-param>
 
  	<context-param>
        <param-name>facelets.DEVELOPMENT</param-name>
   		<param-value>true</param-value>
  	</context-param>
 
  	<context-param>
  		<param-name>facelets.REFRESH_PERIOD</param-name>
  		<param-value>1</param-value>
  	</context-param>
 
    <filter>
        <filter-name>charEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
 
    <filter-mapping>
        <filter-name>charEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
 
	<servlet>
		<servlet-name>Resources Servlet</servlet-name>
		<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>Resources Servlet</servlet-name>
		<url-pattern>/resources/*</url-pattern>
	</servlet-mapping>
 
	<servlet>
		<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value></param-value>
		</init-param>
		<load-on-startup>2</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
		<url-pattern>/spring/*</url-pattern>
	</servlet-mapping>
 
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.faces</url-pattern>
	</servlet-mapping>
 
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
 
</web-app>

The mapping for all the faces requests are handled by the Faces Servlet and the context path containing ‘spring’ is handled by Spring’s Dispatcher Servlet. A listener is configured which will load the application context which is found in the path ‘/WEB-INF/config/spring-fc.xml’.

Spring’s Configuration file

The content of Spring’s configuration file is given below. Note that this file contains a mixture of definitions related to Spring Web Flow and Spring MVC although it is possible to segregate them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:webflow="http://www.springframework.org/schema/webflow-config"
       xmlns:faces="http://www.springframework.org/schema/faces"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/webflow-config
           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd
           http://www.springframework.org/schema/faces
           http://www.springframework.org/schema/faces/spring-faces-2.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
	<webflow:flow-executor id="flowExecutor">
	</webflow:flow-executor>
 
	<webflow:flow-registry id="flowRegistry" flow-builder-services="facesFlowBuilderServices">
		<webflow:flow-location path="/WEB-INF/flows/test.xml" />
	</webflow:flow-registry>
 
	<faces:flow-builder-services id="facesFlowBuilderServices" />
 
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<value>
				/test=flowController
			</value>
		</property>
		<property name="defaultHandler">
			<bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
		</property>
	</bean>
 
	<bean id="flowController" class="org.springframework.webflow.mvc.servlet.FlowController">
		<property name="flowExecutor" ref="flowExecutor"/>
	</bean>
 
	<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
		<property name="prefix" value="/WEB-INF/" />
		<property name="suffix" value=".xhtml" />
	</bean>
 
</beans>

We have defined the Spring Web Flow’s flow Controller that is responsible for creating the flow definitions by loading the flows from the file ‘/WEB-INF/flows/test.xml’. We have defined URL based mapping of requests by defining ‘SimpleUrlHandlerMapping’. Note that for JSf integration, the declaration of ‘faces:flow-builder-services’ is necessary.

Faces Configuration file

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC
  "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
  "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
 
<faces-config>
	<application>
		<!-- Enables Facelets -->
		<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>  
	</application>
</faces-config>

In the above faces configuration file, we have explicitly instructed to make use of Faceets as the view technology instead of JSF. Also note that the managed beans declarations and the navigation rules will simply go off and won’t be required at all as part of the integration since it will be taken care by Spring Web Flow itself.

Welcome file

The welcome file mentioned in the Web application’s deployment descriptor is ‘index.htm’ whose contents is given below.

1
2
3
4
5
<html>
<head>
  <meta http-equiv="Refresh" content="0; URL=spring/start">
</head>
</html>

Note that it re-directs the control to the url mapping which will be handled by Spring’s dispatcher servlet.

Flow Definition file

The code snippet for the flow definition file is given below. Remember that the below definitions will be loaded by Spring Web Flow’s Flow Controller as we have configured a context listener in the web.xml file.

1
2
3
4
5
6
7
8
9
<?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">
 
	<view-state id="test">
	</view-state>
 
</flow>

There is only one state defined which is ‘test’. So, when the flow is invoked, the framework will look out for a file called ‘test.xhtml’ in the directory ‘/WEB-INF/flows’ as that is how we have configured the view resolver in the Spring’s application context file.

1
2
3
4
5
<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
		<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
		<property name="prefix" value="/WEB-INF/" />
		<property name="suffix" value=".xhtml" />
	</bean>

Sample Facelets file

The sample facelets file is given below. Note that it really does nothing other than displaying information message to the user. Also note that in the below file we are making use of templates and the name of the template file is ‘template.xhtml’.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">
    <body>
 
        <ui:composition template="../template.xhtml">
 
            <ui:define name="heading">            
            </ui:define>
 
            <ui:define name="body">
                Sample page which illustrates the integration between JSF and Spring Web Flow
            </ui:define>
 
        </ui:composition>
 
    </body>
</html>

Starting Page

Note that this is the page that will be invoked at startup and from here the control resumes back to Spring Web flow for displaying the page ‘test.xhtml’.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	    		xmlns:ui="http://java.sun.com/jsf/facelets"
	  			xmlns:h="http://java.sun.com/jsf/html"
	  			xmlns:f="http://java.sun.com/jsf/core"
                xmlns:sf="http://www.springframework.org/tags/faces"
				template="template.xhtml">
 
    <ui:define name="heading">
    </ui:define>
 
    <ui:define name="body">
        <div align="left">
            <p align="left">
                <a href="test">Click here to invoke the Facelets page</a>
            </p>
        </div>
    </ui:define>
</ui:composition>

Running the application

When the application is invoked, the welcome.html is invoked which redirects the control with the url pattern ‘spring/start’ which will ultimately invoke the file start.xhtml. From here, when the user clicks the link, the url ‘test’ will be mapped to test.xhtml file present in the directory ‘/WEB-INF/flows’. Running the above application will result in something like the following.

Sample application

That’s it. We have run the first sample application that integrates Spring Web Flow and JSF.

email

«»

Comments

comments

,