Abstract

The JavaServer Faces (JSF) 2.0 is the newest Java presentation technology that is covered in JSR-314 and was publicly released on July 01, 2009. It became a part of the JEE6 standard and can be comfortably used in conjunction with other JEE frameworks, with Spring or just on its own. This article reveals the possible scenarios and shows the required configuration for the usage of JSF 2.0 with EJB 3.1 and with Spring 3.0. It also discusses several auxilary technologies which can be used along with JSF 2.0.

Management Summary

There are many presentation frameworks available, so why JSF 2.0? The short answer is simple: it has an extensible component-oriented presentation layer and event-driven programming model, which both abstract from HTML/JS and leverage the developement. In more detail, the most important features are:

  • Facelet Support
  • Validation & Conversion Mechanisms
  • Resources Support
  • Templating
  • Expression Language
  • Annotation Support

JSF 2.0 makes strong use of the SoC (Separation of Concerns) principle, promoting the MVC (Model View Controller) design pattern. Its declarative view is based on facelets: the view documents can be defined using XHTML. These documents build their own component tree from the core or third-party components. The use of special composition elements allows effective templating. The model or/and the controller are realized using so called backing beans / managed beans. A backing bean is an annotated POJO (Plain Old Java Object). The access from the view to the backing beans is possible using the expression language. The navigation can be influenced directly from the view or from the backing beans, by pointing to the logical names of the pages. JSF offers a flexible validation model, which suports Bean Validation (JSR 303) out of the box.

Presentation with JSF 2.0

This chapter discusses the model of the presentation used in JSF 2.0.

Initial setup

A JSF project is an ordinary Java Web project. The result of it runs inside of a web container, like Tomcat or Jetty. A characteristical descriptor has to contain the servlet definitions/mappings of the JSF servlet and third-party component servlets. Here is an exammple for JSF 2.0 and Prime Faces, an open-source component library.

<web-app xmlns=".../javaee" xmlns:xsi="..."
	xsi:schemaLocation=".../web-app_2_5.xsd" version="2.5">
