JavaServer Faces (JSF) is the Java standard technology for building component-based, event-oriented web interfaces. Like JavaServer Pages (JSP), JSF allows access to server-side data and logic. Unlike JSP, which is essentially an HTML page imbued with server-side capabilities, JSF is an XML document that represents formal components in a logical tree. JSF components are backed by Java objects, which are independent of the HTML and have the full range of Java abilities, including accessing remote APIs and databases.
This article presents a snapshot of JSF’s approach to component-based UI development for Java web applications. Simple examples introduce JSF’s MVC architecture, event model, and component library. Examples include new features in JSF 2.3, and we’ll use PrimeFaces for our component library.
While the schedule for future development is unclear, JSF 2.3 gives developers plenty to work with while we wait. Released in March 2017, JSF 2.3 was intentionally designed to modernize JSF. Among several hundred small repairs and larger updates, JSF 2.3 deprecates managed bean annotations in favor of CDI, which I’ll introduce later in this tutorial.
Building component-based web interfaces in JSF
JSF’s core idea is to encapsulate functionality into reusable components. This is similar to the reusable tags used in JSP, but JSF components are more formal.
While you can use JSF pages within JavaServer Pages, it’s more common to use Facelets to build standalone JSF pages. Facelets are XHTML pages designed for defining JSF interfaces. With Facelets, you use XML tags to create a component tree that becomes the scaffold for a JSF user interface.
Listing 1 presents the main parts of a simple JSF page written using Facelets. In this example we’re accessing Java’s server-side capabilities via a bean that’s been placed in scope via CDI. You’ll see more about CDI later on.
Listing 1. JSF sample page
<lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <lt;html xmlns=http://www.w3.org/1999/xhtml xmlns:h="http://xmlns.jcp.org/jsf/html" > <lt;h:head> <lt;title>Hello JavaWorld!<lt;/title> <lt;/h:head> <lt;body> #javaBean.content <lt;/body>
In Listing 1 we see a standard XHTML page. A Facelets view is built on top of XHTML. In addition to the XHTML namespace, a secondary namespace is defined and referenced.
h library contains standard components for use in JSF HTML pages. The
http://xmlns.jcp.org/jsf/html library defines a collection of JSF components, in this case a collection of common HTML elements. One of these components is the
HTML components in JSF
In terms of syntax, Listing 1’s
<h:head> element references the
jsf/html library with the
h prefix. It then references the specific component within the library, which is the
<h:head> component outputs the HTML head element. (All that syntax might seem like overkill for such a simple purpose, but there’s good reason for it, as you’ll see shortly.)
Inside the head is nested a standard HTML
<title> element. This element is provided to the
<h:head> component, along with the content child elements nested inside of it.
In the body of the doc, a JSF expression is contained by the
# syntax. This is exactly analogous to a JSP expression with the
$ format: it allows the access of Java objects in scope, and simple functions.
The basic pattern for JSF is simple: Use Facelets to build an XML tree that references a component library or libraries, then use components within the library to render Java objects as HTML.
Using Java objects in JSF
Going back to Listing 1, notice that inside the JSF expression (
javaBean object is in scope when this markup is executed. The XHTML of Facelets accesses the
.content property on the
javaBean object. The final output is a web interface that merges the Facelets view structure with Java’s server-side data and logic capabilities.
Using a JSF expression is just one way to access Java application data from a JSF user interface. Eventually, you’ll want to explore other ways a JSF component can interact with the Java backend–things like data lists and grids and a variety of input controls. For now, it’s enough to absorb how JSF uses XML tags (or annotations) to create a tree of components that outputs HTML based on the data contained in Java objects.
Structure of a JSF application
Like JavaServer Pages and the Servlet API, JavaServer Faces requires a standard directory structure and metadata. These are deployed as .war files.
The structure of a .war file is similar to a Servlet or JSP application. It contains a
/web-app directory, which holds the application’s markup files (in this case HTML, JSP, and Facelets), as well as a
/WEB-INF directory, which presents the metadata to describe the application.
JSF 2.3: Spec and implementations
One of Java’s strengths is that it is standards based, and those standards are governed by an open source community process. Since its inception, the Java Community Process (JCP) has overseen the development of Java technology. Once a specification or specification improvement has been developed and approved by JCP, it is available to be implemented by multiple parties. Until recently, Servlets, JSP, and JSF were all developed using JCP’s open source specification process.
The most recent JSF specification as of this writing is JSF 2.3, released as part of Java EE 8 in 2017. Oracle’s (now Eclipse’s) Mojarra is the JSF reference implementation, and MyFaces and PrimeFaces are popular third-party implementations.
Each of these frameworks implements the JSF core, which includes some standard components. Vendors may also offer additional component libraries on top of the standard. When evaluating JSF frameworks, it’s a good idea to consider the needs of your application and what component libraries are available to help you build it. Ideally, your JSF framework should get you as close as possible to what you need, right out of the box.
MVC in JSF 2.3
JSF is an MVC framework, implementing the model-view-controller pattern. In the MVC pattern, the idea is to separate the three concerns of a UI into discreet parts, so they’re easier to manage. In general, the view is responsible for displaying data in the model, and the controller is responsible for setting up the model and routing the user to the correct view.
In a JSF implementation, the view is the Facelets page with its set of XML tags. These define the layout of the user interface. The other half of using JSF is the server-side, where Java classes back those UI components.
In JSF 2.3, controller beans provide the controller part of the MVC equation. Normal Java objects (often called POJOs, or plain old Java objects) provide the model.
In terms of process flow, controller beans:
- Decide where to direct user requests
- Set up POJOs for the model
- Use the model to render the Facelets view
JSF then folds together the component tree and model to render the output HTML.
Listing 2 shows how you would define the
javaBean object from Listing 1 using CDI. This listing assumes the application has the cdi-api-1.2.jar in its dependencies.
Listing 2. A JavaBean defined using CDI
import javax.inject.Named; import javax.enterprise.context.SessionScoped; @Named @ViewScoped public class JavaBean implements Serializable private String content = ìWelcome to JSF!î // getters/setters
JSF 2.3 with PrimeFaces
In the next sections I’ll use PrimeFaces to show you how JSF implements the MVC pattern, event-driven messaging, and reusable components. To start, open up the PrimeFaces Showcase, click the Data link in the left-side column, and select DataList. This will pull up the DataList demo code for PrimeFaces.
Figure 1 shows you where to find these samples.
Figure 2 shows the output of a simple data table, which is taken from the PrimeFaces DataList demo.
PrimeFaces DataList: Accessing the data model
Listing 3 presents the markup for this
dataList display. If you scroll to the bottom of the PrimeFaces showcase, you can see the markup in the
Listing 3. Facelet for PrimeFaces DataList
<p:dataList value="#dataListView.cars1" var="car" type="ordered"> <f:facet name="header"> Basic </f:facet> #car.brand, #car.year </p:dataList>
In Listing 3, notice the
value property of the
dataList component. You can see that this references a
dataListView object, and accesses the
.cars1 property on it. The component is going to use the model object returned by that field. JSF tokens use conventional accessors to reference object properties, so
.cars1 will refer to the
getCars() getter on the object.
Next, notice the
var="car" property. This tells the
dataList component what variable to use when it iterates over the list of cars returned by the
value field. These properties are specific to the
dataList component, but the
value property is very common. The
var attribute is also conventional for components that iterate over lists.
In the body of the component in Listing 3, you can see the
car variable is accessed via JSF expressions like
#car.brand. Each iteration of the
dataListView.cars1 instance will output the
Notice that the
<f:facet...> tag demonstrates the ability to customize components for how they will display. In this case, the header is defined as
You can see how the Facelets XML will drive this output by combining the data with the markup. Now let’s look at the Java code behind it.
DataList’s server-side components
Listing 4 shows
DataListView, the Java class that is used by the markup in Listing 3. You’ll see shortly how the
dataListView instance is associated with the
Listing 4. DataListView class
package org.primefaces.showcase.view.data; import java.io.Serializable; import java.util.List; import javax.annotation.PostConstruct; import javax.inject.Named; // Pre JSF 2.3, this was: // import javax.faces.bean.ManagedBean; import javax.inject.Inject; import javax.faces.bean.ViewScoped; import org.primefaces.showcase.domain.Car; import org.primefaces.showcase.service.CarService; @Named @ViewScoped public class DataListView implements Serializable private List<Car> cars1; private Car selectedCar; @Inject("#carService") private CarService service; @PostConstruct public void init() cars1 = service.createCars(10); public List getCars1() return cars1; public void setService(CarService service) this.service = service;
Listing 4 has a few other important elements, which we’ll consider piece by piece.
Dependency injection and annotations
First, notice that the
DataListView class is annotated with
@Named, which you can see from the import
import javax.inject.Named; is part of JSF. The
@Named annotation tells JSF this bean is part of the app. The
@ViewScoped annotation informs JSF that the bean will live for just the life of the view.
Next, observe that the
CarService property has the
@Inject annotation (called the
@ManagedProperty prior to JSF 2.3). This is another JSF feature that allows beans to be “wired together,” a technique popularized by the Spring framework and other dependency injection tools. In essence, JSF will find the
carService object in scope and associate it automatically to the
service field on the
Remembering that the Facelet in Listing 3 accesses the
getCars1() method, you’ll notice that the method simply returns the
cars1 field, which is defined as a list with the line
private List cars1;. How is this list populated?
Take a look at the method
init() in Listing 4, which is annotated with the
@PostConstruct annotation. The
@PostConstruct annotation is a lifecycle hook, meaning that it allows the developer to tap into the JSF component lifecycle. The
PostConstruct informs JSF to run this code once the component has been constructed, but before it has been rendered. In the body of the
init() method, the
CarService object (previously injected into the
service field) is used to populate the
cars1 list with this line:
cars1 = service.createCars(10); .
Now let’s shoot over to the
CarService class. A service class is a class that provides services to other classes, usually by providing services to one more more controllers. Like the MVC pattern, the service class idea is common, and not unique to JSF.
Listing 5. DataListView class
package org.primefaces.showcase.service; import java.util.ArrayList; import java.util.List; import java.util.UUID; import javax.faces.bean.ApplicationScoped; import javax.inject.Named; import org.primefaces.showcase.domain.Car; @Named(name = "carService") @ApplicationScoped public class CarService private final static String colors; private final static String brands; static colors = new String; colors = "Black"; colors = "White"; // ...other colors... public List createCars(int size) List list = new ArrayList(); for(int i = 0 ; i < size ; i++) list.add(new Car(getRandomId(), getRandomBrand(), getRandomYear(), getRandomColor(), getRandomPrice(), getRandomSoldState())); return list; // Utility methods like getRandomId() have been removed
To begin, notice how the code informs JSF this is a managed class:
@Named(name = "carService"). In this case, the bean is given a name,
"carService", which we’ve seen in Listing 4 is used as a handle to reference the bean in the
DataListView controller. In addition, the class is specified as
@ApplicationScoped. In essence, that means that the object instance will live for the duration of the application.
The actual Java code for preparing the cars list should be fairly self-documenting. But how will JSF finds these beans?
JSF uses the application’s metadata to locate the beans it needs; in the past, that meta-data lived primarily in separate XML files, the
/WEB-INF/beans.xml. CDI is enabled in Java 7 by default, so that file is not required unless you need something not supported by annotation. (You no longer have to even tell JSF to use
Events in JSF
Along with being an MVC, component-based framework, JSF is an eventing framework. That means it uses events to handle interactions with users and components. We’ll conclude with a quick look at JSF’s event-oriented architecture.
Ideally, events provide a clean separation of concerns by isolating event generation code from event handling code. JSF events can be divided into two types: server-side events and client-side events.
To set up a server-side event, you would create an event handler in Java code. You would then create an event emitter (on the component markup), or an event listener, whose role is to listen for lifecycle events.
Client-side events–things like a user clicking a button in the browser–are transparently mapped to event-handlers on the server. Component events are handled in this way. For the most part, the JSF framework abstracts the actual wiring of the events. This is true even of AJAX or Websocket-style eventing.
JSF hides the details of how an event works by encapsulating those details inside one or more components. To understand how this works, go back to the DataList example and find Paginator, a
dataList that employs events.
Figure 3 presents the output of a Paginator
This list uses the same kind of structure as the
DataListView in Listing 4 to output the grid, but it has a new feature: if you click on the magnifying glass icon, you will see a popup window displaying a list of links. Listing 6 shows the component that creates those links
Listing 6. Magnifying glass links
<p:commandLink update=":form:carDetail" oncomplete="PF('carDialog').show()" title="View Detail" styleClass="ui-icon ui-icon-search" style="float:left;margin-right:10px"> <f:setPropertyActionListener value="#car" target="#dataListView.selectedCar" /> <h:outputText value="#car.brand, #car.year" /> </p:commandLink>
Listing 7 has the component that supplies the actual popup.
Listing 7. Popup component
<p:dialog header="Car Info" widgetVar="carDialog" modal="true" showEffect="blind" hideEffect="explode" resizable="false"> <!-- Dialog Content --> </p:dialog>
Note that you don’t define the function to be called; instead, it’s pre-defined by the component internals.
p:dialog component in Listing 7 has given itself a name with
JavaServer Faces is the Java standard for creating web-based UIs. As of this writing, JSF 2.3 is the current version, and the reference implementation is Eclipse Mojarra. JSF has been selected for inclusion and further development in Jakarta EE, which is good news for Java developers who want a standard way to develop modern, Java-based web UIs.
Learn more about JSF
This story, “What is JSF? Introducing JavaServer Faces” was originally published by
Share this post if you enjoyed! 🙂