Download
FAQ History |
![]() ![]() ![]() |
API
Search Feedback |
Handling Events
As explained in Event and Listener Model, the JavaServer Faces event and listener model is similar to the JavaBeans event model in that it has strongly typed event classes and listener interfaces. JavaServer Faces technology supports two different kinds of component events: action events and value-changed events.
Action events occur when the user activates a component represented by
UICommand
. These components include buttons and hyperlinks. These events are represented by thejavax.faces.event.ActionEvent
class. An implementation of thejavax.faces.event.ActionListener
handles action events.Value-changed events result in a change to the local value of a component represented by
UIInput
or one of its subclasses. One example of a value-changed event is that generated by entering a value in a text field. These events are represented by thejavax.faces.event.ValueChangedEvent
class. An implementation of thejavax.faces.event.ValueChangedListener
handles value-changed events.Both action events and value-changed events can be processed at any stage during the request processing lifecycle. Both
ActionListener
andValueChangedListener
extend from the commonFacesListener
interface.To cause your application to react to action events or value-changed events emitted by a standard component, you need to:
When emitting events from custom components, you need to manually queue the event on the
FacesContext
. Handling Events for Custom Components explains how to do this. TheUIInput
andUICommand
components automatically queue events on theFacesContext
.The rest of this section explains how to implement a
ValueChangedListener
and anActionListener
and how to register the listeners on components.Implementing an Event Listener
For each kind of event generated by components in your application, you need to implement a corresponding listener interface. Listeners that handle the action events in an application must implement
javax.faces.event.ActionListener
. Similarly, listeners that handle the value-changed events must implementjavax.faces.event.ValueChangedListener
. The cardemo application includes implementations of both of these listeners.
Note: You should not create an
ActionListener
to handle an event that results in navigating to a page. You should write anAction
class to handle events associated with navigation. SeeNavigating Between Pages for more information.ActionListeners
should only be used to handle UI changes, such as tree expansion.
By virtue of extending from
FacesListener
, both listener implementations must implement thegetPhaseId
method. This method returns an identifier fromjavax.event.PhaseId
that refers to a phase in the request processing lifecycle. The listener must not process the event until after this phase has passed. For example, a listener implementation that updates a component's model object value in response to a value-changed event should return aPhaseId
ofPhaseId.PROCESS_VALIDATIONS
so that the local values pass validation checks before the model object is updated. The phases during which events can be handled are Apply Request Events, Process Validations, and Update Model Values. If your listener implementation returns aPhaseID
ofPhaseId.ANY_PHASE
then the listener will process events during the Apply Request Values phase if possible.Implementing a Value-Changed Listener
In addition to the
getPhaseId
method, aValueChangedListener
implementation must include aprocessValueChanged(ValueChangedEvent)
method.The
processValueChanged(ValueChangedEvent)
method processes the specifiedValueChangedEvent
and is invoked by the JavaServer Faces implementation when theValueChangedEvent
occurs. TheValueChangedEvent
instance stores the old and the new values of the component that fired the event.The
cardemo
application has a new feature that updates the price of the chosen car after an extra option is selected for the car. When the user selects an option, aValueChangedEvent
is generated, and theprocessValueChanged
method of thePackageValueChanged
listener implementation is invoked. Here is theprocessValueChanged
method fromPackageValueChanged
:public void processValueChanged(ValueChangedEvent vEvent) { try { String componentId = vEvent.getComponent().getComponentId(); FacesContext context = FacesContext.getCurrentInstance(); String currentPrice; int cPrice = 0; currentPrice = (String)context.getModelValue( "CurrentOptionServer.carCurrentPrice"); cPrice = Integer.parseInt(currentPrice); if ((componentId.equals("currentEngine")) || (componentId.equals("currentBrake")) || (componentId.equals("currentSuspension")) || (componentId.equals("currentSpeaker")) || (componentId.equals("currentAudio")) || (componentId.equals("currentTransmission"))) { cPrice = cPrice - (this.getPriceFor((String)vEvent.getOldValue())); cPrice = cPrice + (this.getPriceFor((String)vEvent.getNewValue())); } else { Boolean optionSet = (Boolean)vEvent.getNewValue(); cPrice = calculatePrice(componentId, optionSet, cPrice); } currentPrice = Integer.toString(cPrice); context.setModelValue( "CurrentOptionServer.carCurrentPrice", currentPrice); } catch (NumberFormatException ignored) {} }This method first gets the ID of the component that fired the event from
ValueChangeEvent
. Next, it gets the current price of the car from theCurrentOptionServer
bean.The if statement checks if the component that fired the event is one of the
SelectItems
components. If it is, it subtracts the old value of the selected option from the current price and adds the new value of the selected option to the current price. ThegetPriceFor(String)
method returns the price of an option.If the component that fired the event is a
SelectBoolean
, the new value is retrieved from the event. ThecalculatePrice(String, Boolean, int)
method checks if the value is true. If it is, the price returned fromgetPriceFor(String)
for the selected option is added to the current price; otherwise it is subtracted from the current price.Finally the method updates the current price in the
CurrentOptionServer
bean.Implementing Action Listeners
In addition to the
getPhaseId
method, aActionListener
implementation must include aprocessAction(ActionEvent)
method.The
processAction(ActionEvent)
processes the specifiedActionEvent
and is invoked by the JavaServer Faces implementation when theActionEvent
occurs. TheActionEvent
instance stores the value ofcommandName
, which identifies the command or action that should be executed when the component associated with thecommandName
is activated.The
cardemo
application has another new feature that allows a user to select a package, which contains a set of options for their chosen car. These packages are called Custom, Deluxe, Performance, and Standard.The user selects a package by clicking on one of the buttons representing a package. When the user clicks one of the buttons, an
ActionEvent
is generated, and theprocessAction(ActionEvent)
method of theCarActionListener
listener implementation is invoked. Here is a piece of theprocessAction(ActionEvent)
method fromCarActionListener
:public void processAction(ActionEvent event) { String actionCommand = event.getActionCommand(); ResourceBundle rb = ResourceBundle.getBundle("cardemo/Resources", (FacesContext.getCurrentInstance().getLocale())); if (actionCommand.equals("custom")) { processCustom(event, rb); } else if (actionCommand.equals("standard")) { processStandard(event, rb); ... } else if (actionCommand.equals("recalculate")) { FacesContext context = FacesContext.getCurrentInstance(); String currentPackage = (String)context.getModelValue( CurrentOptionServer.currentPackage"); if (currentPackage.equals("custom")) { processCustom(event, rb); } else if (currentPackage.equals("standard")) { processStandard(event, rb); } ... }else if (actionCommand.equals("buy")) { FacesContext context = FacesContext.getCurrentInstance(); context.setModelValue("CurrentOptionServer.packagePrice", context.getModelValue( "CurrentOptionServer.carCurrentPrice")); } }This method gets the
commandName
from the specifiedActionEvent
. Each of theUICommand
components onmore.jsp
has its own uniquecommandName
, but more than one component is allowed to use the samecommandName
. If one of the package buttons is clicked, this method calls another method to process the event according to the specifiedcommandName
. For example,processStandard(ActionEvent, ResourceBundle)
sets each component's model value inCurrentOptionServer
according to the options included in the Standard package. Since the engine options allowed in the Standard package are only V4 and V6, theprocessStandard(ActionEvent, ResourceBundle)
method sets theengineOption
property to an array containing V4 and V6.If the
Recalculate
button is clicked, this method gets the value ofcurrentPackage
from theCurrentOptionServer
bean. This value corresponds to thecommandName
associated with one of the package buttons. The method then calls the appropriate method to process the event associated with the current package.If the
Buy
button is clicked, this method updates thepackagePrice
property ofCurrentOptionServer
with the current price.Registering Listeners on Components
A page author can register a listener implementation on a component by nesting either a
valuechanged_listener
tag or anaction_listener
tag within the component's tag on the page.Custom components and renderers also have the option of registering listeners themselves, rather than requiring the page author to be aware of registering listeners. See Handling Events for Custom Components for more information.
This section explains how to register the
PackageValueChanged
listener and theCarActionListener
implementations on components.Registering a ValueChangedListener on a Component
A page author can register a
ValueChangedListener
on aUIInput
component or a component that extends fromUIInput
by nesting avaluechanged_listener
tag within the component's tag on the page. Several components on themore.jsp
page have thePackageValueChanged
listener registered on them. One of these components iscurrentEngine
:<h:selectone_menu id="currentEngine" valueRef="CurrentOptionServer.currentEngineOption"><f:valuechanged_listener type="cardemo.PackageValueChanged" />
<h:selectitems valueRef="CurrentOptionServer.engineOption"/> </h:selectone_menu>The
type
attribute of thevaluechanged_listener
tag specifies the fully-qualified class name of theValueChangedListener
implementation.After this component tag is processed and local values have been validated, the component instance represented by this tag will automatically queue the
ValueChangeEvent
associated with the specifiedValueChangedListener
to theFacesContext
. This listener processes the event after the phase specified by thegetPhaseID
method of the listener implementation.Registering an ActionListener on a Component
A page author can register an
ActionListener
on aUICommand
component by nesting anaction_listener
tag within the component's tag on the page. Several components on the more.jsp page have theCarActionListener
listener implementation registered on them, as shown by thecustom
tag:<h:command_button id="custom" commandName="custom" commandClass="package-selected" key="Custom" bundle="carDemoBundle"><f:action_listener type="cardemo.CarActionListener" />
</h:command_button>The component tag must specify a
commandName
that specifies what action should be performed when the component is activated. TheActionEvent
is constructed with the component ID and thecommandName
. More than one component in a component tree can have the samecommandName
if the same command is executed for those components.The
type
attribute of theaction_listener
tag specifies the fully-qualified class name of theActionListener
implementation.When the component associated with this tag is activated, the component's
decode
method (or its associatedRenderer
) automatically queues theActionEvent
associated with the specifiedActionListener
to theFacesContext
. This listener processes the event after the phase specified by thegetPhaseID
method of the listener implementation.
Download
FAQ History |
![]() ![]() ![]() |
API
Search Feedback |
All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.