JSF-Working with @ListenerFor, ComponentSystemEventListener and SystemEventListener - part I
JSF-Working with @ListenerFor, ComponentSystemEventListener and SystemEventListener - part II
Sometimes you need to install the listener instance referenced by argument listener into the UIViewRoot as a listener for events of type systemEventClass, as in the case of PreRenderViewEvent.
Below you can see the UIViewRoot.subscribeToViewEvent()
provided by JSF and some alternatives provided by OmniFaces 2.1 and 2.0:
@FacesComponent(value
= TomComponent.COMPONENT_TYPE, createTag = true)
public class
TomComponent extends UIComponentBase implements SystemEventListener {
public static final String COMPONENT_FAMILY =
"jsf.uicomponentwithsubscribetoevent";
public static final String COMPONENT_TYPE =
"jsf.uicomponentwithsubscribetoevent.TomComponent";
@PostConstruct
public void tomSubscribeToViewEvent() {
FacesContext.getCurrentInstance().getViewRoot().
subscribeToViewEvent(PreRenderViewEvent.class, this);
}
@Override
public
void processEvent(SystemEvent event) throws AbortProcessingException {
System.out.println("EVENT EMITTED:
" + event);
}
@Override
public void encodeEnd(FacesContext context)
throws IOException {
ResponseWriter responseWriter =
context.getResponseWriter();
responseWriter.write("I'm Tom the
cat!");
}
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@Override
public
boolean isListenerForSource(Object source) {
return
true;
}
}
Sometimes, you need to combine an event like PostAddToViewEvent
with PreRenderViewEvent.
Per example, OmniFaces does this in the OnloadScript component. The
next example is inspired by the source code of OnloadScript component:
@ListenerFor and UIViewRoot.subscribeToViewEvent() used with an UIComponent that implements
the ComponentSystemEventListener
and SystemEventListener
interfaces
§
the UIComponent is annotated with @ListenerFor
and listen the PostAddToViewEvent
event emitted by instances of this UIComponent
§
if the request (initial/postback) is an AJAX
request then the component register as a listener for the PreRenderViewEvent
emitted by the UIViewRoot.
@FacesComponent(value
= TomComponent.COMPONENT_TYPE, createTag = true)
@ListenerFor(systemEventClass =
PostAddToViewEvent.class)
public class
TomComponent extends UIComponentBase implements
ComponentSystemEventListener,
SystemEventListener {
public static final String COMPONENT_FAMILY =
"jsf.uicomponentwithsubscribetoevent";
public static final String COMPONENT_TYPE =
"jsf.uicomponentwithsubscribetoevent.TomComponent";
@Override
public
void processEvent(ComponentSystemEvent event) throws AbortProcessingException
{
System.out.println("EVENT EMITTED
(ComponentSystemEvent): " + event);
FacesContext context =
FacesContext.getCurrentInstance();
boolean ajaxRequest =
context.getPartialViewContext().isAjaxRequest();
if
(ajaxRequest) {
context.getViewRoot().subscribeToViewEvent(PreRenderViewEvent.class,
this);
}
}
@Override
public
void processEvent(SystemEvent event) throws AbortProcessingException {
System.out.println("EVENT EMITTED
(SystemEvent): " + event);
}
@Override
public void encodeEnd(FacesContext context)
throws IOException {
ResponseWriter responseWriter =
context.getResponseWriter();
responseWriter.write("I'm Tom the
cat!");
}
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@Override
public
boolean isListenerForSource(Object source) {
return
source instanceof TomComponent || source instanceof UIViewRoot;
}
}
Output at initial request (AJAX reqest):
EVENT
EMITTED (ComponentSystemEvent):
javax.faces.event.PostAddToViewEvent[source=jsf.listenerforanduicomponent.TomComponent]
Output at postback (AJAX request):
EVENT
EMITTED (ComponentSystemEvent):
javax.faces.event.PostAddToViewEvent[source=jsf.listenerforanduicomponent.TomComponent]
EVENT
EMITTED (ComponentSystemEvent): javax.faces.event.PostRestoreStateEvent[source=jsf.listenerforanduicomponent.TomComponent]
EVENT
EMITTED (SystemEvent): javax.faces.event.PreRenderViewEvent[source=javax.faces.component.UIViewRoot]
System events can be
configured in faces-config.xml
also. If you need to register as listener for a built-in JSF component then
this can be the right approach. Per example, we can write a system event for looping through the CSS
resources and remove some of them (or, all of them). The code of our listener
is pretty simple, as you can see in the following code:
public class
ResourcesListener implements SystemEventListener {
@Override
public void processEvent(SystemEvent event)
throws AbortProcessingException {
FacesContext context =
FacesContext.getCurrentInstance();
int i =
context.getViewRoot().getComponentResources(context, "HEAD").size() -
1;
while (i >= 0) {
UIComponent resource =
context.getViewRoot().getComponentResources(context, "HEAD").get(i);
String resourceLibrary = (String)
resource.getAttributes().get("library");
String resourceName = (String)
resource.getAttributes().get("name");
if
((resourceLibrary.equals("default")) &&
(resourceName.equals("css/jerry.css"))) {
context.getViewRoot().removeComponentResource(context, resource,
"HEAD");
}
i--;
}
}
@Override
public boolean isListenerForSource(Object
source) {
return
(source instanceof UIViewRoot);
}
}
The listener should be
configured in faces-config.xml,
as follows (the tags names reveals their goal):
...
<application>
<system-event-listener>
<system-event-listener-class>
tom.jerry.ResourcesListener
</system-event-listener-class>
<system-event-class>
javax.faces.event.PreRenderViewEvent
</system-event-class>
<source-class>
javax.faces.component.UIViewRoot
</source-class>
</system-event-listener>
</application>
...
So, even if initially we
write the following code:
...
<h:head>
<h:outputStylesheet
library="default" name="css/tom.css"/>
<h:outputStylesheet
library="default" name="css/jerry.css"/>
</h:head>
...
JSF will render the
following code:
...
<head>
<link type="text/css"
rel="stylesheet"
href="/tomandjerry/faces/javax.faces.resource/css/tom.css?ln=default"
/>
</head>
...
Note: Programmatically,
you can unsubscribe from an event using the UIComponent/Application.unsubscribeFromEvent() methods:
//UIComponent
public void
unsubscribeFromEvent(java.lang.Class<? extends SystemEvent> eventClass,
ComponentSystemEventListener componentListener)
//Application
public void
unsubscribeFromEvent(java.lang.Class<? extends SystemEvent>
systemEventClass,
java.lang.Class<?>
sourceClass,
SystemEventListener listener)
public void
unsubscribeFromEvent(java.lang.Class<? extends SystemEvent>
systemEventClass,
SystemEventListener listener)
Useful
links: JSF ZEEF
Niciun comentariu :
Trimiteți un comentariu