Handling Events in JavaServer Faces, Part 1
The Request Processing Lifecycle Phases
So far, so good. If you've programmed
with GUI frameworks or in other
event-driven environments, the JSF event model should look familiar.
But as I mentioned in the introduction, the fact that JSF operates
with a disconnected client that only occasionally communicates with
the server where the application runs requires a few twists to the
model.
First of all, the application may declare that the component
instances should not be saved on the server between requests, due to
memory usage concerns. JSF must then save enough information
somewhere (e.g., in the response) to be able to reconstruct the
component tree and restore all component state when it receives the
next request. In other words, component instances may come and go in
a JSF application, as opposed to a GUI application where they remain
in memory as long as the application runs.
JSF must also deal with the fact that value changes happen in the
client and that the server can't detect the changes
until it receives a new request with the new values. One possible
work-around is to add client-side scripting to the mix, so that value
changes causes an immediate request; unfortunately, that solution can
make the application feel sluggish, and it doesn't
work at all if the client doesn't support scripting.
Button and link clicks are a bit easier to deal with, because they
cause a new request always to be sent. Events corresponding to these
user actions can, however, be classified further into events that
affect only the user interface (e.g., show the next set of rows in a
table or change from a brief to a detailed display) and events that
must be processed by backend code (e.g., permanently save the values
entered in a form or finalize a reservation request). For user
interface events, the backend typically shouldn't be
bothered at all. An event that involves the backend, on the other
hand, must not be processed until all model properties have been
updated with the new values received with the request.
JSF deals with all these concerns by defining a request processing
lifecycle with well-defined phases (shown in Figure 8-1), where different activities take place and
events fire in an orderly manner at the appropriate time.

Figure 8-1. Request processing lifecycle phases
The phases are described in detail in Appendix C, but here's a quick
rundown:
-
Next, in the Apply Request Values phase, each component in
the view looks for its own value in the request and saves it.
-
When the model properties have been populated with the latest values,
event listeners may call backend code to process the
new data in the Invoke Application phase.
-
Finally, a response to the request is sent, using
the same view or a new one. This happens
in the Render Response.
If the user triggered the request by clicking a button or a link, the
corresponding UICommand component discovers this
in the Apply Request Values phase when it finds a request parameter
with a name that matches its ID. It creates an
ActionEvent to represent the event, but
doesn't notify the listeners immediately, because
the rest of the components in the tree may not have picked up their
values yet. Instead it adds it to a queue by
calling its queueEvent()
method.
At the end of the Apply Request Values phase, when all components
know about their new values, it's safe to fire an
ActionEvent that affects the user interface. JSF
asks the UICommand that queued it to notify all
listeners by calling its broadcast() method. But
as you'll see soon, that's not the
whole story: sometimes this event must not be broadcast until the
Invoke Application phase.
Value change event handling happens in the Process Validations phase
in a similar fashion, by default. A component that discovers that a
value in the request is both valid and different from its previous
value queues a ValueChangeEvent. Because the user
may have changed a number of values since the previous request, it is
likely that more than one event is queued in this phase. At the end
of the phase, JSF scans the queue and calls the broadcast(
) method on the component that queued a
ValueChangeEvent.
A listener processing an event may in turn do things that cause other
events to be queued, so JSF continues to scan the queue at the end of
a phase until the event queue is empty before moving on to the next
phase.
Handling Application Backend Events
Separate the queuing from the firing of the event is the easy part.
Dealing with the two subcategories of ActionEvent
requires one more twist. From what I've said so far,
it looks like an ActionEvent is always processed
at the end of the Apply Request Values phase, but
that's only appropriate for user interface events.
As you may recall, an ActionEvent that requires
backend processing must not be handled until the model properties are
updated, i.e., after the Update Model Values phase at the earliest.
Let's look at some real examples of action handling
using the report entry form in the sample application. We start with
events that invoke backend logic in this section and look at user
interface events in the next.
As you may recall, the report entry form has three fields for
entering a date, an expense type and an amount for a report entry,
and an Add button. Figure 8-2 shows the form
produced by the version of the page we use in this section.

Figure 8-2. The report entry form area with a few entries
The Add button is a typical example of the most common type of event
handling, namely a button that fires an event that requires
processing by the application backend. When the user clicks this
button, a new entry with the values entered in the fields is added to
the current report.
Example 8-1 shows a version of the JSP page where
the Add button is bound to an event handling method that invokes the
backend code for adding the entry.
Example 8-1. Entry form area JSP page with an Add button action reference (expense/stage2/entryFormArea.jsp)
<%@ page contentType="text/html" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
<h:form>
Title:
<h:inputText id="title" size="30" required="true"
value="#{reportHandler.currentReport.title}" />
<h:message for="title" />
<br>
Entry:
<br>
Date:
<h:inputText id="date" size="8" required="true"
value="#{entryHandler.currentEntry.date}">
<f:convertDateTime dateStyle="short" />
</h:inputText>
<h:message for="date" />
<br>
Type:
<h:selectOneMenu id="type" required="true"
value="#{entryHandler.currentEntry.type}">
<f:selectItems value="#{entryHandler.expenseTypeChoices}"/>
</h:selectOneMenu>
<h:message for="type" />
<br>
Amount:
<h:inputText id="amount" size="8" required="true"
value="#{entryHandler.currentEntry.amount}">
<f:convertNumber pattern="#,##0.00" />
<f:validateDoubleRange minimum="1"/>
</h:inputText>
<h:message for="amount" />
<br>
<h:commandButton value="Add"
disabled="#{reportHandler.addEntryDisabled}"
action="#{entryHandler.add}" />
</h:form>
<h:messages globalOnly="true" />
<%-- Loop to verify that it works --%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<ol>
<c:forEach items="${reportHandler.currentReportEntries}" var="e">
<li>Date: ${e.date}, Type: ${e.type}, Amount: ${e.amount}</li>
</c:forEach>
</ol>
</f:view>
The only real difference compared to the version of the page we used
in Chapter 7 is the action
attribute for the Add button
<h:commandButton> action element. Of less
interest at this point is the JSTL
<c:forEach> action that lists all entries in
the current report at the end of the page. I added the loop just to
verify that the Add button's event handler really
does what it's supposed to do. This loop gets the
report entries from the report handler we looked at in Chapter 6. I'm not showing you the
details here, but I promise to return to them when we replace the
plain list with a real report entries table in Chapter 10.
The action attribute contains a
method binding expression. The method binding
expression syntax is similar to that of a value binding expression.
It's a subset of the JSF EL that evaluates to a bean
method with a certain signature. In Example 8-1, the
method binding expression points to a method named
add in the EntryHandler
instance available through the entryHandler
variable. Before we look at the add() method,
let's see how it relates to the event listeners and
the request processing lifecycle we discussed earlier.