librerias - ui define jsf
Cómo registrar un(componente) SystemEventListener para todos los UIInputs (1)
Se supone que @ListenerFor
se establece en una implementación UIComponent
o Renderer
, no en una implementación independiente SystemEventListener
. Ver también el javadoc (énfasis mío):
La implementación predeterminada debe admitir adjuntar esta anotación a las clases
UIComponent
oRenderer
. En ambos casos, el proceso de anotación descrito en este documento debe comenzar durante la implementación de cualquier variante deApplication.createComponent()
y debe completarse antes de que la instancia deUIComponent
sea devuelta porcreateComponent()
. El proceso de anotación debe proceder según un algoritmo semánticamente equivalente al siguiente....
Para tener un oyente global, no específico para un UIComponent
o Renderer
, su mejor apuesta es crear y registrar un PhaseListener
que suscriba al oyente a la raíz de la vista.
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.
}
}
Para que se ejecute, regístrelo de la siguiente manera en faces-config.xml:
<lifecycle>
<phase-listener>com.example.PostValidateListener</phase-listener>
</lifecycle>
Incluso puedes convertir tu InputPostValidationListener
en un PhaseListener
.
public class InputPostValidationListener implements PhaseListener, SystemEventListener {
@Override
public void beforePhase(PhaseEvent event) {
event.getFacesContext().getViewRoot().subscribeToViewEvent(PostValidateEvent.class, this);
}
// ...
}
Estoy tratando de tener un SystemEventListener
personalizado que se registre para todas las instancias de tipo UIInput
y reaccione a sus postValidate
. Basado en un ejemplo que encontré en la web, logré obtener uno corriendo para HtmlInputText
registrándolo en faces-config.xml
siguiente manera:
<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>
Luego traté de 1) ampliar esto para que funcione para UIInputs en general y para 2) usar la anotación @ListenerFor
, pero parece que no puedo hacer funcionar ninguno de los dos.
para 1) Realmente no pude encontrar ningún ejemplo o documentación, así que lo intenté por a) definiendo múltiples etiquetas de clase de fuente o por b) usando javax.faces.component.UIInput
como clase de origen. Ninguno funcionó.
para 2) probé
@ListenerFor(systemEventClass = PostValidateEvent.class, sourceClass = UIInput.class)
que no funcionó ni para UIInput ni para html.HtmlInputText.
Ahora, cuando duplico la misma configuración XML para todos los otros tipos de entradas de HTML, esto funciona, pero complica el xml y en conjunto me parece bastante molesto.
Entonces la pregunta es: ¿En general estoy haciendo algo mal con la anotación @ListenerFor? ¿Existe alguna restricción sobre qué clases fuente son posibles, es decir, por qué no puedo usar la UIInput más genérica? ¿Hay una manera más eficiente de registrar al oyente para todas esas entradas diferentes que repetir el XML? Y finalmente: me gustaría implementar ComponentSystemEventListener
. Asumiendo que el problema anterior se resolvió, simplemente cambiaría los implements
-Declaración e implementaría el abstract processEvent
consecuencia, ¿verdad? ¿Funcionaría igual o el registro / xml-config es diferente en este caso (por ejemplo, quizás <component-system-event-listener>
lugar de solo <system-event-listener>
?
(y como una nota posterior: ¿soy solo yo o es un poco difícil encontrar ejemplos no triviales para este tipo de cosas en la web?)