Hier werden die Events des Produkts JSF Ext beschrieben.
Name | Java | Parameter | Beschreibung |
---|---|---|---|
javax.faces.post_construct | Event.EVENT_POST_CONSTRUCT | Object managedBean | Der Event wird nach dem Erzeugen einer managed Bean durch das JSF-System erzeugt. |
javax.faces.pre_destroy | Event.EVENT_PRE_DESTROY | Der Event wird vor dem Entfernen einer managed Bean erzeugt. | |
javax.faces.event | Event.EVENT_EVENT | String event, Object... arguments | Dieser Meta-Event wird bei jedem Event erzeugt, sodass allgemeine Event-Handler geschrieben werden können. Dies ist mit Vorsicht zu verwenden. |
javax.faces.messages | MessageHandler.EVENT | - | Der Event wird erzeugt, wenn Faces Messages vorliegen. |
login.before | Login.EVENT_LOGIN_BEFORE | - | Bevor ein Benutzer eingeloggt wird. |
login.success | Login.EVENT_LOGIN_SUCCESS | - | Nachdem ein Benutzer erfolgreich eingeloggt wurde. Der Benutzer ist über Login.instance().getUser() abrufbar. |
login.fail | Login.EVENT_LOGIN_FAIL | - | Nachdem ein Login fehlgeschlagen ist. |
login.after | Login.EVENT_LOGIN_AFTER | - | Nach dem Login-Prozess, unabhängig ob er erfolgreich oder fehlgeschlagen ist. |
login.logout | Login.EVENT_LOGOUT | - | Nach dem Logout. |
Aus diesem Grund führt JSF Ext die (Render-)Events ein. Events können zwar aus der View durch den Tag <e:raise> erzeugt werden, sinnvoll ist meist jedoch die Erzeugung durch die raise-Methode auf der Java-Seite. Dadurch bleibt die lose Kopplung von View und Controller erhalten. Die können Controller können Ereignisse auslösen, auf die sich Teile der View registrieren um neu gerendert zu werden.
Das Session basierte Event-Objekt enthält die Methode raise(String event, Object... arguments), also im einfachsten Fall:
Event.instance().raise("com.intersult.some-event");
Die Events werden in der Regel durch eine Annotation konsumiert:
@Listener("com.intersult.some-event") public void someEvent() { }
Es ist zu beachten, dass Events nur empfangen werden wenn eine Bean tatsächlich instantiiert ist.
<e:render event="javax.faces.messages" target="messages"/> <h:messages id="messages" globalOnly="true"/>
Ergebnis: Die Faces-Messages werden gerendered, ohne dass bei jedem AJAX-Tag ein gesondertes Rendered-Attribut angegeben werden muss.
Hinweis: Hier wird der Render-Tag nicht im Messages-Tag verschachtelt, weil der Messages-Tag das Rendern von Child-Tags ausdrücklich verhindert.
Lösung bisher: In vielen Projekten wird für jedes Input-Element ein Composite-Tag gebaut, in dem der Code für AJAX, Validierung, Messages und so weiter wiederholt wird.
Mit JSF Ext kann ein generischer Wrapper für Input-Elements gebaut werden:
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:cc="http://java.sun.com/jsf/composite" xmlns:e="http://java.sun.com/jsf/ext" xmlns:ext="http://java.sun.com/jsf/composite/ext" xmlns:p="http://primefaces.org/ui" > <cc:interface> </cc:interface> <cc:implementation> <e:insert component="#{cc.children[0]}"> <f:ajax event="change"/> </e:insert> <h:message id="#{cc.children[0].id}-message" for=":#{cc.children[0].clientId}"> <e:render for=":#{cc.children[0].clientId}"/> </h:message> </cc:implementation> </html>
Die Anwendung dieses Composite-Tags ist dann wie folgt:
<h:form id="form"> <app:input id="text"> <h:inputText id="text" value="#{test.text}"/> </app:input> <h:commandButton value="Submit" action="#{bean.action}"> <f:ajax/> </h:commandButton>
Erklärung: Die Composite-Component wrappt das Input-Element, welches innerhalb des Composite Tags durch <e:insert> eingefügt wird. Der Zugriff erfolgt dabei durch die EL-Expression cc.children[0].
<e:render for=":form:some-text"/>
Der Event tritt in folgenden Fällen auf:
Hinweis: Das For-Attribut löst nur die Client-Id auf, das heißt es können relative Id's benutzt werden oder die @-Aliase. Letztlich entspricht es einem Event mit der vollen ClientId der Component, also <e:render for="text"/> hat denselben Effekt wie <e:render event=":form:panel:text"/>. Das Verwender des For-Attributs erleichtert allerdings den Bau der Komponenten und vermeidet Fehler, indem die Id validiert wird.
<h:commandButton value="Submit"> <f:ajax execute="@form"/> <e:raise name="com.intersult.test"/> </h:commandButton>
Hinweis: Beim Raise-Tag handelt es sich um einen Action-Listener, der nur unterhalb einer Action-Source verwendet werden kann (Command-Button, -Link etc.) Bei vollen GET- oder POST-Requests macht Event gesteuertes Rendering keinen Sinn, da hier sowieso die komplette Seite gerendered werden würde. Was auch bei vollen Requests nützlist ist, sind @Listener-Methoden an Beans.
Der Raise-Tag unterstützt auch Parameter, die genauso wirken wie bei raise(event, param...):
<e:raise name="com.intersult.test"> <f:param value="#{cc.attrs.someParam}"/> </e:raise>
Das Konsumieren kann wieder auf ähnliche Weise erfolgen:
<h:outputText id="output" value="#{bean.text}"> <e:render event="com.intersult.test"/> </h:outputText>
Es ist zu beachten, dass bei der Update-Component (hier outputText) eine Id angegeben wird, damit der AJAX-Handler das Rerendering zuordnen kann. Dies tritt beim Verwenden des render-Attributs nicht auf, da durch die Angabe einer Id ja eine vergeben wurde.
Name | Java | Parameter | Beschreibung |
---|---|---|---|
javax.faces.post_construct | Event.EVENT_POST_CONSTRUCT | Object managedBean | Der Event wird nach dem Erzeugen einer managed Bean durch das JSF-System erzeugt. |
javax.faces.pre_destroy | Event.EVENT_PRE_DESTROY | Der Event wird vor dem Entfernen einer managed Bean erzeugt. | |
javax.faces.event | Event.EVENT_EVENT | String event, Object... arguments | Dieser Meta-Event wird bei jedem Event erzeugt, sodass allgemeine Event-Handler geschrieben werden können. Dies ist mit Vorsicht zu verwenden. |
javax.faces.messages | MessageHandler.EVENT | - | Der Event wird erzeugt, wenn Faces Messages vorliegen. |
login.before | Login.EVENT_LOGIN_BEFORE | - | Bevor ein Benutzer eingeloggt wird. |
login.success | Login.EVENT_LOGIN_SUCCESS | - | Nachdem ein Benutzer erfolgreich eingeloggt wurde. Der Benutzer ist über Login.instance().getUser() abrufbar. |
login.fail | Login.EVENT_LOGIN_FAIL | - | Nachdem ein Login fehlgeschlagen ist. |
login.after | Login.EVENT_LOGIN_AFTER | - | Nach dem Login-Prozess, unabhängig ob er erfolgreich oder fehlgeschlagen ist. |
login.logout | Login.EVENT_LOGOUT | - | Nach dem Logout. |
Aus diesem Grund führt JSF Ext die (Render-)Events ein. Events können zwar aus der View durch den Tag <e:raise> erzeugt werden, sinnvoll ist meist jedoch die Erzeugung durch die raise-Methode auf der Java-Seite. Dadurch bleibt die lose Kopplung von View und Controller erhalten. Die können Controller können Ereignisse auslösen, auf die sich Teile der View registrieren um neu gerendert zu werden.
Das Session basierte Event-Objekt enthält die Methode raise(String event, Object... arguments), also im einfachsten Fall:
Event.instance().raise("com.intersult.some-event");
Die Events werden in der Regel durch eine Annotation konsumiert:
@Listener("com.intersult.some-event") public void someEvent() { }
Es ist zu beachten, dass Events nur empfangen werden wenn eine Bean tatsächlich instantiiert ist.
<e:render event="javax.faces.messages" target="messages"/> <h:messages id="messages" globalOnly="true"/>
Ergebnis: Die Faces-Messages werden gerendered, ohne dass bei jedem AJAX-Tag ein gesondertes Rendered-Attribut angegeben werden muss.
Hinweis: Hier wird der Render-Tag nicht im Messages-Tag verschachtelt, weil der Messages-Tag das Rendern von Child-Tags ausdrücklich verhindert.
Lösung bisher: In vielen Projekten wird für jedes Input-Element ein Composite-Tag gebaut, in dem der Code für AJAX, Validierung, Messages und so weiter wiederholt wird.
Mit JSF Ext kann ein generischer Wrapper für Input-Elements gebaut werden:
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:cc="http://java.sun.com/jsf/composite" xmlns:e="http://java.sun.com/jsf/ext" xmlns:ext="http://java.sun.com/jsf/composite/ext" xmlns:p="http://primefaces.org/ui" > <cc:interface> </cc:interface> <cc:implementation> <e:insert component="#{cc.children[0]}"> <f:ajax event="change"/> </e:insert> <h:message id="#{cc.children[0].id}-message" for=":#{cc.children[0].clientId}"> <e:render for=":#{cc.children[0].clientId}"/> </h:message> </cc:implementation> </html>
Die Anwendung dieses Composite-Tags ist dann wie folgt:
<h:form id="form"> <app:input id="text"> <h:inputText id="text" value="#{test.text}"/> </app:input> <h:commandButton value="Submit" action="#{bean.action}"> <f:ajax/> </h:commandButton>
Erklärung: Die Composite-Component wrappt das Input-Element, welches innerhalb des Composite Tags durch <e:insert> eingefügt wird. Der Zugriff erfolgt dabei durch die EL-Expression cc.children[0].
<e:render for=":form:some-text"/>
Der Event tritt in folgenden Fällen auf:
Hinweis: Das For-Attribut löst nur die Client-Id auf, das heißt es können relative Id's benutzt werden oder die @-Aliase. Letztlich entspricht es einem Event mit der vollen ClientId der Component, also <e:render for="text"/> hat denselben Effekt wie <e:render event=":form:panel:text"/>. Das Verwender des For-Attributs erleichtert allerdings den Bau der Komponenten und vermeidet Fehler, indem die Id validiert wird.
<h:commandButton value="Submit"> <f:ajax execute="@form"/> <e:raise name="com.intersult.test"/> </h:commandButton>
Hier ist zu beachten, dass ein AJAX-Tag zusätzlich verwendet wird. Bei vollen GET- oder POST-Requests machen Events keinen Sinn, da hier sowieso die komplette Seite gerendered werden würde.
Das Konsumieren kann wieder auf ähnliche Weise erfolgen:
<h:outputText id="output" value="#{bean.text}"> <e:render event="com.intersult.test"/> </h:outputText>
Es ist zu beachten, dass bei der Update-Component (hier outputText) eine Id angegeben wird, damit der AJAX-Handler das Rerendering zuordnen kann. Dies tritt beim Verwenden des render-Attributs nicht auf, da durch die Angabe einer Id ja eine vergeben wurde.