SeamFramework.orgCommunity Documentation
When the seam-faces module is installed in a web application, JSF events will automatically be propagated via the CDI event-bridge, enabling managed beans to easily observe all Faces events.
There are two categories of events: JSF phase events, and JSF system events. Phase events are triggered as JSF processes each lifecycle phase, while system events are raised at more specific, fine-grained events during request processing.
A JSF phase listener is a class that implements javax.faces.event.PhaseListener
and
is registered in the web application's faces-config.xml
file. By implementing the methods of the
interfaces, the user can observe events fired before or after any of the six lifecycle phases of a JSF request:
restore view
, apply request values
, process validations
,
update model values
, invoke application
or render view
.
In order to observe events in an EJB JAR, the beans.xml file must be in both the WEB-INF folder of the WAR, and inside the EJB JAR containing the observer.
What Seam provides is propagation of these Phase events to the CDI event bus; therefore, you can observe events
using normal CDI @Observes
methods. Bringing the events to CDI beans removes the need to
register phase listener classes via XML, and gives the added benefit of injection, alternatives, interceptors
and access to all other features of CDI.
Creating an observer method in CDI is simple; just provide a method in a managed bean that is annotated with
@Observes
. Each observer method must accept at least one method parameter: the event object;
the type of this object determines the type of event being observed. Additional parameters may also be specified,
and their values will be automatically injected by the container as per the CDI specification.
In this case, the event object passed along from the phase listener is a
javax.faces.event.PhaseEvent
. The following example observes all Phase events.
public void observeAll(@Observes PhaseEvent e)
{
// Do something with the event object
}
Events can be further filtered by adding Qualifiers. The name of the method itself is not significant. (See the CDI Reference Guide for more information on events and observing.)
Since the example above simply processes all events, however, it might be appropriate to filter out some events
that we aren't interested in. As stated earlier, there are six phases in the JSF lifecycle, and an event is
fired before and after each, for a total of 12 events. The @Before
and
@After
"temporal" qualifiers can be used to observe events occurring only before or only after
a Phase event. For example:
public void observeBefore(@Observes @Before PhaseEvent e)
{
// Do something with the "before" event object
}
public void observeAfter(@Observes @After PhaseEvent e)
{
// Do something with the "after" event object
}
If we are interested in both the "before" and "after" event of a particular phase, we can limit them by adding a "lifecycle" qualifier that corresponds to the phase:
public void observeRenderResponse(@Observes @RenderResponse PhaseEvent e)
{
// Do something with the "render response" event object
}
By combining a temporal and lifecycle qualifier, we can achieve the most specific qualification:
public void observeBeforeRenderResponse(@Observes @Before @RenderResponse PhaseEvent e)
{
// Do something with the "before render response" event object
}
This is the full list of temporal and lifecycle qualifiers
Qualifier | Type | Description |
---|---|---|
@Before | temporal | Qualifies events before lifecycle phases |
@After | temporal | Qualifies events after lifecycle phases |
@RestoreView | lifecycle | Qualifies events from the "restore view" phase |
@ApplyRequestValues | lifecycle | Qualifies events from the "apply request values" phase |
@ProcessValidations | lifecycle | Qualifies events from the "process validations" phase |
@UpdateModelValues | lifecycle | Qualifies events from the "update model values" phase |
@InvokeApplication | lifecycle | Qualifies events from the "invoke application" phase |
@RenderResponse | lifecycle | Qualifies events from the "render response" phase |
The event object is always a javax.faces.event.PhaseEvent
and according to the general
CDI principle, filtering is tightened by adding qualifiers and loosened by omitting them.
Similar to JSF Phase Events, System Events take place when specific events occur within the JSF life-cycle. Seam Faces provides a bridge for all JSF System Events, and propagates these events to CDI.
This is an example of observing a Faces system event:
public void observesThisEvent(@Observes ExceptionQueuedEvent e)
{
// Do something with the event object
}
Since all JSF system event objects are distinct, no qualifiers are needed to observe them. The following events may be observed:
Event object | Context | Description |
---|---|---|
SystemEvent | all | All events |
ComponentSystemEvent | component | All component events |
PostAddToViewEvent | component | After a component was added to the view |
PostConstructViewMapEvent | component | After a view map was created |
PostRestoreStateEvent | component | After a component has its state restored |
PostValidateEvent | component | After a component has been validated |
PreDestroyViewMapEvent | component | Before a view map has been restored |
PreRemoveFromViewEvent | component | Before a component has been removed from the view |
PreRenderComponentEvent | component | After a component has been rendered |
PreRenderViewEvent | component | Before a view has been rendered |
PreValidateEvent | component | Before a component has been validated |
ExceptionQueuedEvent | system | When an exception has been queued |
PostConstructApplicationEvent | system | After the application has been constructed |
PostConstructCustomScopeEvent | system | After a custom scope has been constructed |
PreDestroyApplicationEvent | system | Before the application is destroyed |
PreDestroyCustomScopeEvent | system | Before a custom scope is destroyed |
There is one qualifier, @Component
that can be used with component events by specifying the component ID. Note that
view-centric component events PreRenderViewEvent
, PostConstructViewMapEvent
and
PreDestroyViewMapEvent
do not fire with the @Component
qualifier.
public void observePrePasswordValidation(@Observes @Component("form:password") PreValidateEvent e)
{
// Do something with the "before password is validated" event object
}
Global system events are observer without the component qualifier
public void observeApplicationConstructed(@Observes PostConstructApplicationEvent e)
{
// Do something with the "after application is constructed" event object
}
The name of the observing method is not relevant; observers are defined solely via annotations.