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?
Lifecycle hooks
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);
.
Service classes
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[10];
colors[0] = "Black";
colors[1] = "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?
Bean metadata
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 bean-discovery-mode="all
).
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.
Component-managed events
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 dataList
.
Figure 3. Paginator dataList with events
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>
By carefully studying Listings 6 and 7, it becomes clear that in JSF, JavaScript eventing is handled by components. In Listing 6, the JavaScript oncomplete
event is used to fire JavaScript code: oncomplete="PF('carDialog').show()"
.
Note that you don't define the function to be called; instead, it's pre-defined by the component internals.
The p:dialog
component in Listing 7 has given itself a name with widgetVar="carDialog
. The work to unite these two into a functioning JavaScript dialog is handled by the PrimeFaces framework and the components themselves.
Conclusion
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
- "Looking at the brand new JSF 2.3: New features for an old favorite" (Josh Juneau, Jaxenter.com) is an overview of JSF 2.3, including highlights not covered here.
- "Get started with Servlet 4.0" (Alex Theedom, IBM Developer) includes a section on Servlet 4.0 updates in JSF 2.3, primarily for HTTP/2 and server push.
- Take what you've learned to the next level, with "Learn to fully leverage JavaServer Faces" (Eugen Paraschiv, Stackify).
This story, "What is JSF? Introducing JavaServer Faces" was originally published by JavaWorld.