jsf-2annotationslistenersystemevent

Doesn't work JSF annotation @ListenerFor/@ListenersFor


JSF annotation @ListenerFor doesn't work with GlassFish or Tomcat. No errors or warnings. It's just doesn't call method processEvent().

@ListenersFor({@ListenerFor(systemEventClass=PostConstructApplicationEvent.class), 
public class MySystemEventListener implements SystemEventListener {

   @Override
   public void processEvent(SystemEvent event) throws AbortProcessingException {
      if(event instanceof PostConstructApplicationEvent){
         System.out.println("*********************************************");
         System.out.println("processEvent Method is Called: PostConstructApplicationEvent");
         System.out.println("*********************************************");
      }

      if(event instanceof PreDestroyApplicationEvent){
         System.out.println("*********************************************");
         System.out.println("processEvent Method is Called: PreDestroyApplicationEvent");
         System.out.println("*********************************************");
      }
}

   @Override
   public boolean isListenerForSource(Object o) {
      return (o instanceof Application);
   }

}

With the idea of​​?


Solution

  • As its javadoc tells you, the @ListenerFor is intented to be put on an UIComponent or Renderer implementation, not on a standalone SystemEventListener implementation. For the latter, you'd need to register it as <system-event-listener> in faces-config.xml.

    E.g.

    <application>
        <system-event-listener>
            <system-event-listener-class>com.example.MySystemEventListener</system-event-listener-class>
            <system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
            <system-event-class>javax.faces.event.PreDestroyApplicationEvent</system-event-class>
        <system-event-listener>
    </application>
    

    For the particular functional requirement, you might want to consider to use an eagerly initialized application scoped bean instead. This is somewhat easier and doesn't require some verbose XML:

    @ManagedBean(eager=true)
    @ApplicationScoped
    public void App {
    
        @PostConstruct
        public void init() {
            // ...
        }
    
        @PreDestroy
        public void destroy() {
            // ...
        }
    
    }