...
	<!-- Activating the Expression Language -->
	<context-param>
		<param-name>com.sun.faces.expressionFactory</param-name>
		<param-value>com.sun.el.ExpressionFactoryImpl</param-value>
	</context-param>

	<!-- Java Server Faces Servlet -->
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<!--  Prime Faces Resource loading -->
	<servlet>
		<servlet-name>Resource Servlet</servlet-name>
		<servlet-class>org.primefaces.resource.ResourceServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<!-- Java Server Faces Servlet Mapping -->
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
	</servlet-mapping>
	<!--  Prime Faces Resource loading -->
	<servlet-mapping>
		<servlet-name>Resource Servlet</servlet-name>
		<url-pattern>/primefaces_resource/*</url-pattern>
	</servlet-mapping>
...
</web>

The View

The definition of a JSF presentation is relatevely simple. Just create a simple XHTML document and import the JSF namespaces in the header.

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:p="http://primefaces.prime.com.tr/ui">
	 <f:loadBundle var= "msgs" basename= "ViewMessages" />
	 <h:head>
		 <title>#{msgs.welcomeTitle}</title>
		 <h:outputStylesheet library="css" name="default.css" target="head"/>
	 </h:head>
	 <h:body>
		 <p:dataTable id= "customers" value="#{cusomterProvider.customer}" var="customer">
			 <p:column>
				 <h:outputText id="customerName" value="#{customer.name}" />
			 </p:column>
			...
		 </p:dataTable>
	 </h:body>
</html>

Please note, that along with the JSF core components, the PrimeFaces component dataTable is used. At runtime the components will be transformed into the corresponding HTML elements.

The Backing Bean

In the previos example, special strings have been used #{customerProvider.customers} and #{customer.name}. Both of them are expressions specified in the Expression Language. This language allows to address elements known inside the application. The customer.name accesses the property name of the variable defined inside the iteration over the elements delivered from the customerProvider.getCustomers(). The customerProvider is a Java Object that delivers data to the view and is called Backing Bean. A Backing Bean is a serializeable POJO, that is attached to the view. It can be declared using JSF Annotation javax.faces.ManagedBean, using the ManagedBean element of the faces-config.xml or by other mechanisms compatible with the Expression Language resolvers.

@ManagedBean
@SessionScope
public class CustomerProvider
{
	public List <Customer > getCustomers()
	{
		...
	}
}

Internationalization

Internationalization is an important requirement for the presentation layer. In the previous example, a special string has been used #{msgs.welcomeTitle} to provide a message. The msgs variable is bound to a resource file, containing the localized messages, so the #{msgs.welcomeTitle} is pointing to the key welcomeTitle inside the property file.

Validation

Input validation is another important requirement for web applications. Especially, the ability to validate parts of the input using technologies like AJAX has to be supported in order to deliver the state-of-the-art technology. JSF fosters numerous different validation approaches. For example:

...
 <h:inputText id="customerName" value="#{customerService.current.name}" required= "true" />
	 <f:validateLength minimum="7 "/>
 </h:inputText>
 <h:message for="customerName"/>
...

Please note, that in the example above, the input of the customer name is mandatory and the minimum length is seven.

Another validation approach is defined in the Bean Validation Standard (JSR 303) and is supported if the components are deployed and available. According to JSR 303, the data container can define format constraints which can be used for purposes of validation. There is a set of predefined constraints available, which can be extended by custom constraints. For example:

public class Customer
{
	@Size(min=2, max=50, message= "Customer name must be at least 2 and at most 50 characters long. ")
	private String name;
	// getters and setters
	...
}

This example shows that the customer name has to be at least two and at most fifty characters long and defines a custom error message which is displayed on violation. Remember the previous section Internationalization? Yes, the validation error message can be localized too, by suppliying EL-expressions instead of the message description:

public class Customer
{
	@Size(min=2, max=50, message= "{customerNameError} ")
	private String name;
	// getters and setters
	...
}

Thus, the value of {customerNameError} (without a #) is a key in the file which must be named ValidationMessages.properties and must be available on classpath.

JSF 2.0 with other frameworks

The use of JSF fosters comfort in implementing the presentation tier. The presentation-tier is usually built on top of the business logic layer. The latter can be implemented using different technolgies.

JSF 2.0 and EJB 3.1

Enterprise Java Beans is a standard way to implement business logic inside JEE applications. The current EJB 3.1 specification fosters the usage of Stateless and Statefull Session Beans for this purpose. Since JEE6-compliant servers support Context and Dependency Injection (CDI) and the EJB and Resource Injection, the session beans can be directly referenced from the backing beans. JSF 2.0 is also a part of the JEE 6, every JEE-compliant server will support JSF out-of-the-box, too.

@ManagedBean
public class CustomerProvider
{
	@EJB
	private CustomerService service;
	...
}

JSF 2.0 and Spring 3.0

If you don’t want to run a full-blown JEE server, but a web-container only, you have to include some libraries into your application deployment.

This list will be extended by libraries required to run the Spring framework. In order to activate Spring, the context listeners have to be activated. The application context parameter can be provided as a context parameter.

 <!-- Spring Activation -->
 <listener>
	 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <listener>
	 <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
 </listener>
 <context-param>
	 <param-name>contextConfigLocation</param-name>
	 <param-value>/WEB-INF/spring-config.xml</param-value>
 </context-param>

In addition, the Expression Language variable resolvers of JSF should be replaced by those from Spring. This is configured in the faces-config.xml

<faces-config 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-facesconfig_2_0.xsd"
	version="2.0">
	<application>
		<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
	</application>
</faces-config>

In order to enable the Spring’s IoC (Inversion of Control), we need to activate the component scan in the application-context configuration file:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="..." xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="...">

	<context:component-scan base-package="de.techjava">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Service" />
	</context:component-scan>
</beans>

Instead of using JSF for resolving the backing beans, the Spring framework can be used. The backing bean is annotated with the Spring annotation Controller. The controller is a special kind of Spring component, which is used in the presentation layer. The Spring’s way of implementing business logic is to provide Spring services. Spring service has to be annotated with Service annotation.

@Controller
@Scope( "session ")
public class CustomerProvider implements Serializable
{
	@Inject
	private CustomerService customerService;
	...
}

@Service
@Scope( "singleton ")
public class CustomerServiceImpl implements CustomerService
{
	...
}

This is not as elegant as inside the JEE server, but it will work.

References