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 4 changed one line
[JSF Ext] wurde weiter vereinfacht, sodass eine hohe Geschwindigkeit der Web-Seiten erreicht werden kann. [JSF Ext] wurde optimiert, sodass höchst mögliche Kompatibilität mit anderen Produkten sichergestellt ist. Sollten Sie Fragen, Bugs oder Feature-Requests haben, so nutzen sie bitte die [Issue List|https://code.google.com/p/jsf-ext/issues/list].
[JSF Ext] wurde weiter vereinfacht, sodass eine hohe Geschwindigkeit der Web-Seiten erreicht werden kann. [JSF Ext] wurde optimiert, sodass höchst mögliche Kompatibilität mit anderen Produkten sichergestellt ist. Sollten Sie Fragen, Bugs oder Feature-Requests haben, so nutzen sie bitte die [Issue List|https://www.sub-flow.com/subflow/project/SUBFLOW].
At line 6 changed one line
Einige der Features:
Übersicht der Features:
At line 11 changed 2 lines
* __Events:__ Einfach nutzbare Event-Erzeugung und automatisches Rendering
* __Push:__ AJAX-Push unabhängig von verwendeten Frameworks
* __Events:__ Einfach nutzbare Events und automatisches Rendering
* __Push:__ AJAX-Push unabhängig von verwendeten Framework
At line 15 added one line
* __Persistence:__ [JSF Ext] läuft auch ohne Hibernate, diese Funktionalität befindet sich in [JPA Support].
At line 17 added 9 lines
Folgende Inhalte befinden sich auf eigenen Wiki-Seiten:
* [JSF Ext Tags]
* [JSF Ext Scopes]
* [JSF Ext Events]
* [JSF Ext Push]
* [JSF Ext Functions]
* [Faces Filter]
At line 29 changed one line
Die Anwendung befindet sich im [Intersult Maven Repository]:
[JSF Ext] kann von [Central|http://search.maven.org/] bezogen werden:
At line 31 changed one line
In der pom.xml wird angegeben:
In der pom.xml für den Maven-Build wird angegeben:
At line 41 changed one line
<version>2.2-SNAPSHOT</version>
<version>2.2.0.1</version>
At line 45 removed 8 lines
<repositories>
<repository>
<id>intersult-repo</id>
<name>Intersult Repository</name>
<url>http://repository.intersult.com/repository</url>
</repository>
...
</repositories>
At line 83 removed 14 lines
!!Redirects
Standardmäßig schicken Command-Tags wie <h:commandButton> das Formular ab und rendern unter umständen eine neue ViewId. Dabei entstehen zwei Probleme:
* Im Browser wird bei einem View-Wechsel die vorherige View-Id angezeigt, anstatt der neuen View-Id.
* Ein Refresh der Seite durch den Browser führt zu Komplikationen, die Submit-Parameter müssen nochmals abgeschickt werden. Die meisten Browser legen dabei ein für den Benutzer wenig verständliches Verhalten an den Tag, Popups öffnen sich mit merkwürdigen Fragen.
Die Lösung besten in einem Redirect nach dem Submit, der häufig Page für Page, Action für Action in das Projekt reingezogen wird. Die Nachteile seitens Wartbarkeit, Konsistenz und Veränderbarkeit liegen auf der Hand. Eine saubere Lösung besteht darin, einen entsprechenden Navigation-Handler zu benutzen:
{{{
<navigation-handler>com.intersult.jsf.util.RedirectNavigationHandler</navigation-handler>
}}}
__Hinweis:__ Der Redirect-Navigation-Handler ist per Default deaktiviert, da dies einen erheblichen Eingriff in den Page-Flow und damit das Standard-Verhalten von JSF darstellt. Das Feature kann bei Bedarf durch die oben gezeigte Zeile einfach selbst in die eigene faces-config.xml eingefügt werden.
At line 108 removed 2 lines
!!![Tags|JSF Ext Tags]
At line 152 changed one line
JSF-Behaviors bestehen aus einer Klasse die von Behavior oder ClientBehavior abgeleitet sind. Im Wesentlichen ist eine Methode getScript enthalten, mit der ein Fragmet des entsprechenden event-Attribut des entsprechenden HTML-Tags gerendert wird, also zum Beispiel onclick="...". Bei komplexeren Behaviors braucht man zusätzlichen HTML-Code, der kann an dieser Stelle nicht geschrieben werden. Ursache ist dass der HTML-Writer sich gerade innerhalb des geöffneten Tags befindet und startElement ungültiges HTML erzeugen würde.
JSF-Behaviors bestehen aus einer Klasse die von Behavior oder ClientBehavior abgeleitet sind. Im Wesentlichen ist eine Methode getScript enthalten, mit der ein Fragment des entsprechenden event-Attribut des entsprechenden HTML-Tags gerendert wird, also zum Beispiel onclick="...". Bei komplexeren Behaviors braucht man zusätzlichen HTML-Code, der kann an dieser Stelle nicht geschrieben werden. Ursache ist dass der HTML-Writer sich gerade innerhalb des geöffneten Tags befindet und startElement ungültiges HTML erzeugen würde.
At line 164 changed 2 lines
!!!Events
Events sind eine Erweiterung des Action- und Update-Systems von JSF. Events können von der Java- und XHTML-Seite erzeugt und konsumiert werden.
!!Components referenzieren
In JSF gibt es drei Arten von Referenz-Ausdrücken in render und execute Ausdrücken, relative, absolute und meta:
At line 167 changed 10 lines
||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.
* __Absolute:__ Beispielsweise :form:panel:input-text
* __Relative:__ panel:input-Text
* __Meta:__ @this, @component, @form, @all
At line 178 changed 2 lines
!!Hintergrund
In [JSF] werden oft Render-Attribute direkt in AJAX- und anderen Anweisungen angegeben. Da diese lose gekoppelt sind, wird im günstigen Fall eine Fehlermeldung entstehen, dass die entsprechende Id nicht mehr im Component Tree vorhanden ist. Der nachträgliche Einbau zusätzlich zu rendernder Components ist nicht vorgesehen, diese müssen explizit am Render-Attribut aller betreffenden Anweisungen hinzugefügt und gepflegt werden.
Meist arbeitet man soweit es geht mit relativen Ausdrucken und wechselt notfalls zu absoluten. Um die allgemeine Verwendbarkeit von absoluten Ausdrücken in Composite Components zu gewährleisten, beginnt man diese etwa mit :#{cc.clientId}:input-Text. Das funktioniert leider nicht immer, insbesondere wenn Tabellen, For-Tags oder andere dynamische Elemente darüber liegen.
At line 181 changed one line
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.
Dazu führt [JSF Ext] die Syntax ".." ein, die man bereits von relativen Pfadangaben im Dateisystem kennt. Damit ist es nun möglich innerhalb einer Composite Component einen oder einige Components nach oben zu gehen und von dort ab etwas zu selektieren. Also die Kombination von relativen Angaben und Erreichbarkeit der Components:
At line 183 removed 5 lines
!!Java
Ein Event wird erzeugt, indem die Instanz von Event geholt wird. Dies kann durch @ManagedProperty("#{event}") geschehen oder durch die statische Methode Event.instance(). Dabei ist zu beachten, dass keine Session scoped Bean in einen Application Context injected wird.
Das Session basierte Event-Objekt enthält die Methode raise(String event, Object... arguments), also im einfachsten Fall:
At line 189 changed one line
Event.instance().raise("com.intersult.some-event");
<e:ajax render="..:#{cc.id}:panel"/>
At line 192 changed one line
Die Events werden in der Regel durch eine Annotation konsumiert:
__Hinweis:__ Jede Angabe von ".." geht eine Naming-Container nach oben. Components die kein Naming Container sind, werden dabei übersprungen, ebenso wie beim ursprünglichen Absteigen im Component Tree mit x:y:z.
At line 194 removed 111 lines
{{{
@Listener("com.intersult.some-event")
public void someEvent() {
}
}}}
Es ist zu beachten, dass Events nur empfangen werden wenn eine Bean tatsächlich instantiiert ist.
!!FacesMessages
Events können auch im XHTML verarbeitet werden, indem bestimmte Bereiche neu gerendert werden.
!FacesMessages
Zum Beispiel der vorgefertigte Event javax.faces.messages, der bei vorhandenen Faces-Messages ausgelöst wird:
{{{
<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.
!Beispiel Input-Wrapper
__Situation:__ In einer Anwendung kommen zumeist verschiedene Eingabeelemente wie <h:inputText>, <h:selectOneMenu>, <h:inputSecret>, <h:selectBooleanCheckbox> sowie selbst gebaute Tags zur Verwendung. Für die Applikation besteht gewöhnlich ein einheitliches Layout mit AJAX- oder Client-Side Validierung, FacesMessages und weiteren Elementen.
__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].
!!Component FacesMessages
[JSF Ext] generiert auch Events für Component FacesMessages, die entstehen beim Konvertieren, Validieren oder manuell in Java-Code. Oft wird unnötiger Weise das komplette Form neu gerendert, um die Component FacesMessages anzuzeigen. Mit [JSF Ext] können gezielt einzelne Messages gerendert werden, wenn diese auftreten. Um eine Komponenten durch eine Faces-Message rendern zu lassen, kann das for-Attribut verwendet werden:
{{{
<e:render for=":form:some-text"/>
}}}
Der Event tritt in folgenden Fällen auf:
* Nur wenn die Component vom AJAX-Execute betroffen ist
* Wenn eine FacesMessage für die Component zum ersten Mal vorhanden ist
* Wenn eine FacesMessage für die Component zum zweiten oder öfteren Mal vorhanden ist
* Wenn keine FacesMessage für die Component verschwunden ist
__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.
!!Raise-Component
Events können hervorragend dazu benutzt werden, um AJAX-Submits und Rerendering voneinander zu trennen. Events werden dabei durch Components erzeugt und von anderen Components konsumiert. So braucht die erzeugende Component zur Erstellungszeit nicht wissen, welche Components rerendered werden:
{{{
<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.
!!Hinweise
Events sind momentan Session-basiert, das heißt es existieren keine Application übergreifenden Events.
!!![Scopes|JSF Ext Scopes]
At line 194 added 25 lines
!!Properties Resources
In [JSF] können Properties-Dateien definiert werden, die entsprechend der Endung im Namen für die Internationalisierung verwendet werden können. Um auch aus dem Java-Code darauf zugreifen zu können, gibt es die Klasse com.intersult.jsf.messages.Resource:
||Methode||Beschreibung
|getString|Den Resource-String zurückgeben. Falls nicht vorhanden, wird ein Dummy zurückgegeben.
|getStringNull|Den Resource-String zurückgeben. Falls nicht vorhanden, wird null zurückgegeben.
|getStringVariant|Eine Variante eines Resource-Strings zurückgeben.
|getFormatVariant|Eine formatierte Variante eines Resource-Key zurückgeben.
|getFormat|Einen formatierten Resource-String zurückgeben.
|addMessage|Eine globale Faces-Message aus einem Resource-Key hinzufügen.
|addMessageToComponent|Eine Faces-Message aus einem Resource-Key zu einer Komponente hinzufügen.
|getMessage|Eine Faces-Message aus einem Ressource-Key erzeugen
|enumFormat|Einen formatierten Resource-String für ein Enum zurückgeben.
|enumFormatVariant|Eine Variante eines formatierten Resource-String für ein Enum zurückgeben.
|enumString|Einen Resource-String für ein Enum zurückgeben.
|enumList|Eine Liste mit Enums zurückgeben.
|enumStringList|Eine Liste mit Enum-Strings zurückgeben.
|enumStringListVariant|Eine Liste mit Varianten von Enum-Stringe zurückgeben.
|enumSelectItems|SelectItems für das Befüllen von JSF-Elementen (Dropdowns etc.) zurückgeben
|enumSelectItemsType|SelectItems für einen Enum-Type zurückgeben.
|enumSelectItemsTypeVariant|SelectItems für Varianten eines Enum-Types zurückgeben.
|enumSelectItem|Ein einzelnes SelectItem erzeugen.
|abbreviate|Einen String für die Oberfläche abkürzen.
|replaceHtml|HTML-Sonderzeichen ersetzen.
At line 378 changed one line
@Value("#{scope.rule}")
@ScopeValue
At line 500 changed one line
<h:outputLabel for="name" value="Name"/>
<h:outputLabel for="name:name" value="Name"/>
At line 451 added 7 lines
!!Validation Messages
Die ValidationException von JSF nimmt den String direkt. [JSF Ext] stellt eine Ableitung davon zur Verfügung, mit der ein Resource-Key übergeben werden kann. Damit ist eine Internationalisierung möglich:
{{{
throw new ValidatorResourceException("user.unique.name");
}}}
At line 610 changed one line
|mimeType|Enthält den vom Browser gesendeten Mime-Type.
|mimeType|String|Enthält den vom Browser gesendeten Mime-Type.
At line 529 added 129 lines
__Achtung:__ Es gibt Servlet-Filter, welche den InputStream des HttpServletRequest nicht korrekt durchreichen. Sie sollten diese Filter ausschalten, sonst kann der File-Upload nicht an die entsprechende Datei herankommen.
!!!Utilities und Tools
[JSF Ext] enthält einige Instrumente zur Unterstützung der Entwicklung von weiteren Tool- und Component-Bibliotheken für [JSF].
!!Document Writer
[JSF] bietet die Möglichkeit zum Einsatz von Render-Kits, also eine alternative Darstellung der XHTML-Seiten. Der Standard-Writer schreibt allerdings HTML-Code direkt als Stream. Für Anwendung wie z.B. PDF generieren wäre sinnvoll, auf den Document-Tree zuzugreifen. Dafür kann der Document Writer eingesetzt werden:
{{{
DocumentWriter writer = new DocumentWriter(context.getResponseWriter(), "application/pdf");
context.setResponseWriter(writer);
}}}
__Hinweis:__ Für die Integration in den JSF Lifecycle sind noch einige andere Dinge zu beachten. Dies zu erklären wäre zu umfangreich für diese Dokumentation, dies kann in der Dokumentation für JSF nachgelesen werden.
!!XML Rendering
Soll die Seite direkt als XML gerendert werden, bietet [JSF Ext] noch eine weitere Kapselung des Document Writer an. Die Methode Jsf.renderViewXml kann direkt aus einem HTTP-Request ein XHTML-Document rendern, ohne über das JSF-Servlet zu gehen.
Dies kann nützlich sein, wenn der Document-Tree weiter verarbeitet werden soll, zum Beispiel zum Generieren anderer Ansichten.
__Hinweis:__ Für PDF steht das [PDF Renderkit] zur Verfügung. Andere Browser- und Download-Ansichten sollten generell in der Form eines Renderkit zur Verfügung gestellt werden. Für weitere Unterstützung beraten wir Sie gerne.
!!Unwrapping FacesWrapper
Vor allem seit [JSF 2|JSF2] wurde die faces-config.xml weiter ausgebaut. JSF-Komponenten können viele JSF-Klassen wrappen, indem sie das Interface FacesWrapper implementieren. Einige Klassen haben diesen Wrapper bereits implementiert, sodass sie nur noch abgeleitet werden brauchen. [JSF Ext] enthält noch weitere Wrapper im Package com.intersult.jsf.wrapper.*, wie zum Beispiel ViewRootWrapper oder ValueExpressionWrapper, die das Implementieren von Komponenten unterstützen können.
Dahinter liegender Sinn ist das Zusammenspiel mehrerer Faces-Erweiterungen nebenher. Die Wrapper werden in unbestimmter Reihenfolge aufgerufen, sodass jede betroffene Klasse prüfen kann, ob sie etwas zu tun hat. Falls nicht, gibt sie den Aufruf einfach an die Wrapped Instance weiter.
Einen Nachteil gibt es bei der Sache: Hat man FacesWrapper erst einmal abgeleitet, kommt man meist nur mehr sehr schwierig an die eigene Klasse ran. Abhilfe schafft die Methode Jsf.unwrap, mit der man seine eigenen (oder auch fremde) Klassen in der Wrapper-Kette findet:
{{{
ExtFacesContext extContext = Jsf.unwrap(parent, ExtFacesContext.class);
}}}
!!Expression Analyzer
Methoden um Referenzen auf EL-Expressions zu bekommen, Expressions umzuwandeln. Wird gebraucht, um Validierungen an der Oberfläche vornehmen zu können.
{{{
ValueReference reference = ExpressionAnalyzer.getReference(expression, context.getELContext());
Object base = reference.getBase();
}}}
!!Interpolator
Mit dem Interpolator können EL-Expressions innerhalb eines Strings ersetzt werden.
||Methode||Bedeutung
|interpolate|Einen String interpolieren.
|evaluate|Eine Expression evaluieren.
|create|Eine neue EL-Expression anlegen.
|createMethodExpression|Eine Method-Expression erzeugen.
|createValueExpression|Eine Value-Expression erzeugen.
|createLiteral|Eine Literal-Expression erzeugen.
|coerce|Eine Typumwandlung vornehmen.
|setVariable|Eine Variable setzen.
|restoreVariable|Eine Variable wiederherstellen.
|action|Eine Action-Expression ausführen.
|converterFor|Einen Converter für eine bestimmte Klasse holen.
!!IO Utils
Methoden für das Schreiben, Lesen und Kopieren von Streams:
{{{
IOUtils.copy(binaryStream, outputStream);
}}}
!!!Navigation
[JSF Ext] enthält eine transparente Lösung für das Redirect-After-Submit-Pattern. Am besten arbeitet diese Lösung mit web.xml 3.0 und Application-Servern, wie Tomcat 7, die diesen Standard unterstützen.
__Hintergrund:__ Ohne Redirect-After-Submit wird nach der Navigation auf eine andere Seite in der Browser-URL-Zeile die vorhergehende Seite angezeigt. Des Weiteren wird bei einem Seiten-Request die für den Benutzer oft unverständliche Meldung angezeigt, ob die Seite nochmal abgeschickt werden soll. Ziel des Redirect-After-Submit-Pattern ist beides zu vermeiden.
Redirect-After-Submit wird aktiv, wenn man [JSF Ext] einbindet und web.xml 3.0 verwendet. Alle Page-Submits mit <h:commandButton>, <h:commandLink> etc. werden mit einem Redirect abgeschlossen.
__Ergebnis:__ Nach der Navigation wird die aktuelle URL im Browser angezeigt. Refresh der Seite im Browser kann ohne Rückfrage durchgeführt werden.
__Hinweis:__ Bei einem Redirect geht üblicher Weise der Zustand der Seite verloren. [JSF Ext] nutzt den sogenannten Flash-Scope von [JSF], um dieses Hindernis zu überwinden und auch Faces-Messages über den Redirect zu retten. Daher ist web.xml 3.0 und Tomcat 7 für das saubere Arbeiten erforderlich.
Bei web.xml 2.x und Tomcat 6 kann ein Fallback-Mechanismus verwendet werden, der die View-Id als GET-Parameter an die URL hängt. Dies ist zwar problemlos möglich, jedoch können dann keine "sauberen" URLs mehr produziert werden. Dieses Verhalten kann mit einem Konfigurations-Parameter in der web.xml aktiviert werden:
{{{
<context-param>
<param-name>javax.faces.REDIRECT_AFTER_SUBMIT</param-name>
<param-value>true</param-value>
</context-param>
}}}
!!!Fehler und Exceptions
[JSF Ext] enthält mehrere Mechanismen für das Handling von Exceptions. Grundlage dazu ist der ExtExceptionHandler und eine speziell Ableitung, der AjaxExceptionHandler.
!!AJAX Exception Handler
Der Handler ist dafür verantwortlich, dass Exceptions während eines AJAX-Requests nicht die komplette Seite lahm legen. Eine derartige Exception wird ins Logfile eingetragen und eine Faces-Message dafür generiert.
Dabei existieren zwei Konfigurationsparameter:
||Parameter||Bedeutung
|javax.faces.IGNORE_EXCEPTIONS|Eine durch Kommata separierte Liste von voll qualifizierten Exception-Klassen-Namen, die ignoriert werden sollen. Diese tauchen nicht als Fehler auf. Damit sollte sehr vorsichtig umgegangen werden, weil es zu versteckten Fehlfunktionen in der Applikation führen kann, die später sehr schwer zu finden sein können.
|javax.faces.PASS_EXCEPTIONS|Diese Exceptions werden an den nächsten Exception-Handler durchgelassen. Dies ist für Exceptions sinnvoll, für die man einen eigenen Exception-Handler schreiben möchte oder eine Dritt-Software hat, die diese handeln möchte.
!!Full Request Exception Handler
Wenn kein AJAX-Request vorliegt oder die Exception in javax.faces.PASS_EXCEPTIONS konfiguriert wurde und von keinem anderen Exception-Handler verarbeitet wurde, erreicht sie den ExtExceptionHandler.
Dieser erlaubt das Definieren von Exception-Navigationen in der faces-config.xml:
{{{
<navigation-rule>
<navigation-case>
<from-outcome>org.springframework.security.access.AccessDeniedException</from-outcome>
<to-view-id>/security/login.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<navigation-case>
<from-outcome>java.lang.Throwable</from-outcome>
<to-view-id>/error.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
}}}
__Erklärung:__ Die erste Navigationsregel leitet alle Fälle von AccessDeniedException auf die View /security/login.xhtml um. Die zweite Regel für Throwable leitet alle Exceptions, die nicht von vorherigen Regeln erfasst wurden auf die View /error.xhtml um.
Die aufgetretene Exception wird dabei in einer Bean namens pageError erfasst:
||Property oder Methode||Bedeutung
|exception|Hier ist die aufgetretene Instanz von java.lang.Throwable enthalten. Dadurch können genauere Informationen über den Fehler angezeigt werden.
|viewId|Hier ist die View-Id gespeichert, bei Bedarf kann diese ebenfalls angezeigt werden.
|init()|Diese Methode kann vor dem Aufbau der Error-Page aufgerufen werden und check ob ein Fehler vorliegt.
|back()|Navigiert zurück auf die Seite auf der der Fehler aufgetreten war, damit der Benutzer weiter arbeiten kann.
!!!Downloads
* [JSF Ext CDI Package|JSF Ext/jsf-ext-cdi.zip]