JSF Component listener with @ListenerFor
This tutorial shows how to add a listener to a component using the @ListenerFor
and @ListenersFor
annotation. The @ListenerFor
annotation allows a component to subscribe to particular events with the component itself being the listener. For this we need to do the following:
- Implement the
ComponentSystemEventListener
interface. TheUIComponent
implements this interface, so all components that extend fromUIComponent
are automatically eligible for receiving component system events. - Override the
processEvent
method. We can use this method to process the incoming event. - Use the
@ListenerFor
and/or@ListenersFor
annotations to indicate the event that the component will listen for (by registering the source class of the event).
Component Listener with @ListenersFor and @ListenerFor
Our MyOutput
component extends from UIOutput
, which extends from UIComponent
. This makes our class eligible for handling ComponentSystemEvents
. We register two system events by annotating the class with the wrapper @ListenersFor
annotation, which has 2 @ListenerFor
annotations describing which system events to listen for. We listen for a PostAddToViewEvent
and the PostConstructViewMapEvent
. Finally, we simply process the event by printing some standard text to the console.
package com.memorynotfound.jsf;
import javax.faces.component.FacesComponent;
import javax.faces.component.UIOutput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.*;
import java.io.IOException;
@FacesComponent(value = "com.memorynotfound.myOutput", createTag = true,
tagName = "myOutput", namespace = "https://memorynotfound.com/component-listener")
@ListenersFor({
@ListenerFor(systemEventClass=PostAddToViewEvent.class),
@ListenerFor(systemEventClass=PostConstructViewMapEvent.class)
})
public class MyOutput extends UIOutput {
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
super.processEvent(event);
System.out.println("process event - " + event.toString());
}
@Override
public void encodeEnd(FacesContext context) throws IOException {
ResponseWriter responseWriter = context.getResponseWriter();
responseWriter.write((String)getValue());
}
}
Using JSF Component with the listener
We can use our component in the HTML.
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:custom="https://memorynotfound.com/component-listener">
<h:body>
<h2>JSF Custom Component Event Listener</h2>
<custom:myOutput value="JSF Custom Component Event Listener"/>
</h:body>
</html>
Generated Output
When the page is accessed, the following output is printed to the console.
process event - javax.faces.event.PostAddToViewEvent[source=com.memorynotfound.jsf.MyOutput@2c78f1a0]
process event - javax.faces.event.PostAddToViewEvent[source=com.memorynotfound.jsf.MyOutput@5aceb3c0]
Demo
URL: http://localhost:8081/jsf-component-listener/