The Java Web Development Series

What is JSF? Introducing JavaServer Faces

Find out what's new in JSF 2.3, the Java standard for developing component-based, event-oriented web UIs

1 2 Page 2
Page 2 of 2

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 DataListView object.

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.

paginator table Matthew Tyson

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

1 2 Page 2
Page 2 of 2