Webcam Chat QuickBooks Advice international calling cards international phone cards
JavaBeat Certifications Certifications Kits Articles Tutorials Tips QNA Book Store Interview Questions SCJP 1.5 SCJP 1.6 SCWCD 5.0 SCBCD 5.0 SCEA SCJA Feeds
Kaspersky Anti-Virus 2011
Submit Your Blog Feedback Request Article Print Email

Spring Faces

Author : JavaBeat
Topic : spring books 
Pages :
Hibernate Books | Spring Books | JSF Books | Java Books
Title : Spring Faces
Publisher : JavaBeat
Topic : spring
Related : Hibernate, Spring, Struts, ejb
Javabeat : Tips, Java / J2EE Tutorials, Certifications

Spring Faces

The main focus of the Spring Web Flow framework is to deliver the infrastructure to describe the page fl ow of a web application. The fl ow itself is a very important element of a web application, because it describes its structure, particularly the structure of the implemented business use cases. But besides the fl ow which is only in the background, the user of your application is interested in the graphical user interface (GUI). Therefore, we need a solution of how to provide a rich user interface to the users. One framework which offers components is JavaServer Faces (JSF). With the release of Spring Web Flow 2, an integration module to connect these two technologies has been introduced. The name of the module is Spring Faces. This chapter starts with the description of the configuration of the integration. Following this, the usage of the Spring Faces module is shown. This chapter is no introduction to the JavaServer Faces technology. It is only a description about the integration of Spring Web Flow 2 with JSF. If you have never previously worked with JSF, please refer to the JSF reference to gain knowledge about the essential concepts of JavaServer Faces.


	JavaServer Faces (JSF)—a brief introduction
	The JavaServer Faces (JSF) technology is a web application framework
	with the goal to make the development of user interfaces for a web
	application (based on Java EE) easier. JSF uses a component-based
	approach with an own lifecycle model, instead of a request-driven
	approach used by traditional MVC web frameworks. The version 1.0
	of JSF is specified inside JSR (Java Specification Request) 127
	(http://jcp.org/en/jsr/detail?id=127).

Enabling Spring Faces support

To use the Spring Faces module, you have to add some configuration to your application. The diagram below depicts the single configuration blocks. These blocks are described in this chapter.

The first step in the configuration is to configure the JSF framework itself. That is done in the deployment descriptor of the web application—web.xml. The servlet has to be loaded at the startup of the application. This is done with the <load-on-startup>1</load-on-startup> element.


	<!-- Initialization of the JSF implementation. The Servlet is not
	  used at runtime -->
	<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>
	
	For the work with the JavaServer Faces, there are two important classes.
	These are the javax.faces.webapp.FacesServlet and the
	javax.faces.context.FacesContext classes.
	You can think of FacesServlet as the core base of each JSF application.
	Sometimes that servlet is called an infrastructure servlet. It is important
	to mention that each JSF application in one web container has its own
	instance of the FacesServlet class. This means that an infrastructure
	servlet cannot be shared between many web applications on the same
	JEE web container.
	FacesContext is the data container which encapsulates all information
	that is necessary around the current request.
	For the usage of Spring Faces, it is important to know that
	FacesServlet is only used to instantiate the framework. A further
	usage inside Spring Faces is not done.

To be able to use the components from Spring Faces library, it's required to use Facelets instead of JSP. Therefore, we have to configure that mechanism.


	If you are interested in reading more about the Facelets technology,
	visit the Facelets homepage from java.net with the following URL:
	https://facelets.dev.java.net. A good introduction inside the
	Facelets technology is the http://www.ibm.com/developerworks/
	java/library/j-facelets/ article, too.

The configuration process is done inside the deployment descriptor of your web application—web.xml. The following sample shows the configuration inside the mentioned file.


	<context-param>
		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
		<param-value>.xhtml</param-value>
	</context-param>

As you can see in the above code, the configuration parameter is done with a context parameter. The name of the parameter is javax.faces.DEFAULT_SUFFIX. The value for that context parameter is .xhtml.

Inside the Facelets technology

To present the separate views inside a JSF context, you need a specific view handler technology. One of those technologies is the well-known JavaServer Pages (JSP) technology. Facelets are an alternative for the JSP inside the JSF context. Instead, to define the views in JSP syntax, you will use XML. The pages are created using XHTML.

The Facelets technology offers the following features:

  • A template mechanism, similar to the mechanism which is known from the Tiles framework
  • The composition of components based on other components.
  • Custom logic tags
  • Expression functions
  • With the Facelets technology, it's possible to use HTML for your pages. Therefore, it's easy to create the pages and view them directly in a browser, because you don't need an application server between the processes of designing a page
  • The possibility to create libraries of your components

The following sample shows a sample XHTML page which uses the component aliasing mechanism of the Facelets technology.


	<!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:h="http://java.sun.
	  com/jsf/html">
		<body>
			<form jsfc="h:form">
				<span jsfc="h:outputText" value="Welcome to our page: #{user.name}"
				  disabled="#{empty user}" />
				<input type="text" jsfc="h:inputText" value="#{bean.theProperty}"/>
				<input type="submit" jsfc="h:commandButton" value="OK"
				  action="#{bean.doIt}" />
			</form>
		</body>
	</html>

The sample code snippet above uses the mentioned expression language (for example, the #{user.name} expression accesses the name property from the user instance) of the JSF technology to access the data.


	What is component aliasing
	One of the mentioned features of the Facelets technology is that it is
	possible to view a page directly in a browser without that the page is
	running inside a JEE container environment. This is possible through the
	component aliasing feature. With this feature, you can use normal HTML
	elements, for example an input element. Additionally, you can refer to
	the component which is used behind the scenes with the jsfc attribute.
	An example for that is <input type="text" jsfc="h:inputText"
	value="#{bean.theProperty}" /> . If you open this inside a
	browser, the normal input element is used. If you use it inside your
	application, the h:inputText element of the component library is used.

The ResourceServlet

One main part of the JSF framework are the components for the GUI. These components often consist of many files besides the class files. If you use many of these components, the problem of handling these files arises. To solve this problem, the files such as JavaScript and CSS (Cascading Style Sheets) can be delivered inside the JAR archive of the component.


	If you deliver the file inside the JAR file, you can organize the components
	in one file and therefore it is easier for the deployment and maintenance of
	your component library.

Regardless of the framework you use, the result is HTML. The resources inside the HTML pages are required as URL. For that, we need a way to access these resources inside the archive with the HTTP protocol. To solve that problem, there is a servlet with the name ResourceServlet (package org.springframework.js.resource).

The Servlet can deliver the following resources:

  • resources which are available inside the web application (for example, CSS files)
  • resources inside a JAR archive

The configuration of the Servlet inside web.xml is shown below.


	<servlet>
		<servlet-name>Resource Servlet</servlet-name>
		<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>Resource Servlet</servlet-name>
		<url-pattern>/resources/*</url-pattern>
	</servlet-mapping>

It is important that you use the correct url-pattern inside servlet-mapping. As you can see in the sample above, you have to use /resources/*. If a component does not work (from the Spring Faces components), first check if you have the correct mapping for the Servlet. All resources in the context of Spring Faces should be retrieved through this Servlet. The base URL is /resources.

Internals of the ResourceServlet

ResourceServlet can only be accessed via a GET request. The ResourceServlet servlet implements only the GET method. Therefore, it's not possible to serve POST requests. Before we describe the separate steps, we want to show you the complete process, illustrated in the diagram below.

For a better understanding, we choose an example for the explanation of the mechanism which is shown in the previous diagram. Let us assume that we have registered the ResourcesServlet as mentioned before and we request a resource by the following sample URL: http://localhost:8080/ flowtrac-web-jsf/ resources/css/test1.css..


	How to request more than one resource with one request
	First, you can specify the appended parameter. The value of the
	parameter is the path to the resource you want to retrieve. An example
	for that is the following URL: http://localhost:8080/ flowtracweb-
	jsf/resources/css/test1.css?appended=/css/test2.
	css. If you want to specify more than one resource, you can use the
	delimiter comma inside the value for the appended parameter. A
	simple example for that mechanism is the following URL: http://
	localhost:8080/ flowtrac-web-jsf/resources/css/test1.
	css?appended=/css/test2.css, http://localhost:8080/
	flowtrac-web-jsf/resources/css/test1.css?appended=/
	css/test3.css. Additionally, it is possible to use the comma delimiter
	inside the PathInfo. For example: http://localhost:8080/
	flowtrac-web-jsf/resources/css/test1.css,/css/test2.
	css. It is important to mention that if one resource of the requested
	resources is not available, none of the requested resources is delivered.
	This mechanism can be used to deliver more than one CSS in one request.
	From the view of development, it can make sense to modularize your
	CSS files to get more maintainable CSS files. With that concept, the client
	gets one CSS, instead of many CSS files. From the view of performance
	optimization, it is better to have as few requests for rendering a page as
	possible. Therefore, it makes sense to combine the CSS files of a page.
	Internally, the files are written in the same sequence as they are requested.

To understand how a resource is addressed, we separate the sample URL into the specific parts. The example URL is a URL on a local servlet container which has an HTTP connector at port 8080. See the following diagram for the mentioned separation.

The table below describes the five sections of the URL that are shown in the previous diagram.

request url request url is the complete URL. You can retrieve it with the help of the getRequestURL method from HttpServletRequest.
request uri This is the URL without the server information. You can retrieve it with the help of the getRequestURI method from HttpServletRequest.
context path The name of the servlet context. You can retrieve it with the help of the getContextPath method from HttpServletRequest.
servlet path The name of the servlet. You can retrieve it with the help of the getServletPath method from HttpServletRequest.
path info path info is the part of the URL after the name of the servlet and before the first parameter begins. In other words, before the query sign starts. The reason for that parameter type is to have the possibility to provide a servlet (or a CGI script) with a complete absolute filename. You can retrieve it with the help of the getPathInfo method from HttpServletRequest.

Step 1: Collect the requested resources

The GET method of ResourceServlet calls the internal getRequestResourceURLs method , which fetches the path info and appends the value from the appended parameter. As a delimiter, a comma is used. At the end, the complete string is separated to an array.

Step 2: Check whether the path is allowed or not

The first step for each resource is to check whether the specified path is allowed to be retrieved or not, because it is not appropriate to allow the deliverance of the class or library files inside the secured WEB-INF directory. That check is done through the internal method called isAllowed of ResourceServlet. At first, it is validated whether the path is a protected path or not. The protected path is /?WEBINF/.*. That means everything inside the /WEB-INF directory can not be delivered with ResourceServlet. The protected path (stored inside private final variable protectedPath) can not be changed.


	With the protection of the WEB-INF directory, it's ensured that there will
	be a web application, which is compliant to the Servlet specification. In
	that specification, all content inside the WEB-INF directory cannot be
	accessed. With the protectedPath variable, it is ensured that there is no
	possibility to directly address a resource. If you want to change that, you
	have to write your own ResourceServlet, an extension of the existing
	servlet does not help in that case.

The next check is whether the specified path is inside the list of allowed paths (stored inside the allowedResourcePaths array. The array is implemented as a private instance variable of the String[] type). The following paths are allowed in the default implementation:

  • /**/*.css
  • /**/*.gif
  • /**/*.ico
  • /**/*.jpeg
  • /**/*.jpg
  • /**/*.js
  • /**/*.png
  • META-INF/**/*.css
  • META-INF/**/*.gif
  • META-INF/**/*.ico,
  • META-INF/**/*.jpeg
  • META-INF/**/*.jpg
  • META-INF/**/*.js
  • META-INF/**/*.png•

The paths are in Ant-style (http://ant.apache.org) path patterns. The paths are checked through an implementation of the PathMatcher class (package org.springframework.util).


	The class which implements the Ant-Style is the AntPathMatcher class
	inside the same package as the interface. Both are inside the Spring Core
	framework. You can use it without the other parts of the Spring framework
	(maybe in your own classes to have an ant-like resource selecting, too). You
	only need a dependency to the spring-core-x.x.x.jar library (in the
	case of version 2.5.4, spring-core-2.5.4.jar).

If you want to allow other parameters, there is a public method called setAllowedResourcePaths. ResourceServlet, which extends from HttpServletBean (package org.springframework.web.servlet). This servlet implements the opportunity to configure a servlet in a Spring way. That means for each init parameter inside the web.xml file, a setter method on the servlet is called. In our case, if you have an init parameter allowedPaths, the setAllowedPaths method is called. See an example for the configuration below.


	<servlet>
		<servlet-name>Resource Servlet</servlet-name>
		<servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
		<init-param>
			<param-name>allowedResourcePaths</param-name>
			<param-value>/**/*.png,/**/*.css</param-value>
		</init-param>
	</servlet>

In most of the cases, you want to specify more than one value for the allowedResourcePaths parameter. Therefore, the usage of a comma to separate the values is preferred. Unfortunately, the default implementation does not convert that value into an array. If you want to use a comma as a delimiter for the values, you have to manually register StringArrayPropertyEditor inside the org. springframework.beans.propertyeditors package. An easy way to implement this is to overwrite the initBeanWrapper method of ResourceServlet.


	@Override
	protected void initBeanWrapper(BeanWrapper bw) throws
	BeansException {
		bw.registerCustomEditor(String[].class, new
		StringArrayPropertyEditor());
	}

Finally, we want to show how to use such a servlet inside the web deployment descriptor of your web application. Just assume that the servlet has the name ResourceServlet and is inside the flowtrac.swf.extension.resources sample package. The configuration is done as shown below.


	<servlet>
		<servlet-name>Resource Servlet</servlet-name>
		<servlet-class>flowtrac.swf.extension.resources.
			ResourceServlet</servlet-class>
		<load-on-startup>0</load-on-startup>
		<init-param>
			<param-name>allowedResourcePaths</param-name>
			<param-value>/**/*.tss,/**/*.css</param-value>
		</init-param>
	</servlet>

	Just remember: If the resource is not allowed, the isAllowed method
	returns false and the servlet delivers no resource for the actual request.

Step 3: Try to load from the servlet context

The next step after the positive check on allowance is to try to load the resource within the servlet context. This is done with the getServletContext().getResou rce(resourcePath) expression. Do not confuse the load from the servlet context with a load from the classpath. With that method, you only get resources which are reachable directly through a filesystem access. There is no search done. That means the specified resourcePath is relative to the base directory of the web application.

Step 4: Load from the classpath

I f the resource cannot be found, the META-INF path (that prevents from delivering classes which are on the classpath) is prefixed to the path of the resource. The next step is to try to load the resource with the classloader. This is done with the ClassUtils.getDefaultClassLoader().getResource(resourcePath) helper method. The ClassUtils utility class is inside the org.springframework.util package of the spring-core library. If no resource is found, the method returns null and no resource is delivered by the actual request.

Step 5: Stream the resources

Each resource is now written as a separate byte stream.


	Remember if you request more than one resource, the resources are only
	delivered if all of the resources could be found from ResourceServlet.
	If one of the requested resources could not be found (or not allowed),
	none of the requested resources is delivered.

For the usage of ResourceServlet, dependency to the org.springframework.js library is necessary.

Configuration of the application context

The next step is to configure the application context which is used for the Spring Web Flow project. This is done in the deployment descriptor of the web application. We use the same technique as in the samples in the chapters before. For our example, we choose the name web-application.config.xml in the /WEB-INF/config directory.


	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/config/web-application-config.xml
		</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.
			ContextLoaderListener</listener-class>
	</listener>

The configuration of web.xml is now complete. For the simple purpose of an overview, we repeat the configuration steps below:

  • Configure the Resources Servlet
  • Configure contextConfigLocation
  • Configure the Faces Servlet
  • Configure faces.DEFAULT_SUFFIX

After we have configured the used file for the configuration of the application context, it is time to configure the application context itself. For that case, we have to add an additional XSD file (http://www.springframework.org/schema/faces/ spring-faces-2.0.xsd). Therefore, the header of the file is extended with the definition of that grammar under the accessor faces.


	<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		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">

The integration of JSF into Spring Web Flow is done through the configuration of a special parser which creates builders for the integration. To register that parser, the following line is added to the application context configuration file:


	<faces:flow-builder-services id="facesFlowBuilderServices" />

In the case of the usage of the faces: prefix in the XML configuration file, the FacesNamespaceHandler class (package: org.springframework.faces.config) is used to handle the tags. The class is extended from NamespaceHandlerSupport (package: org.springframework.beans.factory.xml) and implements only the init method. The implementation of the method is shown below.


	public void init() {
		registerBeanDefinitionParser("flow-builder-services", new
		FacesFlowBuilderServicesBeanDefinitionParser());
	}

As you can see, the method creates an instance of FacesFlowBuilderServicesBeanDefinitionParser, which resides inside the org.springframework.faces.config package. Besides the definition of facesFlowBuilderServices, it is important to provide that instance to flow-registry. The instance can be provided with the help of the flow-builder-services attribute of the flow-registry.


	<webflow:flow-registry id="flowRegistry" flow-builder-services="facesF
	  lowBuilderServices">
		<webflow:flow-location path="/WEB-INF/issue/add/add.xml" />
	</webflow:flow-registry>

W ith the registration of facesFlowBuilderServices, some other default classes for the JSF integration are instantiated. It is possible to change the default behavior. To better understand what is customizable, we look at the FacesFlowBuilderServicesBeanDefinitionParser class. The class defines some internal constants which are used through the process of parsing the XML configuration file. The following diagram shows the class diagram of FacesFlowBuilderServicesBeanDefinitionParser.

There are five important attributes that you can configure in the faces:flowbuilder- services tag. These attributes infl uence the behavior of the application. Therefore, it is important to understand the meaning of the attributes. The attributes are evaluated through FacesFlowBuilderServicesBeanDefinitionParser. The diagram below shows the sequence of the evaluation of the attributes. The evaluation of the attributes is done in four or five steps. The number of steps depends on the value of the enable-managed-beans attribute. The value is of the Boolean type.

Step 1: Evaluation of the enable-managed-beans attribute.

Step 2: If the enable-managed-beans attribute is set to false, the expression-parser value is evaluated.

Step 3: Evaluate the formatter-registry attribute.

Step 4: Evaluate the conversion-service attribute.

Step 5: Evaluate the view-factory-creator attribute.

The doParse internal method is called from the AbstractSingleBeanDefinitionParser class. The doParse method has to be provided with an instance of the BeanDefinitionBuilder class inside the org.springframework.beans.factory.support package. That instance is created inside the parseInternal method of AbstractSingleBeanDefinitionParser. The instance is created with the genericBeanDefinition static method of the BeanDefinitionBuilder class.

After the evaluation sequence, we describe the meaning of the attributes.

Name of the attribute Description
enable-managed-beans
JSF uses the concept of managed beans. In the context of the
Spring framework, there is a concept of Spring beans. If you
want to use the managed beans facility of JSF, you have to
provide the enable-managed-beans attribute. The attribute
is a boolean attribute. If you set that attribute to true, the
JsfManagedBeanAwareELExpressionParser class (package: org.
springframework.faces.webflow) is used for the evaluation of the
referenced beans inside the fl ow. Otherwise, the expression-parser
attribute is evaluated.
The default value for that attribute is false.
expression-parser
If the enable-managed-beans attribute is not set or set to
false, the expression-parser attribute is evaluated. With
that attribute, you can provide a specific parser of the expression
which is used inside the fl ow. If the value is not set, a new instance
of the WebFlowELExpressionParser class (package: org.
springframework.webflow.expression.el) is created.
That instance is created with an ExpressionFactory by
using the createExpressionFactory static method of the
DefaultExpressionFactoryUtils class. The default expression
factory is org.jboss.el.ExpressionFactoryImpl.
formatter-registry
A formatter registry is the class which creates or provides the formatter
for a specific class. With a formatter from the org.springframework.
binding.format.Formatter type, you can format a specific class for
the output. Additionally, a formatter provides a method called parse
to create the specific class. If you do not provide that attribute, a default
formatter registry is created with the getSharedInstance method of
the DefaultFormatterRegistry class.
That registry has formatters for the following classes: Integer (for
numbers, a NumberFormatter inside the org.springframework.
binding.format.formatters package is used), Long, Short,
Float, Double, Byte, BigInteger, BigDecimal, Boolean (for
Boolean, a BooleanFormatter inside the org.springframework.
binding.format.formatters package is registered) and Date (for
Date, a DateFormatter inside the org.springframework.binding.
format.formatters package is registered).
DefaultFormatterRegistry extends the
GenericFormatterRegistry class from the org.springframework.
binding.format.registry package. If you want to implement your
own formatter registry, it could be a choice to extend from that class.
conversion-service
A conversion service is responsible to provide instances of
ConversionExecutor (package: org.springframework.
binding.convert) for a specific class. A conversion service is from
type ConversionService (package: org.springframework.
binding.convert). A conversion service converts a source object
into a specific target object. If no value for the conversion-service
attribute is provided, an instance of the FacesConversionService
class (package: org.springframework.faces.model.converter)
is registered. The class extends DefaultConversionService. If
you implement your own conversion service, you could extend from
GenericConversionService (package: org.springframework.
binding.convert.service). This default implementation
registers the following four converters: TextToClass (the
FacesConversionService class registers on the TextToClass
converter an alias for the DataModel class from the javax.model.
DataModel. TextToClass package converts a piece of text to a class.),
TextToBoolean, TextToLabeledEnum and TextToNumber.
view-factory-creator
A view factory creator is responsible to provide a view factory. A
view factory creator is from type ViewFactoryCreator (package:
org.springframework.webflow.engine.builder). Such a
ViewFactoryCreator is responsible for creating instances from
type ViewFactory (package: org.springframework.webflow.
execution). If the value for the view-factory-creator attribute
is not provided, an instance of the JsfViewFactoryCreator class
(package: org.springframework.faces.webflow) is registered.
That class creates instances of JsfViewFactory (package: org.
springframework.faces.webflow).

The next step is the configuration of JSF itself. This is done in faces-config.xml, which can be located inside the WEB-INF directory.


	<?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>

Recommended Books

Submit Your Blog Feedback Request Article Print Email

Java / J2EE Tutorials

Spring Framework

Hibernate Framework

JSF Framework

Struts Framework

Java Server Pages(JSP)

Servlets

Java / J2EE Design Patterns

SCJP

SCEA


JavaBeat Website (2004-2009), India
javabeat | advertise | about us | useful resources
Copyright (2004 - 2009), JavaBeat