How to register (Component) SystemEventListener for all UIInputs

I am trying to create a custom SystemEventListener that registers for all instances of type UIInput and responds to their postValidate -Events. Based on an example that I found on the Internet, I managed to run one for HtmlInputText by registering it in faces-config.xml as follows:

 <system-event-listener> <source-class>javax.faces.component.html.HtmlInputText</source-class> <system-event-class>javax.faces.event.PostValidateEvent</system-event-class> <system-event-listener-class>com.ourcompany.ourproduct.validators.inputPostValidationListener</system-event-listener-class> </system-event-listener> 

Then I tried 1) to expand this to work for UIInputs in general, and 2) to use the @ListenerFor annotation, but I just can't get it to work.

for 1) I could not find any examples or documentation, so I just tried: a) to define several source code tags or b) using javax.faces.component.UIInput as the source class. Nothing worked.

for 2) I tried

 @ListenerFor(systemEventClass = PostValidateEvent.class, sourceClass = UIInput.class) 

which worked neither for UIInput nor for html.HtmlInputText.

Now, when I duplicate the same XML configuration for all other types of HTML inputs, this does the trick, but it just clutters the xml and generally seems very unpleasant to me.

So the question is: am I doing anything wrong with the @ListenerFor annotation? Is there a restriction on which source classes are possible, i.e. Why can't I use a more generic UIInput? Is there a more efficient way to register a listener for all of these different input data than to repeat the XML? And finally: I would prefer to implement the ComponentSystemEventListener . Assuming the above problem was resolved, I just changed the implements -Statement and executed the abstract processEvent accordingly, right? Will it work the same way or in this case it will have the value register / xml-config (for example, maybe <component-system-event-listener> instead of <system-event-listener> ?

(and as a note: is it just me or is it hard to find some non-trivial examples for this kind of thing on the Internet?)

+4
source share
1 answer

It is assumed that @ListenerFor installed in a UIComponent or Renderer implementation, and not in a stand- SystemEventListener implementation. See Also javadoc (my selection):

The default implementation should support attaching this annotation to the UIComponent or Renderer classes. . In both cases, the annotation processing described here should begin during the implementation of any variant of Application.createComponent() and must end before the UIComponent instance is returned from createComponent() . Annotation processing should be performed in accordance with an algorithm that is semantically equivalent to the following.

...

To have a global listener other than UIComponent or Renderer , your best bet is to create and register a PhaseListener that subscribes the listener to the root of the view.

 public class PostValidateListener implements PhaseListener { @Override public PhaseId getPhaseId() { return PhaseId.PROCESS_VALIDATIONS; } @Override public void beforePhase(PhaseEvent event) { event.getFacesContext().getViewRoot() .subscribeToViewEvent(PostValidateEvent.class, new InputPostValidationListener()); // Capitalize class name? } @Override public void afterPhase(PhaseEvent event) { // NOOP. } } 

To run it, register it as follows in faces-config.xml:

 <lifecycle> <phase-listener>com.example.PostValidateListener</phase-listener> </lifecycle> 

You can even make your InputPostValidationListener itself.

 public class InputPostValidationListener implements PhaseListener, SystemEventListener { @Override public void beforePhase(PhaseEvent event) { event.getFacesContext().getViewRoot().subscribeToViewEvent(PostValidateEvent.class, this); } // ... } 
+2
source

All Articles