This page (revision-184) was last changed on 21-Apr-2017 08:27 by Dieter Käppel

This page was created on 09-Aug-2012 13:29 by Dieter Käppel

Only authorized users are allowed to rename pages.

Only authorized users are allowed to delete pages.

Page revision history

Version Date Modified Size Author Changes ... Change note
184 21-Apr-2017 08:27 36 KB Dieter Käppel to previous
183 21-Apr-2017 08:27 36 KB Dieter Käppel to previous | to last
182 15-Jan-2016 10:18 36 KB Dieter Käppel to previous | to last
181 15-Jan-2016 10:16 36 KB Dieter Käppel to previous | to last

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 108 changed 2 lines
!!!Tags
Das [JSF Ext] enthält eine Reine von Tags.
!!![Tags|JSF Ext Tags]
At line 111 removed 502 lines
!!Insert Tag
Der Insert Tag kann Components in den Component Tree einfügen, anhand einer EL-Expression. Dies ist unter anderem nützlich, wenn man Composite Components baut. Also Components mit dem Namespace http://java.sun.com/jsf/composite/...
In der Composite Component gibt es nur den Tag <cc:insertChildren>, damit hat man keine detailierte Kontrolle, die Children werden alle an derselben Stelle eingefügt. Möchte man diese zum Beispiel durch ein SPAN-Tag wrappen, braucht man den Insert Tag.
__Lösung:__ Man iteriert durch die Children mittels <c:forEach> und fügt diese an einer beliebigen Stelle mittel <e:insert> ein.
{{{
<?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"
>
<cc:interface>
<cc:attribute name="align" default="center"/>
</cc:interface>
<cc:implementation>
<div style="margin-top: 5px; text-align: #{cc.attrs.align};">
<c:forEach items="#{cc.children}" var="child">
<h:panelGroup style="padding: 5px 5px 0 0;" rendered="#{child.rendered}">
<e:insert component="#{child}"/>
</h:panelGroup>
</c:forEach>
</div>
</cc:implementation>
</html>
}}}
!!Behavior-Tag
Eine Neuerung bei [JSF2] ist die Einführung von Behaviors, also das Generieren von Java-Script-Snippets aus Java heraus. Ein Behavior kann jeder Komponente hinzugefügt werden, die ClientBehaviorHolder implementiert.
In vielen Fällen hab man bereits Behavior-Components zu einem Tag hinzugefügt. Würde man dennoch das entsprechende Attribut verwenden (z.B. onclick bei commandButton), kann es zu Problemen kommen, wie die Reihenfolge der Snippets oder das "return false;"-Anhängsel.
Lösung bringt der Behavior-Tag von [JSF Ext]. Typisch ist zum Beispiel die Verwendung zusammen mit dem AJAX-Tag:
{{{
<h:commandButton value="X">
<f:ajax/>
<e:unload/>
<e:behavior script="#{rich:component('popup-panel')}.hide(event);"/>
</h:commandButton>
}}}
Die Behavior-Snippets werden in der entsprechenden Reihenfolge produziert:
{{{
jsf.util.chain(this,event,'mojarra.ab(this,event,\'action\',0,0)','RichFaces.$(\'popup:form:popup-panel\').hide(event);');return false
}}}
!!Evaluate Tag
Wenn mit Actions und Java-Script gearbeitet wird, kann eine Ausführung im Erfolgsfall des Form Submit sinnvoll sein. Dies kann durch den Evaluate-Tag erreicht werden, der einen ActionListener darstellt und entsprechendes Script ausführen kann.
{{{
<h:commandButton value="Submit">
<f:ajax/>
<e:evaluate script="alert('Success');"/>
</h:commandButton>
}}}
Zusätzlich ist der Evaluate-Tag ein ClientBahaviorHolder, sodass Behavior-Tags verwendet werden können, um das Script zu erzeugen.
Unterschied zwischen Behavior- und Evaluate-Tag:
||||Behavior||Evaluate
|Zeitpunkt der Ausführung|Direkt durch den Browser-Event|Durch den AJAX-Request an den Browser gesendet
|Bedingungen für die Ausführung|Keine Server-Bedingungen möglich, nur Java-Script if-Statements|Das Script wird nur nach erfolgreichen Submit ausgeführt, also wenn die Validation erfolgreich war
|Anwendungszweck|Steuerung des Browserverhaltens, Ein- und Ausblenden, Fading, dynamische Browserelemente, Client-Behavior|Abwickeln von Server-States, Popups öffnen und Schließen, Submits bestätigen
!!AJAX-Tag
Der AJAX-Tag von [JSF Ext] erlaubt das Abschicken eines anderen Formulars. Der Tag <f:ajax> kann nur das aktuelle Formular abschicken, innerhalb der Action-Source in der er sich befindet.
!Sources
Manchmal ist es sinnvoll andere Sources abzuschicken, dafür stellt [JSF Ext] den Tag <e:ajax> zur Verfügung:
{{{
<h:form id="test-form">
<h:panelGrid columns="3">
<h:outputText value="Name"/>
<h:inputText id="name" value="#{bean.name}" required="true"/>
<h:message for="name"/>
</h:panelGrid>
</h:form>
<h:form id="other-form">
<h:commandButton id="tag-save" value="Tag Button">
<e:ajax source=":test-form" render=":test-form"/>
</h:commandButton>
</h:form>
}}}
Der Tag <e:ajax> ersetzt in diesem Fall den Tag <f:ajax>, er braucht nicht zusätzlich angegeben zu werden.
!Action Source
Der Tag kann auch Actions abschicken, wenn er an einfachen ClientBehaviorHolder gehängt wird, weil er selbst eine ActionSource darstellt:
{{{
<h:panelGrid>
<f:ajax event="dblclick" action="#{bean.action}"/>
</h:panelGrid>
}}}
!Client-Behaviors
Der Tag <e:ajax> ist nicht nur ein ClientBehavior sonder auch selbst wieder ein ClientBehaviorHolder. Er unterstützt die vier AJAX-Events begin, complete, success und error, wobei das Default-Event success ist:
{{{
<h:graphicImage id="edit" value="edit.png">
<e:ajax event="click">
<f:setPropertyActionListener value="#{element}" target="#{editController.element}"/>
<rich:componentControl target=":some-popup" operation="show"/>
</e:ajax>
</h:commandButton>
}}}
!!DIV-Tag
In JSF gibt es eine Reihe von Möglichkeiten, einen DIV- oder SPAN-Tag zu erzeugen, zum Beispiel durch <h:panelGroup>. Dabei handelt es sich jedoch um einfache Komponenten, die keine ClientBehaviorHolder sind, und daher kein <f:ajax>, <e:bahavior> und andere Behaviors unterstützen.
Der Tag <e:div> ist ein vollwertiger ClientBehaviorHolder:
{{{
<e:div id="mouse-active" tabindex="0" onkeypress="alert((event || window.event).keyCode);">
<ext:mouse-focus id="mouse-focus"/>
<h1>TEST</h1>
</e:div>
}}}
Damit wird das Erstellen von einfachen Komponenten mit wenig HTML-Code und flachen Komponenten-Bäumen deutlich vereinfacht.
!!Attribute-Tag
Bei manchen Tags fehlen Attribute, wie zum Beispiel placeholder oder oncontextmenu. JSF-Tags reichen die Attribute nicht durch, daher besteht keine andere Möglichkeit diese Attribute hinzuzufügen. In den meisten Fällen können solche Attribute durch das Attribute-Tag trotzdem hinzugefügt werden:
{{{
<h:inputText id="name" value="#{bean.name}">
<e:attribute name="placeholder" value="Name eingeben..."/>
</h:inputText>
}}}
Des Weiteren unterstützt der Attribut-Tag folgende Attribute:
||Name||Beschreibung
|finalizer|Zeichen für den Abschluss eines Behaviors. Default ist, dieses Zeichen aufgrund einer Reihe von Heuristiken zu erraten. Dazu zählen Behaviors und Attribut-Namen wie z.B. "style" mit den Finalizern ";" und "". Jeder untergeordnete Behavior-, Part- und anderer Tag wird mit diesem Zeichen abgeschlossen.
|delimiter|Zeichen für die Abtrennung untergeordneter Behavior-Tags usw. Im Gegensatz zum Finalizer wird dieses Zeichen nur zwischen den Behaviors eingefügt, nicht jedoch am Ende. Default ist ein einzelnes Whitespace.
__Hinweis:__ Durch dieses Feature können Strings bequem zusammengesetzt werden, die mit Attributen "rendered" versehen sind. Untergeordnete Behaviors, wie das Part-Tag, können die Werte nochmal für einzelne Strings überschreiben.
!Attribute-Behaviors
Der Attribute-Tag ist ein ClientBehaviorHolder, es können also Behaviors darunter gehängt werden wie <e:behavior> oder sogar <e:ajax>. Dadurch ist es möglich, Behaviors für Attribute zu festzulegen, die eigentlich nicht dafür gedacht sind:
{{{
<h:panelGroup>
<e:attribute name="oncontextmenu">
<f:ajax listener="#{bean.render}" render=":some-menu"/>
</e:attribute>
</h:panelGroup>
}}}
!Zusammengesetzte Attribute
Gelegentlich möchte man Attribute zusammen setzen, zum Beispiel um Styles in Composite-Tags zu rendern. Dies kann durch Kombination eines Attribute-Tags und mehreren Behavior-Tags erreicht werden:
{{{
<e:div id="#{cc.id}" styleClass="button-bar">
<e:attribute name="style" renderEmpty="false">
<e:behavior script="text-align: #{cc.attrs.align};" rendered="#{!empty cc.attrs.align}"/>
<e:behavior script="background-color: #{cc.attrs.color};" rendered="#{!empty cc.attrs.color}"/>
</e:attribute>
...
</e:div>
}}}
!Part-Attribute
Zusammengesetzt Attribute können bequem durch <e:part> erzeugt werden:
{{{
<h:commandButton>
<e:attribute name="value">
<e:part value="This"/>
<e:part value="is"/>
<e:part value="a"/>
<e:part value="composed"/>
<e:part value="value"/>
</e:attribute>
</h:commandButton>
}}}
__Hinweis:__ Der Part-Tag kann hilfreich sein, wenn bedingte styleClass-Attribute auftreten. Entsprechende Teile können mit dem rendered-Attribut gesteuert werden, anstatt unübersichtliche EL-Expressions zu konstruieren.
!Style-Attribute
Da Style-Attribute besonders häufig auftreten und zusammengesetzt werden, gibt es dafür einen eigenen Tag:
{{{
<e:div>
<e:attribute name="style">
<e:style name="text-align" value="#{valueEdit.permission.field.type.align}"/>
<e:style name="width" value="100%"/>
<e:style name="margin-left" value="10px"/>
</e:attribute>
</e:div>
}}}
!!Reference-Tag
__Achtung:__ Der Reference-Tag wird nicht mehr unterstützt.
__Begründung:__ Der Reference-Tag wird seit längerem durch Scopes ersetzt. Diese sind wesentlich besser in JSF integriert, brauchen weniger Ressourcen und sind flexibler in der Anwendung.
!!New-Tag
Der Tag <e:new> kann an jeder Stelle verwendet werden, an der auch <f:param> verwendet wird:
{{{
<e:load scopeId="test-scope">
<e:new name="bean" type="com.intersult.test.Bean"/>
</e:load>
}}}
Es ist auch möglich, Properties der neuen Bean Werte zuzuweisen:
{{{
<e:new name="bean" type="com.intersult.test.Bean">
<f:param name="param1" value="#{some-expression}/>
</e:new>
}}}
__Hinweis:__ Es ist zu erwähnen, dass das Instantiieren von Beans durch den New-Tag möglicher Weise nicht die beste Praxis ist. Die erste Wahl beim Erzeugen von Beans sollte das Verwenden von Scope- und Factory-Annotations sein, entweder über JSF mit @ManagedBean oder über Spring mit @Component. An zweiter Wahl steht das Erzeugen im Java-Code, zum Beispiel mit Lazy-Initialization Pattern "if (bean == null) bean = new Bean();". <e:new> macht vor allem da Sinn, wo eine neue leere Bean erzeugt werden soll (z.B. Create Popup) und wo mehrere Parameter durch eine Bean übergeben werden sollen.
!!Set-Tag
Eine gängige Praxis ist das Setzen von Java-Properties mittels <f:setPropertyActionListener>. Bei Composite Components können ebenfalls als ActionSource agieren:
{{{
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:e="http://java.sun.com/jsf/ext"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite"
>
<cc:interface>
<cc:attribute name="label"/>
<cc:attribute name="action" targets="link" method-signature="void action()"/>
<cc:actionSource name="action" targets="link" default="true"/>
</cc:interface>
<cc:implementation>
<h:commandLink id="link"
<h:outputText value="#{cc.attrs.label}"/>
</h:commandLink>
</cc:implementation>
</html>
}}}
Dieser Tag kann wie folgt verwendet werden:
{{{
<app:myLink label="Some Link">
<e:set value="Some Value" target="#{bean.value}"/>
</app:myLink>
}}}
Beim Verwenden von <f:setPropertyActionListener> müsste man explizit mit einem Attribut for="action" die Action spezifizieren. Der Tag <e:set> macht dies automatisch, bei häufigem Verwenden sieht der kurze Name einfach ausdrucksvoller und aufgeräumter aus.
!!Label
[JSF Ext] liefert einen Tag <e:outputLabel> mit, der auf Required-Attribute mit einem unterschiedlichen Style reagiert. Zusätzlich berücksichtigt werden die Annotations @NotNull und @NotEmpty auf den durch EL-Expressions gebundenen Bean-Klassen.
Die Verwendung ist identisch mit <h:outputLabel>:
{{{
<e:outputLabel for="username:username" value="#{messages['user.username']}"/>
<ext:input id="username">
<h:inputText id="username" value="#{userRegister.user.username}"/>
</ext:input>
}}}
Dabei kommen die beiden CSS-Style-Klassen label-required und label-not-required zum Einsatz, die mit "font-weight: bold;" und "color: #a0a0a0;" vorbelegt sind. Diese können durch ein Benutzer-Stylesheet überschrieben werden.
Der <e:outputLabel> unterstützt das Attribut disabled, mit dem der Label als optional angezeigt werden kann, unabhängig von der tatsächlichen Required-Eigenschaft. Dies ist nützlich, wenn die zugehörige Input-Component ebenfalls Disabled wird.
!!Busy Pointer
Die Integration von AJAX in die Anwendung findet vom Browser zunächst transparent statt. Der Benutzer hat keinen Hinweis, dass gerade eine Server-Aktion erfolgt. Der Vorteil ist, dass der Benutzer mit dem Browser normal weiter arbeiten kann. In vielen Fällen ist dies auch möglich, da Operationen unabhängig voneinander ausgeführt werden können. Der Nachteil ist, dass der Benutzer keinen Hinweis erhält, dass die beabsichtigte Operation angelaufen ist.
In den Anwendungen werden daher unterschiedlichste Elemente in die Seite eingebaut, von rotierenden, blinkenden durch durchlaufenden Bildern bis zu Seiten abdunkelnden und sperrenden Elementen. Das übliche Verfahren von Anwendungen die Verarbeitung einer Operation zu zeigen, ist den Mauszeiger als Busy Pointer darzustellen.
Also wieso nicht auch im Browser bei JSF-Anwendungen den Busy Pointer aktivieren. Der Benutzer wird nicht abgelenkt durch zappelnde Bilder, es wird nichts gesperrt, da die Seite ja weiterhin funktional ist:
{{{
<ext:busyPointer/>
}}}
Optional kann das Attribut cursor angeben werde, das per default auf "wait" gesetzt ist.
!!Mouse Visibility
Auf Seiten die sehr viele Elemente enthalten kann es die Übersicht verbessern, wenn Elemente erst bei Mouse-Over angezeigt werden. Durch reine CSS-Styles ist das meist nicht zu realisieren, weil das Mouse-Over-Element ein Parent-Element des anzuzeigenden Elements ist. Lösungen mit A-Tags, die man häufig findet, führen zu Nebenwirkungen wie Anchor-Links und ungewollten GET-Requests.
Eine Lösung ist der Tag <ext:mouse-visibility>:
{{{
<e:div>
<h:outputText id="project" value="#{processDetails.process.project.name}"/>
<ext:mouse-visibility for=":process-form:image"/>
<h:graphicImage id="image" name="edit.gif" library="images/bitcons">
<e:ajax event="click">
<e:load scopeId=":projectEdit">
<f:param name="project" value="#{project}"/>
</e:load>
</e:ajax>
</h:graphicImage>
</e:div>
}}}
Darüber hinaus gibt es noch die Tags <ext:mouse-display> mit welcher der Display-Style eines Elements gesteuert werden kann. Besonders schick ist auch der <ext:mouse-fade>, mit der das Element ein- und ausgefadet wird.
!!Move-Listener
Auf modernen Web-Seiten wird mehr und mehr mit Popups und Elementen gearbeitet, die mit der Maus verschoben werden können. Der Move-Listener ist ein Event-Generator, mit dem solche Eingriffe verarbeitet werden können:
{{{
<e:moveListener listener="#{dialog.moveListener}"/>
}}}
[JSF Ext] enthält eine Custom-Scoped Bean "dialog", in der das Ergebnis gespeichert werden kann. Im obigen Beispiel geschieht dies durch listener="#{dialog.moveListener}". Ein entsprechendes Popup kann dann durch position="#{dialog.position}" wieder positioniert werden.
Um einem Primefaces-Dialog einen Listener hinzuzufügen, verwendet man:
{{{
<e:moveListener listener="#{dialog.moveListener}"
targetNode="document.getElementById('#{cc.clientId}:dialog').childNodes[0]"
height="element.childNodes[1].offsetHeight - 16"
width="element.childNodes[1].offsetWidth"/>
}}}
!!Init-Tag
In einigen Situationen ist es hilfreich, wenn eine Bean an einer bestimmten Stelle im Component-Tree initialisiert werden kann. So kann beispielsweise ein HTTP-GET-Parameter verarbeitet werden oder ein Scope initialisiert. Dazu gibt es den Tag <e:init>:
{{{
<e:init action="#{testBean.init}"/>
}}}
__Hinweis:__ Die Action-Methode kann mehrfach aufgerufen werden, wenn Redirects durchgeführt werden.
Der Tag kann innerhalb eines Scopes verwendet werden, um den Scope zu initialisieren, falls kein Laden mit <e:load> erfolgt ist.
{{{
<e:scope id="test" load="true">
<e:init action="#{testBean.init}"/>
...
</e:scope>
}}}
{{{
public class TestBean {
@ScopeValue
private String test;
public void init() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String test = externalContext.getRequestParameterMap().get("test");
if (test != null)
this.test = test;
}
...
}
}}}
__Hinweis:__ Der Load-Tag ist dabei weiterhin möglich.
Der Init-Tag ist eine ActionSource und kann damit auch ActionListener als Unterobjekte haben:
{{{
<e:init>
<e:set value="#{value}" target="#{target}"/>
</e:init>
}}}
!!Otherwise-Tag
Da ist mit dem <c:choose>, <c:when> und <c:otherwise> Konstrukt in JSF Probleme gibt, enthält [JSF Ext] eine neue Implementierung von Otherweise als Component <e:otherwise>. Diese Component ist einfacher in der Nutzung:
* Als Basis der Choose-Liste kann eine beliebige Component verwendet werden
* Child-Components werden mit rendered-Attributen versehen
* Der Otherwise-Tag wird hinzugefügt und rendered dann, wenn keine der anderen Components gerendert wurde
Das Ganze sieht dann so aus:
{{{
<e:div>
<h:selectBooleanCheckbox id="boolean" value="#{bean.value}" rendered="#{bean.type == 'boolean'}"/>
...
<e:otherwise>
<h:inputText id="text" value="#{bean.value}"/>
</e:otherwise>
</e:div>
}}}
!!Render-Tag
Der Tag <e:render> ist ein nützlicher Tag für dynamische Web-Seiten, in denen Teile automatisch refreshed werden. Bisher gibt man im Ajax-Tag eine Liste von Elementen an, die neu gerendered werden sollen.
Die alte Implementierung über Render-Attribute führt zu folgenden Verbesserungswünschen:
* __Dynamik:__ Zum Zeitpunkt des Ausführens der Render-Anweisung ist unklar, welche Bereiche überhaupt neu gerendered werden brauchen. Die Zielbereiche können über das Render-Attribut, Scopes und andere Mechanismen dynamisch ein- und ausgeblendet werden. Man möchte die Veränderung einer Struktur melden können, unabhängig von den zur Laufzeit tatsächlich abhängigen Elementen.
* __Weiterentwicklung:__ Nach Schreiben der Render-Anweisung wird die Anwendung weiterentwickelt. Zielbereiche zum Rendern können hinzukommen oder wegfallen, dies führt zu permanenter Pflege einer wachsenden Zahl von Render-Attributen in der Anwendung. Gewünscht ist, dass fertiger Code nicht permanent wieder angefasst werden braucht.
* __Modularisierung:__ Bei Modulen, die durch JAR-Dateien ins Projekt kommen, kann auf die XHTML-Seiten kein Einfluss genommen werden. Dort soll ebenfalls ein Rendering möglich sein.
Die Lösung sind Events und der Render-Tag. Typischer Weise werden Events durch den Code ausgelöst, wie etwa beim Login:
{{{
Event.instance().raise(EVENT_LOGIN, authentication.getPrincipal());
}}}
Dadurch werden Bereiche neu gerendered:
{{{
<h:form id="process-form" enctype="multipart/form-data" styleClass="ui-widget" style="margin-left: 10px;">
<e:render event="intersult.subflow.Authenticator.login"/>
<e:render event="intersult.subflow.Process.change"/>
<e:render event="intersult.subflow.Process.select"/>
<e:div rendered="#{!empty processDetails.process}">
...
</e:div>
</form>
}}}
__Hinweis:__ Es können nur Bereiche neu gerendered werden, die bereits gerendered wurden. Dadurch können Render-Tags dadurch problemlos in Scopes und anderen dynamischen Berechen verwendet werden. Es ist völlig verträglich, wenn ein Abschnitt mit einem Render-Tag selbst nicht gerendered wurde, dieser wird dann einfach ignoriert.
__Tipp:__ Soll ein Bereich durch ein Render-Tag ein- und ausgeblendet werden, platziert man den Render-Tag in die übergeordnete Component. So wird die Region auf jeden Fall gerendered, unabhängig vom Render-Zustand (Render-Attribut, <c:if> etc.) der innen liegenden Sektion.
!!Async-Tag
Manchmal kann es von Vorteil sein, wenn der wichtigste Teil einer Seite sofort zur Verfügung steht. Andere Teile können dann nachgeladen werden. Dies trifft insbesondere zu, wenn eine langsame Verbindung besteht oder Teile der Seite mehr Zeit auf dem Server in Anspruch nehmen, etwa bei komplexen Datenbankanfragen oder Berechnungen.
Hier kann der Tag <e:async> verwendet werden, dieser lädt seinen Inhalt erst nach dem Rendern der Seite per AJAX nach:
{{{
<script type="text/javascript">
jsf.ajaxQueue = 10;
</script>
<c:forEach begin="1" end="20" var="index">
<e:div style="height: 20px; background-color: #e0e0e0; margin-bottom: 3px;">
<e:async>
<h:outputText value="Async Content #{index}, sleep = #{async.sleep}"/>
</e:async>
</e:div>
</c:forEach>
}}}
Und eine Klasse, die den Request verzögert:
{{{
@Component
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class Async {
private static Random random = new Random();
public int getSleep() throws InterruptedException {
int sleep = random.nextInt(3000);
Thread.sleep(sleep);
return sleep;
}
}
}}}
!!Socket-Tag und AJAX-Push
Mit sogenannten Push können Informationen aktiv an den Browser übertragen werden. Vor allem ist es dadurch möglich, eine Vielzahl von Benutzern gleichzeitig über ein Ereignis zu informieren.
Der Tag <e:socket> nutzt Web-Sockets um Browser-Push durchzuführen. Dies ist eine sehr effiziente Implementierung mit geringer Verzögerung zwischen dem Versenden der Nachricht und dem Eintreffen im Browser, sowie Netzwerk und Ressourcen schonend. Dies ist möglich, wenn der Web-Server den Web-Standard 3.0 beherrscht (z.B. ab Tomcat 7). Sind Web-Sockets nicht verfügbar aufgrund eines Web-Servers kleiner als 3.0, weil der Browser dies nicht beherrscht oder ein dazwischen liegender Proxy es nicht unterstützt, wird die Comet-Engine verwendet, die Long-Polling durchführt.
Zur Verwendung wird einfach das Atmosphere-Framework in die pom.xml konfiguriert:
{{{
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>2.0.0.RC3</version>
</dependency>
}}}
__Hintergrund:__ Es wird das Atmosphere-Framework verwendet, das mit allen gängigen Application-Servern und Browsern zusammen arbeitet.
Die Anwendung des Sockets sieht zum Beispiel so aus:
{{{
<e:socket channel="/test">
<f:ajax render=":push-form:chat"/>
</e:socket>
}}}
Auf der Java-Seite wird der Socket dann so angesprochen:
{{{
PushContext.instance().push("/test");
}}}
__Hinweis:__ Die Push-Funktionalität befindet sich momentan in der Entwicklung. In Zukunft werden weitere Funktionalitäten hinzukommen.
Wird ein Load-Balancer verwendet, sind die Web-Sockets zu beachten. Bei Apache werden folgende Proxy-Einträge vor der eigentlichen Applikation gebraucht:
{{{
ProxyPass /<context-path>/faces/javax.faces.resource/<channel> ws://<ziel>/<context-path>/faces/javax.faces.resource/<channel>
ProxyPassReverse /<context-path>/faces/javax.faces.resource/<channel> ws://<ziel>/<context-path>/faces/javax.faces.resource/<channel>
}}}
__Erklärung:__ Die Web-Socket-Protokolle WS werden vor den eigentlichen Proxy-Einträgen für die Application abgefangen und mit dem WS-Protokoll umgeleitet. In Apache 2.4 steht dafür das Modul mod_proxy_wstunnel.so zur Verfügung.