This page (revision-41) was last changed on 04-Sep-2014 13:44 by Dieter Käppel

This page was created on 21-Aug-2013 14:14 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
41 04-Sep-2014 13:44 35 KB Dieter Käppel to previous

Page References

Incoming links Outgoing links

Version management

Difference between version and

At line 1 changed one line
Das Produkt [JSF Ext] enthält eine ganze Reihe von JSF-Tags. Diese werden auf dieser Seite beschrieben.
Das Produkt [JSF Ext] enthält eine Reihe von JSF-Tags. Diese Seite beschriebt die Anwendung der Tags.
At line 3 changed one line
Die Tags <e:load>, <e:unload>, <e:scope> und <e:scopes> werden bei [JSF Ext Scopes] beschrieben.
Ausnahmen:
* Die <e:push> und <e:socket> für AJAX-Push werden in [JSF Ext Push] beschrieben.
* Die Tags <e:load>, <e:unload>, <e:scope> und <e:scopes> werden bei [JSF Ext Scopes] beschrieben.
At line 8 changed one line
!!!Insert Tag
!!!Control Tags
In diesem Abschnitt werden Tags für den Umgang mit Tag Handling und Aufbau der Page beschrieben.
!!Insert Tag
At line 41 changed one line
!!!Behavior-Tag
!!!JavaScript ausgeben
!!Behavior Tag
At line 62 changed one line
!!!Evaluate Tag
!!Evaluate Tag
At line 74 changed one line
Unterschied zwischen Behavior- und Evaluate-Tag:
!!Script Tag
Der Tag <e:script> gibt Scripte beim AJAX-Rendering aus. Es ist keine Kopplung an Behaviors oder Actions erforderlich. Dadurch können Aktionen beim Rendern von Components aufgeführt werden, zum Beispiel ein Highlighting durch JavaScript:
At line 76 changed 4 lines
||||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
{{{
<e:script script="ext.util.flash('some-tag', '#80ff80');"/>
}}}
At line 81 changed one line
!!!AJAX-Tag
!!Output Behavior
Der Tag <e:outputBehavior> gibt das Script anderer Behaviors als Text aus. Dies ist vor allem in Composite-Tags nützlich, die Behaviors unterstützen sollen. Dies ist vor allem bei AJAX-Request nützlich, weil es viel bequemer und robuster ist <f:ajax>, <e:ajax> oder dergleichen zu benutzen anstatt von jsf.ajax.request oder anderen JavaScript-Konstrukten.
Möchte man zum Beispiel einen Composite-Tag schreiben, der am unteren Ende einer Page ein Behavior ausführt, kann das wie folgt geschehen:
{{{
<?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"
>
<cc:interface>
<cc:clientBehavior name="behavior" event="behavior" targets="behavior" default="true"/>
</cc:interface>
<cc:implementation>
<h:outputScript name="util.js" library="ext-js"/>
<script id="#{cc.clientId}" type="text/javascript">
ext.util.addListener(window, 'scroll', function(event) {
var body = event.target.body;
var bottom = body.scrollTop + window.innerHeight;
if (bottom == body.scrollHeight) {
<e:outputBehavior id="behavior"/>
}
});
</script>
</cc:implementation>
</html>
}}}
__Erklärung:__ Der Tag definiert das Behavior "behavior" als Behavior-Parameter. Das übergebene Behavior wird dann an der Stelle des <e:outputBehavior> im JavaScript-Block ausgegeben.
__Hinweis:__ Dieser Tag ist als <ext:onscroll> bereits in [JSF Ext] enthalten.
!!Unterschiede der Tags
Unterschied zwischen Behavior-, Evaluate- und Script-Tag:
||||Behavior||Evaluate||Script
|Zeitpunkt der Ausführung|Direkt durch den Browser-Event|Durch den AJAX-Request an den Browser gesendet|Durch das AJAX-Rendering der Component
|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|Nur beim AJAX-Rendering, nicht beim Aufbau der Seite.
|Anwendungszweck|Steuerung des Browserverhaltens, Ein- und Ausblenden, Fading, dynamische Browserelemente, Client-Behavior|Abwickeln von Server-States, Popups öffnen und Schließen, Submits bestätigen|Spezielle AJAX- und Push-Features, Highlighting, Informationen.
!!!AJAX Tag
At line 84 changed one line
!Sources
!!Sources
At line 104 changed one line
!Action Source
!!Action Source
At line 113 changed one line
!Client-Behaviors
!!Client-Behaviors
At line 176 added 15 lines
!!Request Parameter
Der AJAX-Tag kann auch Request-Parameter übertragen.
{{{
<h:graphicImage name="process.png" library="images/info">
<e:ajax event="click" action="/index.xhtml">
<f:param name="mode" value="AVAILABLE"/>
</e:ajax>
</h:graphicImage>
}}}
__Achtung:__ Die im Value-Attribut verwendeten EL-Expressions werden bereits beim Rendern der View ausgewertet und können möglicher Weise veraltete, nicht gewünschte Werte enthalten. Verwenden sie diese Möglichkeit zur Übergabe von Parametern nur, wenn sie genau wissen, was sie tun.
__Hinweis:__ In den meisten Fällen ist es angebraucht, die Werte mit <e:set> (bzw. <f:setPropertyActionListener>) zu setzen, weil die entsprechenden EL-Expressions erst beim Drücken des Knopfs ausgewertet werden.
At line 139 changed one line
!!!Attribute-Tag
!!!Attributes und Paramters
!!Attribute Tag
At line 156 changed one line
!Attribute-Behaviors
!!Attribute-Behaviors
At line 167 changed one line
!Zusammengesetzte Attribute
!!Zusammengesetzte Attribute
At line 180 changed one line
!Part-Attribute
!!Part Attribute
At line 197 changed one line
!Style-Attribute
!!Style Attribute
At line 210 changed one line
!!!Reference-Tag
!!Method Parameters
Für Zwecke wie dem Laden eines Scopes mit <e:load> können Parameter mit <f:param> übergeben. Dies unterstützt allerdings nur Value-Expressions und keine Method-Expressions. Mit dem Tag <e:method-param> können auch Methoden übergeben werden. Dies geht allerdings nur, wenn EL 2.0 unterstützt wird.
{{{
<e:load viewId="/dialogs/someDialog.xhtml">
<e:method-param name="action" value="#{test.action}"/>
</e:load>
}}}
Damit können parameterisierte Dialoge erstellt werden, deren Action-Elemente bestimmte Methoden ausführen.
__Erklärung:__ Der Aufruf findet dann über #{scope.action.invoke} statt. Die eigentliche Methode wird im EL-Scope als Value abgelegt und enthält die Methode "invoke", mit der die Methode dann aufgerufen werden kann.
__Hinweis:__ Der Aufruf kann auch mit Parametern erfolgen, wenn #{scope.action.invoke(param)} verwendet wird.
Soll eine derart übergebene Method-Expression weitergereicht werden, kann dies als normaler <f:param> erfolgen:
{{{
<h:commandLink value="Nested">
<f:ajax/>
<e:load scopeId="select" viewId="/dialog.xhtml">
<f:param name="action" value="#{scope.action}"/>
</e:load>
</h:commandLink>
}}}
!!!Utility Tags
!!Reference-Tag
At line 215 changed one line
!!!New-Tag
!!New-Tag
At line 234 changed one line
!!!Set-Tag
!!Set-Tag
At line 270 changed one line
!!!Label
!!Label
At line 286 changed 2 lines
!!!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.
Darüber hinaus können die Klassen requiredStyleClass und notRequiredStyleClass auch manuell festgelegt werden, indem diese als Attribut angegeben werden.
At line 289 changed 32 lines
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
!!Move Listener
At line 338 changed one line
!!!Init-Tag
!!Init-Tag
At line 382 changed one line
!!!Otherwise-Tag
!!Otherwise-Tag
At line 401 changed 34 lines
!!!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
!!Async-Tag
At line 478 changed one line
!!!For-Tag
!!For-Tag
At line 497 changed 2 lines
!!!Method Parameters
Für Zwecke wie dem Laden eines Scopes mit <e:load> können Parameter mit <f:param> übergeben. Dies unterstützt allerdings nur Value-Expressions und keine Method-Expressions. Mit dem Tag <e:method-param> können auch Methoden übergeben werden. Dies geht allerdings nur, wenn EL 2.0 unterstützt wird.
!!Vertical Text Tag
Vertikaler Text, also um 90° gedrehter Text kann in einigen Fällen sehr hilfreich sein. Zum Beispiel um Platz zu sparen beim Beschriften von Header in Tabellen. Die Browser rendern Anweisungen für vertikale CSS-Anweisungen nur sehr uneinheitlich, wenn überhaupt.
At line 529 added 2 lines
Daher bietet [JSF Ext] einen Tag für das Rendern von vertikalen Text:
At line 501 changed 3 lines
<e:load viewId="/dialogs/someDialog.xhtml">
<e:method-param name="action" value="#{test.action}"/>
</e:load>
<e:vertical-text value="Hello World!" fontSize="16"/>
At line 506 changed one line
Damit können parameterisierte Dialoge erstellt werden, deren Action-Elemente bestimmte Methoden ausführen.
||Attribut||Bedeutung
|fontSize|Die Größe des Schriftsatz in Point (pt)
|width|Breite der gerenderten Grafik in Pixel
|height|Höhe der gerenderten Grafik in Pixel
|fontName|Name des Fonts
|color|Farbe der Schrift
At line 508 changed one line
__Achtung:__ Method-Parameters können nur mit EL-API 2.0 verwendet werden. Dies bedeutet auch, dass sie nicht mit einer EL-Implementierung 2.0 verwendet werden können, auch wenn diese auf EL-API 1.0 basiert, wie die JBoss-Implementierung.
!!Facet Tag
Dem Standard Tag <f:facet> fehlt leider das Attribut rendered. Man kann auch kein <c:if> herum wrappen. Bei Tabellen löst beispielsweise bereits der leere Tag "header" das Rendern des Headers aus. Der Tag <e:facet> implementiert dieses Attribut.
At line 510 changed one line
!!!Action Component
!!Embed Tag
Einige Zeit lang war Portlet das Stichwort für verteilte Web-Anwendungen. Leider hat sich die Implementierung als wenig praktikabel erwiesen, daher sind viele Firmen wieder davon abgerückt.
Eine einfachere Lösung für verteilte Anwendungen ist das Einbetten von Inhalten mit dem Tag <e:embed src="...">. Die Inhalte können vom gleichen Server, der gleichen Anwendung oder einer ganz anderen Quelle kommen. Da mit IFrames gearbeitet wird, ist nicht einmal [JSF] erforderlich oder die gleichen Komponentenbibliotheken.
!!!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.
!!!Action Support
!!Action Tag
At line 522 changed 2 lines
!!!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.
!!Action Context Tag
In [JSF] ist es vorgesehen, dass beim Ausführen einer Action-Methode die ausführende Komponente auf dem Component-Stack gepushed wird. Das bedeutet unter anderem, dass die Komponente mit UIComponent.getCurrentComponent(context) abgefragt werden kann. Dies ist wichtig, wenn man mit <f:attribute> gesetzte Werte abfragen möchte.
At line 525 changed one line
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.
Der Workaround besteht im Wrappen des Tags <e:actionContext> um die eigentliche Action-Source:
At line 527 removed 2 lines
Dazu ist folgende Dependency zum Projekt hinzuzufügen:
At line 530 changed 5 lines
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>2.1.0-beta1</version>
</dependency>
<p:treeTable id="table" value="#{cc.attrs.value}" var="node">
<p:column>
<e:actionContext>
<p:autoComplete ...>
<f:attribute name="param" value="#{node.someValue}"/>
</p:autoComplete>
</e:actionContext>
</p:column>
</p:treeTable>
At line 537 changed 2 lines
!!Push-Tag
Der Push-Tag ist die einfachste Art, AJAX-Push zu implementieren. Der Tag <e:push> stellt eine transparente Verbindung zu einem Push-Channel her. Der Inhalt des Tags wird auf alle Clients verteilt, die mit dem gleichen Channel verbunden sind:
__Erklärung:__ Bei der Primefaces Tree-Table wurde offenbar vergessen der Component-Push
At line 540 changed 14 lines
{{{
<h:form id="form">
<h:commandButton value="Senden" action="#{pushTest.action}">
<f:ajax render=":test:value"/>
</h:commandButton>
</h:form>
<e:push id="test" direct="true">
<h:panelGrid id="panel" columns="2">
<h:outputText id="text" value="Test"/>
<h:outputText id="value" value="#{pushTest.count}"/>
</h:panelGrid>
</e:push>
}}}
!!!Composite Tags
[JSF Ext] enthält auch bereits einige Composite Tags, diese sind unter dem Namespace xmlns:ext="http://java.sun.com/jsf/composite/ext" verwendbar.
At line 555 changed one line
__Erklärung:__ Der Tag ":test:value" wird durch eine einfache AJAX-Render-Anweisung auf allen verbundenen Clients neu gerendert.
!!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.
At line 557 changed 2 lines
!Direct- und AJAX-Mode
Der Push-Tag kann in zwei unterschiedlichen Modi betrieben werden: Direct und AJAX:
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.
At line 560 changed 6 lines
||Eigenschaft||Direct Mode||AJAX Mode
||Rendering|Inhalt wird nur bei dem Client gerendert, der den Event ausgelöst hat|Inhalt wird für jeden Client gerendert
||Effizienz|Effizienter Modus, da das HTML-Update direkt an alle Clients geschickt werden kann|Rendering wird für jeden Client getrennt gerendert
||Inhalt|Inhalt ist für jeden Client identisch|Inhalt kann für jeden Client individualisiert werden
||Daten|Anzeige von Daten die für mindestens eine Gruppe bestimmt oder öffentlich ist|Anzeige privater Daten möglich
||Auslöser|Auslöser ist ein Faces-Event|Auslöser kann ein Timer oder beliebiger Event sein
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:
At line 567 changed 2 lines
!Rendering
Die beim Render-Attribut angegebenen Ids werden einzeln gerendert und nur der relevante Inhalt zum Client übertragen. Auch wenn sich innerhalb des Push-Tag große Mengen an Tags befinden, wird nur die relevante Änderung übertragen, sofern die Render-Anweisungen entsprechend ausgelegt sind.
{{{
<ext:busyPointer/>
}}}
At line 570 changed one line
Damit ist es beispielsweise möglich, eine Tabelle zu erzeugen und einzelne Zellen per Push upzudaten.
Optional kann das Attribut cursor angeben werde, das per default auf "wait" gesetzt ist.
At line 572 changed 2 lines
!Channel
Wird der Channel-Attribut nicht angegeben, wird die Client-Id der Component als Channel benutzt.
!!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.
At line 575 changed one line
__Warnung:__ Channel-Name und Push-Tag sollte für alle Clients übereinstimmen, damit die Inhalte übereinstimmen. Andernfalls kommt es zu sogenannten Cross-Talking - der Inhalt des Push-Tags ändert sich.
Eine Lösung ist der Tag <ext:mouse-visibility>:
At line 577 removed 3 lines
!!Socket-Tag
Mit dem Socket-Tag ist eine fortgeschrittenere Integration von AJAX-Push in die Applikation möglich. Dazu wird einfach ein sogenannter Socket in die XHTML-Seite gesetzt:
At line 581 changed 3 lines
<e:socket channel="/test">
<f:ajax render=":push-form:chat"/>
</e:socket>
<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>
At line 586 changed one line
Auf der Java-Seite wird der Socket dann so angesprochen:
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.
At line 652 added 3 lines
!!Onscroll Tag
In den letzten Jahren ist das automatische Nachladen von Content modern geworden, wenn die Web-Seite am unteren Ende angelangt ist. Dies lässt sich leicht mit dem Tag <ext:onscroll> realisieren:
At line 589 changed one line
PushContext.instance().push("/test");
<ext:onscroll>
<e:ajax action="#{dashboard.more}" render=":dashboard-form:transaction-list:list"/>
</ext:onscroll>
At line 592 changed one line
__Hinweis:__ In vielen Fällen reicht die reine Benachrichtigung des Client aus, weil dieser dann per AJAX-Call eine Server-Anfrage startet. Dies bietet den Vorteil, dass die Session und der FacesContext des entsprechenden Benutzers verfügbar ist.
__Erklärung:__ Der Tag führt das Behavior <e:ajax/> aus, sobald ans untere Ende der Page gescrollt wird.
At line 594 changed one line
Die Socket-Component unterstützt folgende Attribute und Behaviors:
!!!Resource Link
JSF-Resources können mit <h:outputStylesheet> und <h:outputScript> ausgegeben werden, mit <h:graphicImage> als Image angezeigt. Einige weitere Tags unterstützen die Attribute "name" und "library". Darüber hinaus gibt es die Möglichkeit, Resource-URLs mit
At line 596 removed 10 lines
||Attribut||Beschreibung
|channel|Das Attribut wird benötigt und beschreibt den Kommunikationskanal zum Server. Indem der Server diesen Channel informiert, wird im Browser eine Nachricht ausgeliefert. Die Besonderheit am Channel ist, dass dieser von beliebig vielen Browsern d.h. eingeloggten Benutzern abonniert werden kann. Der Server braucht daher nicht zu wissen, wieviele Clients überhaupt die Nachricht empfangen werden.
|onopen|Der Event wird beim Öffnen des Channels ausgelöst. Der Client weiß so immer, ob er verbunden ist oder nicht. Dadurch kann dem Nutzer auch ein Verbindungsstatus angezeigt werden.
|onclose|Das Gegenstück zu onopen, wird aufgerufen, wenn die Verbindung abbricht. Im normalen Produktivbetrieb wird diese Methode nur in Ausnahmefällen aufgerufen.
|onmessage|Dies ist der eigentliche Push-Aufruf. Wenn am Server PushContext.push() aufgerufen wird, wird am Client dieses JavaScript-Behavior ausgelöst.
|onerror|Hier kann eine Fehlerbehandlung hinzugefügt werden, zum Beispiel dem Benutzer angezeigt werden, wenn ein Problem mit der Verbindung auftaucht.
!!Push-Context
Auf der Server-Seite gibt es die Klasse com.intersult.jsf.push.PushContext. Um eine Nachricht zu einem Tag <e:socket channel="/test"> zu schicken, wird hier ein entsprechender Methodenaufruf durchgeführt:
At line 607 changed one line
PushContext.instance().push("/test");
#{resource['<library>:<name>']}
At line 610 changed 2 lines
!!Push-Parameter
Optional kann der Aufruf auch mit einem Parameter erfolgen, der wird dann JSON-Serialisiert und an den Client übertragen:
zu erzeugen oder ganz zu Fuß mit
At line 614 changed one line
PushContext.instance().push("/test", parameter);
#{request.contextPath}/faces/javax.faces.resource/<name>?ln=<library>
At line 617 changed one line
Auf der Client-Seite kann der Parameter dann wie folgt entgegen genommen werden:
Möchte man einen Link erzeugen vom Schema <a href="...">, bietet [JSF Ext] eine schönere Lösung:
At line 620 changed one line
<e:socket channel="/test" onmessage="alert(response.responseBody);">
<e:resourceLink name="<name>" library="<library">
<h:outputText value="Some link"/>
</e:resourceLink>
At line 623 changed 2 lines
!!Load Balancer und Reverse Proxy
Wird ein Load-Balancer verwendet, sind die Web-Sockets zu beachten. Bei Apache werden folgende Proxy-Einträge vor der eigentlichen Applikation gebraucht:
__Hinweis:__ Wie der normale <h:outputLink> unterstützt <h:resourceLink> ebenfalls Parameter vom Typ <f:param>. Des Weiteren ergänzt sich der Link gut mit [Resource Provider|JSF Ext#Resource Provider]
At line 686 added 11 lines
!!!Faces Messages
Das Rendern von Faces Messages braucht üblicher Weise eine explizite Rendering Message. Wird es vergessen, kann der Benutzer nicht erkennen, welches Feld falsch eingegeben wurde.
!!Einfache Message
[JSF Ext] stellt daher selbst rendernde Faces-Messages zur Verfügung als Tag <ext:message>.
!!Severity Tag
Oft sind Seiten komplex aufgebaut und Steuerelemente versteckt. Dafür gibt es den Tag <ext:severity prefix="...">. Dieser Zeigt ein Severity-Icon an für alle Messages mit einem bestimmten Prefix, das heißt für einem Nameing-Container untergeordnete Components.
Der Severity-Tag ist eine Composite Component mit folgender Implementierung:
At line 627 changed 2 lines
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>
<h:panelGroup id="messages" style="#{cc.attrs.style}" styleClass="#{cc.attrs.styleClass}">
<e:render id="render" for=":#{cc.attrs.prefix}:*"/>
<h:graphicImage name="info.png" library="images/message"
rendered="#{e:severity(cc.attrs.prefix) == 'INFO'}"/>
<h:graphicImage name="warn.png" library="images/message"
rendered="#{e:severity(cc.attrs.prefix) == 'WARN'}"/>
<h:graphicImage name="error.png" library="images/message"
rendered="#{e:severity(cc.attrs.prefix) == 'ERROR'}"/>
</h:panelGroup>
At line 631 changed one line
__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.
!!!Captcha Component
In [JSF Ext] ist eine Captcha Component enthalten. Diese bringt ihre eigene Graphic-Resource mit, es werden also keine externen URLs angesprochen. Das Captcha ist also voll kompatibel zu HTTPS und AJAX. Kein dritter Provider kann ein Tracking der Site vornehmen.
At line 633 changed 2 lines
!!!Resource-Tag
JSF-Resources können mit <h:outputStylesheet> und <h:outputScript> ausgegeben werden, mit <h:graphicImage> als Image angezeigt. Einige weitere Tags unterstützen die Attribute "name" und "library". Darüber hinaus gibt es die Möglichkeit, Resource-URLs mit
!!Eigenschaften
Bei Captchas gibt es einige Unterschiede bezüglich des Lifecycle und der Validierung:
At line 715 added 9 lines
* __Default Lifecycle:__ Das Captcha wird in der Session abgelegt. Grundsätzlich führt ein Reload der Page zur Anzeige desselben Captchas.
* __Neues Captcha:__ Durch den Refresh-Knopf wird ein neues Captcha angezeigt. Die Klasse "Captcha" bzw. die Bean "captcha" kann das Captcha mit der Methode "reset" zurückgesetzt werden, sodass beim Rerendering ein neues Captcha angezeigt wird.
* __AJAX:__ Es spielt keine Rolle, ob das Captcha direkt im HTTP-Request geladen wird, oder ob es durch einen AJAX-Request nachgeladen wird. Im Gegensatz zu komplizierten IFrame und Javascript-Lösungen funktioniert <e:captcha> in den meisten Umgebungen.
* __Wiederholte Validierung:__ Die Eingabe kann ein- oder mehrfach positiv validiert werden. Das Captcha wird dabei nicht verändert, wenn es einmal erfolgreich validiert wurde. Der Benutzer kann damit andere Validierungsfehler beheben, ohne das Captcha ständig neu eingeben zu müssen.
* __Negative Validierung:__ Bei negativer Validierung, also Validation failed, wird ein neues Captcha generiert. Damit wird vermieden, dass der Anwender denselben Lesefehler wiederholt.
!!Beispiel
Das Captcha kann als Component in die Seite eingebaut werden:
At line 637 changed one line
#{resource['<library>:<name>']}
<h:form id="form">
<e:captcha id="captcha"/>
<ext:message for=":form:captcha"/>
...
</h:form>
At line 640 changed one line
zu erzeugen oder ganz zu Fuß mit
__Erklärung:__ Die Captcha Component rendert ein PNG-Image mit dem entsprechenden Text, sowie ein Eingabefeld, in dem der Text durch den Benutzer eingegeben wird. Die Component hat eine positive Validierung, wenn das Captcha korrekt ist, andernfalls schlägt die Validierung fehl und eine Faces Message wird eingefügt. Das Fehlschlagen der Validierung verhindert das Ausführen von Action Methoden, die an Command Buttons und ähnlichem hängen.
At line 735 added 2 lines
Um die Captcha Component zu verwenden, ist folgendes Maven Artifact in der pom.xml einzubinden:
At line 643 changed one line
#{request.contextPath}/faces/javax.faces.resource/<name>?ln=<library>
<dependency>
<groupId>com.octo.captcha</groupId>
<artifactId>jcaptcha</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
At line 646 changed one line
Möchte man einen Link erzeugen vom Schema <a href="...">, bietet [JSF Ext] eine schönere Lösung:
__Hinweis:__ Das Artifact hat die servlet-api im Scope "compile" eingebunden. Um das Deployen der servlet-api.jar zu vermeiden, ist die Exclusion erforderlich. Andernfalls kann es zu Problemen beim Deployment kommen.
At line 754 added 4 lines
!!!Behavior Tags
!!Characters Left
Bei Steuerelementen von Text-Areas oder Text-Input kann es von Vorteil sein, die Anzahl der möglichen Zeichen sehen zu können. Dazu fügt der Tag <e:charactersLeftBehavior> einen Zähler ein:
At line 649 changed 3 lines
<e:resourceLink name="<name>" library="<library">
<h:outputText value="Some link"/>
</e:resourceLink>
<h:inputTextarea id="comment" value="#{processDetails.comment}">
<e:charactersLeftBehavior event="keyup"/>
</h:inputTextarea>
At line 654 changed one line
__Hinweis:__ Wie der normale <h:outputLink> unterstützt <h:resourceLink> ebenfalls Parameter vom Typ <f:param> (und abgeleitete Parameter wie <f:method-param> und <f:new>).
__Erklärung:__ Die Anzahl möglicher Zeichen werden den Javax-Validation-Tags @Size und @Length oder dem LengthValidator entnommen. Die verbleibenden Zeichen werden dann im Text-Feld eingeblendet, die Eingabe wird auf die maximale Zeichenzahl begrenzt.