Optionsfeld im Einsatz
 
  MyGourmet 9: showCustomer.xhtmlim Browser
 
  MyGourmet 9: editAddress.xhtmlim Browser
 
  MyGourmet 9: Adressdaten in showCustomer.xhtml
 
  MyGourmet 9: Adressdaten in Customer
 
  MyGourmet 9: Action-Methode zum Löschen einer Adresse
 
  MyGourmet 8: Auszug der Klasse CustomerBean
 
  MyGourmet 8: Ansicht im Browser
 
  Menüfeld im Einsatz
 
  Managed-Bean für Dateiupload
 
  Listenfeld im Einsatz
 
  HTML-Code zur Panel-Grid-Komponente h:panelGrid
 
  HTML-Code der UISelectItem- und UISelectItems-Komponente mit Gruppierung
 
  HTML-Code der UISelectItem- und UISelectItems-Komponente
 
  HTML-Ausgabe des Menüfelds
 
  HTML-Ausgabe des Listenfelds
 
  HTML-Ausgabe des Auswahlfelds
 
  h:outputLink mit externem Link
 
  h:outputLabel im Einsatz
 
  h:outputFormat in MyGourmet
 
  h:message im Einsatz
 
  h:link im Einsatz
 
  h:inputTextarea
 
  h:inputText im Einsatz
 
  h:inputSecret
 
  h:inputHidden
 
  h:inputFile mit h:form
 
  Gerenderte h:dataTable mit Facets
 
  Gerenderte h:dataTable
 
  Gerenderte Ausgabe von h:outputText
 
  Gerenderte Ausgabe von h:dataTable
 
  Gerenderte Ausgabe von h:dataTable
 
  f:selectItems mit Attribut var
 
  f:selectItems im Einsatz
 
  f:selectItem im Einsatz
 
  Eigenschaft persons für h:dataTable
 
  Eigenschaft gender
 
  Eigenschaft einer Bean für ein Auswahlfeld
 
  Die Panel-Grid-Komponente h:panelGrid
 
  Datenfluss bei f:selectItems mit Attribut var
 
  Beispiele von h:outputText
 
  Beispiel für h:form
 
  Beispiel für h:dataTable mit Facets
 
  Beispiel für h:dataTable
 
  Beispiel für f:resetValues
 
  Bean-Eigenschaft für ein Auswahlfeld
 
  Auszug aus Managed-Bean für Objektgruppen
 
  Auszug aus Managed-Bean für UISelectItems
 
  Auswahlfeld im Einsatz
 
  Auswahlfeld im Einsatz

3 Standard-JSF-Komponenten

JSF bietet eine gute Auswahl an vordefinierten Komponenten an, die viel Funktionalität zum Erstellen von Benutzeroberflächen mitbringen. Für die meisten Anwendungsfälle beherrschen diese Standardkomponenten das gewünschte Verhalten, angefangen von einfachen Eingabeschaltflächen über Textfelder bis hin zur Darstellung von Daten in Tabellenform.
Alle JSF-UI-Komponentenklassen im Standard erweitern die Klasse javax.faces.component.UIComponentBase , die das grundlegende Verhalten einer UI-Komponente definiert.
Das Einbinden einer JSF-Komponente in eine Seitendeklaration erfolgt in Facelets und JSP über ihr Tag . Die Tags für die Standard-JSF-Komponenten und ihre Darstellung als HTML-Ausgabe befinden sich in der HTML-Custom-Tag-Library . In der Core-Tag-Library finden sich weitere Tags, die Basisaktionen unabhängig von einem speziellen Render-Kit bereitstellen. JSF 2.2: In JSF 2.2 haben alle Tag-Bibliotheken neue Namensräume erhalten, die mit http://xmlns.jcp.org anstatt http://java.sun.com beginnen, wie Tabelle tab:standard-taglibs zeigt. JSF 2.2 unterstützt sowohl die neuen als auch die alten Namensräume. Für eine optimale Zukunftssicherheit empfehlen wir allerdings, auf die neuen Namensräume umzustellen. Zusätzlich sind in der Tabelle die Präfixe dargestellt, mit denen die Namensräume üblicherweise in die Seitendeklaration eingebunden werden.
NameNamensraumPräfix
HTML-Custom-Tag-Library http://xmlns.jcp.org/jsf/html (ab 2.2) h
http://java.sun.com/jsf/html (vor 2.2) h
Core-Tag-Library http://xmlns.jcp.org/jsf/core (ab 2.2) f
http://java.sun.com/jsf/core (vor 2.2) f
Wie die Einbindung der Tag-Bibliotheken in Facelets- und JSP-basierten Seiten aussieht, haben wir bereits in Abschnitt Sektion:  Seitendeklarationssprachen im Einsatz geklärt.
Hierarchischer Aufbau - Kindkomponenten: Um Komponenten ineinander zu verschachteln und damit einen Komponentenbaum aufzubauen, werden die Kindkomponenten in einer Seitendeklaration direkt in die Elternkomponenten eingefügt. Jede Komponente verwaltet für den Zugriff auf diese Kindkomponenten eine Liste.
Hierarchischer Aufbau - Facets: Wenn eine Kindkomponente eine spezielle Rolle für die Elternkomponente übernehmen soll, können - alternativ zur direkten Einbettung als Kindelement - sogenannte Facets verwendet werden. Damit kann eine spezielle Art oder ein spezielles Verhalten von Kindelementen definiert werden - beispielsweise werden so eine Kopf- oder Fußzeile in eine Tabelle eingebunden. Dieser Effekt wird mit dem f:facet -Tag erreicht Wird in JSF-Versionen vor 2.0 eine zweite Komponente ins Facet übernommen, wird diese zweite Komponente nicht angezeigt - ein Stolperstein für viele JSF-Anwender.: . Facets werden über ihren Namen identifiziert, daher werden sie in Form einer Map in der Elternkomponente gespeichert.
AttributTypBeschreibung
id String Eindeutiger Bezeichner der Komponente; falls id nicht angegeben ist, wird ein Bezeichner generiert.
immediate boolean Ist diese Eigenschaft true gesetzt, werden Eingabe- und Befehlskomponenten schon in Phase 2 des Lebenszyklus abgearbeitet.
value Object Der Wert der Komponente direkt als Text oder als Value-Expression
rendered boolean Bestimmt die Sichtbarkeit der Komponente
converter Converter Bestimmt den Konverter für die Darstellung
validator Method-Expression Referenziert eine Validierungsmethode
styleClass String CSS-Klassennamen der Komponente (durch Leerzeichen getrennt)
style String CSS-Eigenschaften für gerendertes HTML-Element
label String Beschreibung für Fehlermeldungen bei Eingabekomponenten (JSF 1.2)
binding String Bindet die Instanz der Komponente an eine Eigenschaft einer Backing-Bean
Diesen Zusammenhang zeigen die Codebeispiele in Abschnitt [Sektion:  MyGourmet 9: UIData und Detailansicht] , die eine Tabelle mit über Facets eingebundene Kopf- und Fußzeilen beschreiben. Die Spalten der Tabelle sind als Kindelemente ausgeführt.
Komponentenattribute: Über die Attribute einer Komponente wird ihr Verhalten angepasst. Attribute wie zum Beispiel id oder value kommen in den meisten Standardkomponenten vor. Tabelle fig:component-common-props beschreibt die gebräuchlichsten dieser Attribute. Alle diese Attribute (außer id und var ) können eine Value-Expression enthalten und dynamisch auf Werte in den Backing-Beans zugreifen.
Beispiele zu Standard-JSF-Komponenten: Die folgenden Beispiele zur HTML-Custom-Tag-Library bauen auf MyGourmet auf. Aus Gründen der Übersichtlichkeit werden in den einzelnen Abschnitten nur die für die gerade beschriebene Komponente relevanten Änderungen und Erweiterungen abgebildet. Das Beispiel MyGourmet 8 in Abschnitt [Sektion:  MyGourmet 8: Standardkomponenten] fasst alle Änderungen zu den Standard-JSF-Komponenten nochmals zusammen. Der Komponente UIData wird mit MyGourmet 9 in Abschnitt [Sektion:  MyGourmet 9: UIData und Detailansicht] ein eigenes Beispiel gewidmet.

3.1 Basisfunktionen der Core-Tag-Library

Die Tags in der Core-Tag-Library sind für die Basisfunktionalität unabhängig von speziellen Renderern zuständig; die Funktionalität wird meist rein von den Tags (eventuell zusammen mit Frameworkklassen von JSF) zur Verfügung gestellt, es werden keine eigenen Komponenten angelegt, sondern Attribute bestehender Komponenten gesetzt oder verändert. Die folgende Aufzählung listet die wichtigsten JSF-Core-Tags in alphabetischer Reihenfolge auf. Die Beschreibungen der einzelnen Tags sind bewusst kurz gehalten, da viele von ihnen nur in Kombination mit anderen Tags verwendet werden.

3.1.1 Komponenten mit f:resetValues zurücksetzen

JSF 2.2: Mit dem Tag f:resetValues lässt sich ab JSF 2.2 ein bereits länger bekanntes Problem elegant lösen. In einigen Fällen kann JSF den Wert von Eingabekomponenten nur dann aktualisieren, wenn dieser zuvor explizit zurückgesetzt wurde. f:resetValues fügt einen Action-Listener zu Befehlskomponenten hinzu, der alle Eingabekomponenten zurücksetzt, deren Client-IDs im Attribut render angegeben sind. Achten Sie darauf, in render die komplette Client-ID der Komponenten zu verwenden.
Listing Beispiel für f:resetValues zeigt ein Beispiel für f:resetValues . Die Action-Methode reset setzt den Wert der Eigenschaft value1 auf 0 zurück.
<h:form id="form">
  <h:inputText id="v1" value="#{bean.value1}">
    <f:validateLongRange minimum="10"/>
  </h:inputText>
  <h:commandButton value="Save"/>
  <h:commandButton value="Reset" action="#{bean.reset}"
      immediate="true">
    <f:resetValues render="form:v1"/>
  </h:commandButton>
</h:form>
Dieses Beispiel funktioniert auch ohne f:resetValues , aber nur so lange, bis der Benutzer die Schaltfläche zum Speichern mit einem ungültigen Wert für das Eingabefeld betätigt. In diesem Fall bleibt der Local-Value der Komponente gesetzt und der in der Action-Methode aktualisierte Wert wird nicht angezeigt. Mit f:resetValues wird sichergestellt, dass der Local-Value gelöscht wird, bevor JSF die Action-Methode ausführt. In Abschnitt Sektion:  Eingabefelder zurücksetzen wird dieses Problem für Ajax-Anfragen noch etwas genauer analysiert.

3.2 Formularkomponente

Die Komponente UIForm mit dem Tag h:form ist analog zum form -Element in HTML zu verstehen und muss alle Eingabe- und Befehlskomponenten umschließen, die Daten an die Applikation zurückgeben und Aktionen auslösen.
Die Komponente selbst wird als form -Element gerendert und im Browser nicht dargestellt. Eine Seite kann durchaus mehrere UIForm -Komponenten enthalten. Listing Beispiel für h:form zeigt noch einmal das Formular aus MyGourmet 1 zur Demonstration.
<h:form id="form">
  <h:panelGrid id="grid" columns="2">
    <h:outputLabel value="First Name:" for="firstName"/>
    <h:inputText id="firstName"
      value="#{customer.firstName}"/>
    <h:outputLabel value="Last Name:" for="lastName"/>
    <h:inputText id="lastName"
      value="#{customer.lastName}"/>
    <h:commandButton id="save" value="Save"
        action="#{customer.save}"/>
  </h:panelGrid>
</h:form>
Hyperlinks: Im Unterschied zum HTML-Standard ist eine UIForm auch für die Ausführung von Hyperlinks notwendig, die mit h:commandLink in die Ansicht eingefügt werden. Da Command-Link-Komponenten beim Aktivieren ein Formular absenden, funktionieren sie ohne umschließende UIForm nicht. Die Link-Tags h:outputLink und h:link funktionieren auch außerhalb einer UIForm ohne Probleme.

3.3 Befehlskomponenten

UICommand ist von der Klasse UIComponentBase abgeleitet und stellt in der HTML-Seite ein Befehlselement dar. Wird dieses Befehlselement vom Benutzer im Browser aktiviert, wird eine applikationsspezifische Aktion ausgelöst. Das Befehlselement kann beispielsweise als Schaltfläche h:commandButton , Menüpunkt oder Hyperlink h:commandLink dargestellt werden. Hier als Codebeispiel die Button-Komponente aus unserem Beispiel:
<h:commandButton action="#{customerBean.save}" value="Save"/>
Als Beispiel für eine Command-Link-Komponente fügen wir der Ansicht showCustomer.xhtml in MyGourmet einen Link zur Seite editCustomer.xhtml hinzu:
<h:commandLink action="/editCustomer.xhtml"
    value="Edit Customer" />
Damit der Link funktioniert, muss er in eine UIForm eingebettet sein. Hier ein weiteres Beispiel für eine Command-Link-Komponente, die das Attribut rendered benutzt:
<h:commandLink id="check" rendered="{cart.numberOfItems > 0}">
  <h:outputText value="#{managedBean.action}"/>
</h:commandLink>
rendered-Attribut: In diesem Beispiel wird der Command-Link check nicht dargestellt, wenn sich im Einkaufswagen keine Waren befinden, oder genauer, wenn die Eigenschaft numberOfItems der Managed-Bean cart den Wert 0 hat.

3.4 DataTable-Komponente

Die UIData -Komponente mit dem Tag h:dataTable iteriert über Elemente in einer Sammlung von Datenobjekten und erzeugt eine Tabelle in der HTML-Ausgabe. Jedes Element der referenzierten Sammlung wird in der gerenderten Ausgabe zu einer Tabellenzeile mit einer fixen Anzahl von Spalten. Die Spalten selbst und deren Inhalt werden in Form von verschachtelten UIColumn -Komponenten mit dem Tag h:column zur UIData -Komponente hinzugefügt.
In Listing Beispiel für h:dataTable finden Sie ein erstes Beispiel für h:dataTable und h:column , in dem eine Liste von Personen in Form einer Tabelle mit zwei Spalten ausgegeben wird.
<h:dataTable value="#{myBean.persons}" var="person">
  <h:column>
    <h:outputText value="#{person.name}"/>
  </h:column>
  <h:column>
    <h:outputText value="#{person.email}"/>
  </h:column>
</h:dataTable>
Die Liste der Personen wird mittels einer Value-Expression im Attribut value von h:dataTable referenziert. Sie stammt aus der Eigenschaft persons der Managed-Bean myBean und beinhaltet Instanzen der Klasse Person mit den Eigenschaften name und email . Listing Eigenschaft persons für h:dataTable zeigt den entsprechenden Code.
private List<Person> persons;
public List<Person> getPersons() {
  return persons;
}
JSF 2.2: JSF unterstützt nur eine begrenzte Menge von Typen im value -Attribut von h:dataTable . Vor JSF 2.2 waren das im Wesentlichen Arrays, java.util.List und der JSF-Typ javax.faces.model.DataModel . Ab JSF 2.2 kann h:dataTable mit allen von java.util.Collection abgeleiteten Typen umgehen. So war es zum Beispiel bis Version 2.2 nicht möglich, direkt mit java.util.Set zu arbeiten.
Beim Rendering (wie auch in allen anderen Phasen des Lebenslaufs) geht jetzt die UIData -Komponente die gebundene Liste Element für Element durch und stellt das aktuelle Element unter dem im var -Attribut definierten Namen zur Verfügung. Pro Element wird dadurch exakt eine Zeile ausgegeben, deren Inhalt von den mit h:column eingefügten UIColumn -Komponenten definiert ist. In unserem Beispiel aus Listing Beispiel für h:dataTable greifen wir zum Beispiel mit dem Namen person auf die aktuelle Person zu. Für jede Person wird in der ersten Spalte die Eigenschaft name und in der zweiten Spalte die Eigenschaft email ausgegeben. Die daraus gerenderte Darstellung in HTML sehen Sie in Listing Gerenderte h:dataTable .
<table>
  <tbody>
    <tr>
      <td>Anna Muster</td>
      <td>anna@muster.at</td>
    </tr>
    <tr>
      <td>Max Muster</td>
      <td>max@muster.at</td>
    </tr>
  </tbody>
</table>
Abbildung Gerenderte Ausgabe von h:dataTable zeigt, wie die gerenderte Ausgabe der Tabelle im Browser aussieht.
Abbildung:Gerenderte Ausgabe von h:dataTable
Stamping: Auch wenn die an die Komponente gebundene Liste Tausende Einträge hat, wird für jede Spalte nur eine Komponenteninstanz in den Komponentenbaum eingefügt. Beim Bearbeiten der Komponente während des Lebenszyklus - wie etwa beim Rendern - benutzt JSF diese Instanzen für sämtliche Zeilen mit dem jeweils aktuellen Wert. Diese Vorgehensweise nennt sich Stamping und soll einen minimalen Speicherverbrauch garantieren.
Das komplette Beispiel zur UIData -Komponente ist nicht in MyGourmet 8 , sondern in MyGourmet 9 in Abschnitt [Sektion:  MyGourmet 9: UIData und Detailansicht] zu finden. Dort wird dann zusätzlich die Umschaltung zwischen Listen- und Detailansicht und das Löschen und Editieren von einzelnen Adressen aus der Liste erläutert.

3.4.1 Erweiterte Konzepte von h:dataTable

Mit Facets kann die UIData -Komponente und jede ihrer Spalten mit einer Kopf- und Fußzeile versehen werden. Dazu wird ein Facet mit einem definierten Namen - header für Kopfzeilen und footer für Fußzeilen - als Kindelement der jeweiligen Komponente hinzugefügt. Im Beispiel erweitern wir die Personentabelle um Überschriften für die Tabelle selbst und für alle ihre Spalten. Mit Facets eine einfache Übung, wie Listing Beispiel für h:dataTable mit Facets zeigt.
<h:dataTable value="#{myBean.persons}" var="person">
  <f:facet name="header">Personen</f:facet>
  <h:column>
    <f:facet name="header">
      <h:outputText value="Name"/>
    </f:facet>
    <h:outputText value="#{person.name}"/>
  </h:column>
  <h:column>
    <f:facet name="header">
      <h:outputText value="E-Mail"/>
    </f:facet>
    <h:outputText value="#{person.email}"/>
  </h:column>
</h:dataTable>
Sehen wir uns noch einmal den gerenderten HTML-Code an. Alle Überschriften werden als th -Elemente im neu hinzugekommenen Abschnitt thead der Tabelle ausgegeben. Überschriften und Fußzeilen der Tabelle erstrecken sich immer über die gesamte Breite, was in der Ausgabe am gesetzten colspan -Attribut zu erkennen ist. Für die Spalten gibt es jeweils ein eigenes th -Element. Ansonsten hat sich nichts geändert - wie Listing Gerenderte h:dataTable mit Facets zeigt.
<table>
  <thead>
    <tr>
      <th colspan="2" scope="colgroup">Personen</th>
    </tr>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">E-Mail</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Anna Muster</td>
      <td>anna@muster.at</td>
    </tr>
    <tr>
      <td>Max Muster</td>
      <td>max@muster.at</td>
    </tr>
  </tbody>
</table>
Pagination: Die UIData -Komponente unterstützt prinzipiell das Anzeigen eines Ausschnitts einer Datensammlung. Dazu gibt es die Attribute first und rows . Die Darstellung erfolgt dann ab der Zeile, die im first -Attribut angegeben ist. Mit dem rows -Attribut wird die Zeilenanzahl spezifiziert. Ein Beispiel: Um die Zeilen 2 bis 10 einer Tabelle darzustellen, wird first auf 2 und rows auf 9 gesetzt. Der Standardwert dieser beiden Attribute ist null , was der Anzeige aller Zeilen entspricht.
Der Praxiswert der Attribute first und rows ist initial allerdings eher gering, da im JSF-Standard eine Paginator-Komponente fehlt. Für die seitenweise Darstellung von Daten müssen Sie daher auf eine Komponentenbibliothek wie PrimeFaces zurückgreifen (Abschnitt Sektion:  Auswahl einiger PrimeFaces-Komponenten zeigt den Einsatz von p:dataTable ) oder eine eigene Komponente schreiben.

3.4.2 Styling von h:dataTable

Zugegeben, die gerenderte Ausgabe in Abbildung Gerenderte Ausgabe von h:dataTable sieht trotz Kopf- und Fußzeile in der gegenwärtigen Form immer noch etwas eintönig aus. Die DataTable -Komponente bietet diverse Attribute, um die Tabelle mit CSS zu gestalten. Neben dem Attribut styleClass , das eine für die Darstellung der ganzen Tabelle gültige CSS-Klasse referenziert, gibt es noch einige optionale Attribute für die Einbindung von CSS-Klassen für andere Bereiche der Komponente:
Mit Werten für styleClass und headerClass könnte die gerenderte Ausgabe der Tabelle im Browser dann wie in Abbildung Gerenderte Ausgabe von h:dataTable aussehen.
Abbildung:Gerenderte Ausgabe von h:dataTable

3.5 Ausgabekomponenten

In diesem Abschnitt konzentrieren wir uns auf Komponenten zur Ausgabe von Informationen. Dazu zeigt Abschnitt [Sektion:  Textausgabekomponenten] zuerst Komponenten zur Ausgabe textbasierter Inhalte. Abschnitt [Sektion:  Bildausgabekomponente] präsentiert anschließend Details zur Ausgabe von Bildern.

3.5.1 Textausgabekomponenten

Die Komponente UIOutput dient zur Darstellung von Ausgabetext auf einer Seite. Der Wert dieser Komponente kann an ein Modellobjekt gebunden sein und kann durch den Benutzer nicht verändert werden. Die HTML-Tag-Library des JSF-Standards enthält für die einfache Ausgabe von Text folgende Tags:

3.5.1.1 Tag zur Textausgabe h:outputText

Mit h:outputText wird der im Attribut value festgelegte Wert in der HTML-Ausgabe angezeigt. Der Text wird ohne Formatierung dargestellt, außer es werden mit den Attributen style oder styleClass CSS-Stilangaben bzw. CSS-Klassen referenziert, die die Formatierung beeinflussen Normalerweise wird der Text der UIOutput-Komponente direkt gerendert - ohne spezielle HTML-Auszeichnung. Werden HTML-Attribute wie id, styleClass oder style gesetzt, wird der Text in der Ausgabe automatisch von einem <span/>-Element umgeben.: .
escape-Attribut: HTML- oder XML-Formatierungen im Wert gehen bei der Ausgabe verloren; alle Sonderzeichen in Texten werden durch ihre HTML-Entities ersetzt (also beispielsweise \verb|>| durch \verb|>|). Um die direkte Ausgabe von HTML- oder XML-Tags zu erlauben, kann das Attribut escape auf false gesetzt werden. Listing Beispiele von h:outputText zeigt drei Beispiele.
<h:outputText escape="true"
  value="Hallo liebe <em>Leser</em>"/>
<h:outputText escape="false"
  value="Hallo liebe <em>Leser</em>"/>
<h:outputText escape="false"
  value="<script>alert('Böse')</script>"/>
Die Texte im ersten und im zweiten Tag sind identisch. Die Tags unterscheiden sich nur durch das Attribut escape , das einmal auf true und einmal auf false gesetzt ist. Wie sich das in der Ausgabe auswirkt, sehen Sie in Abbildung Gerenderte Ausgabe von h:outputText .
Abbildung:Gerenderte Ausgabe von h:outputText
Wenn Sie escape auf false setzen, sollten Sie allerdings immer im Hinterkopf behalten, dass Sie sich damit eine potenzielle Sicherheitslücke einhandeln - besonders wenn vom Benutzer editierbare Daten direkt ausgegeben werden. Abbildung Gerenderte Ausgabe von h:outputText zeigt, wie ein Anwender ausführbaren Code in den Text schmuggeln kann. Damit werden dann Cross-Site-Scripting-Angriffe möglich.

3.5.1.2 Labelausgabe-Komponente h:outputLabel

Die h:outputLabel -Komponente (HTML-Element label ) ermöglicht es, Bezeichnungen mit Eingabefeldern zu verbinden. Die für die Ausgabe der Bezeichnung notwendigen Komponenten werden dazu in das h:outputLabel -Tag geschachtelt. Die Komponente selbst stellt keinen Text dar. Das Attribut for muss gesetzt sein und auf das Attribut id des Eingabefelds zeigen.
Listing h:outputLabel im Einsatz zeigt in zwei Varianten, wie h:outputLabel eingesetzt werden kann. In der ersten Variante gibt das h:outputText -Tag mit seinem value -Attribut den Text an, der als Label beim Eingabefeld für den Vornamen angezeigt wird. Wie Sie in der zweiten Variante sehen, kann das Label für das Eingabefeld auch im Attribut value des h:outputLabel -Tags selbst spezifiziert werden. Diese Variante ist einfacher, aber auch weniger flexibel - was uns allerdings nicht davon abgehalten hat, diesen Ansatz in MyGourmet zu wählen.
<h:outputLabel for="firstName">
  <h:outputText value="First Name:"/>
</h:outputLabel>
<h:inputText id="firstName" required="true"
    value="#{customerBean.customer.firstName}"/>
<h:outputLabel for="lastName" value="Last Name:"/>
<h:inputText id="lastName" required="true"
    value="#{customerBean.customer.lastName}"/>

3.5.1.3 Linkkomponente h:outputLink

Mit dem h:outputLink -Tag wird ein Hyperlink zu einer externen URL erzeugt. Die URL, die bei einem Klick des Benutzers auf den Link geladen wird, wird im Attribut value definiert. Es wird kein Action-Event ausgelöst, und der von JSF beim Rendern der aktuellen Ansicht gespeicherte Zustand des Komponentenbaums geht verloren.
Um den angezeigten Text und das Aussehen des Links festzulegen, kann jede beliebige Ausgabekomponente in das h:outputLink -Tag verschachtelt werden. Für einfachen Text reicht die h:outputText -Komponente oder verschachtelte HTML-Elemente, für eine grafische Darstellung des Links kann die h:graphicImage -Komponente verwendet werden. Durch die Verschachtelung von f:param -Tags können Parameter der URL festgelegt werden - sowohl statisch als auch dynamisch über einen Unified-EL -Ausdruck.
Listing h:outputLink mit externem Link zeigt eine h:outputLink -Komponente mit einem externen Link und Parametern im Einsatz.
<h:outputLink value="http://wiki.apache.org/myfaces/">
  <h:outputText value="MyFaces Wiki"/>
  <f:param name="action" value="info"/>
</h:outputLink>
Hier die gerenderte HTML-Ausgabe des Beispiels aus Listing h:outputLink mit externem Link :
<a href="http://wiki.apache.org/myfaces/?action=info">
MyFaces Wiki</a>
Eine weitverbreitete Kritik an JSF ist, dass GET-Anfragen nicht in vollem Umfang unterstützt werden. Das ist so nicht richtig. Ab JSF 2.0 gibt es mit View-Parametern und ab JSF 2.2 zusätzlich mit View-Actions eine umfassende Unterstützung für GET-Anfragen. Weiterführende Details finden Sie in Abschnitt Sektion:  Bookmarks und GET-Anfragen in JSF .

3.5.1.4 Parametrisierbares Textausgabefeld h:outputFormat

Das Tag h:outputFormat wird genauso wie das h:outputText -Tag zur Ausgabe von Text verwendet. Zusätzlich ist es möglich, entweder statisch vorgegebene oder über Unified-EL -Ausdrücke dynamisch eingebundene Werte in den ausgegebenen Text einzuflechten. Konkret kann damit beispielsweise in eine Textschablone der Benutzername oder ein Datum eingebunden werden.
Message-Format: Die Ausgabe von Text mit dynamisch eingebundenen Variablen kann durch die Verwendung von Message-Format-Vorlagen mit Platzhaltern noch weiter vereinfacht werden. Ein Platzhalter ist eine Zahl innerhalb von geschwungenen Klammern, die auf den Index eines f:param -Kindelements verweist. Die Nummerierung der Parameter beginnt (für Java typisch) mit der Zahl 0. Der Platzhalter {0} wird also durch den Wert des ersten in h:outputFormat eingebetteten Parameters f:param ersetzt, {1} durch den Wert des zweiten Parameters und so weiter. Als Beispiel wird die Meldung am Ende der Ansicht showCustomer.xhtml wie in Listing h:outputFormat in MyGourmet gezeigt erweitert.
<h:outputFormat value="{0}, your profile is {1}.">
  <f:param value="#{customerBean.customer.firstName}"/>
  <f:param value="active"/>
</h:outputFormat>
Für den Platzhalter {0} wird das Ergebnis des Ausdrucks customer-Bean.customer.firstName und für {1} der Wert des zweiten Parameters, nämlich " active", eingesetzt. Die Gesamtausgabe ist daher:
Martin, your profile is active.
Wird auch noch für verschiedene Sprachen die Vorlagenzeichenkette dynamisch eingebunden, können Parameter an jeweils anderen Stellen ausgegeben werden - das ist für die Internationalisierung wichtig, wie bereits Abschnitt Sektion:  Internationalisierung gezeigt hat.

3.5.2 Bildausgabekomponente

Die Komponente UIGraphic mit dem Tag h:graphicImage zeigt dem Benutzer eine nicht manipulierbare Grafik an. Das Attribut url gibt den Pfad zur Grafik in Form einer statischen Zeichenkette oder einer Value-Expression an.
Relative vs. absolute Adressierung: Ist an den Beginn des Pfads ein Schrägstrich ( / ) gesetzt, wird der Pfad als absolute Angabe innerhalb der Webapplikation verstanden, sonst wird der Pfad relativ aufgefasst. In Webanwendungen ist generell eine absolute Adressierung zu empfehlen, weil dann die Seitenstruktur beliebig verändert werden kann, ohne dass Rücksicht auf die eingebundenen Grafiken und anderen Ressourcen genommen werden muss.
Ein h:graphicImage -Tag wird in der HTML-Ausgabe als img -Tag gerendert. Wenn der im url -Attribut der Komponente übergebene Pfad mit einem Schrägstrich ( / ) beginnt, wird beim Rendern des src -Attributs der Kontextpfad der Applikation vorangestellt.
alt-Attribut: Das Attribut alt spezifiziert den Text, der alternativ zur Bilddarstellung angezeigt werden soll Der Internet Explorer zeigt den ALT-Text dann an, wenn die Maus über das Bild bewegt wird.: . Im folgenden Beispiel referenziert das Attribut alt auf einen lokalisierten Text (Details zur Lokalisierung finden Sie in Abschnitt Sektion:  Internationalisierung ).
<h:graphicImage id="Grafik" url="/images/Grafik.jpg"
    alt="#{bundle.chooseLocale}" title="Grafikanzeige"
    width="149" height="160"/>
Ab JSF 2.0 können Bilder auch in Form von Ressourcen eingebunden werden. Statt des Pfads zur Bilddatei geben Sie dafür den Namen der Ressource im neuen Attribut name des Tags h:graphicImage an. Details zum Umgang mit Ressourcen ab JSF 2.0 erfahren Sie in Kapitel Kapitel:  Verwaltung von Ressourcen .

3.6 Eingabekomponenten

Die Komponente UIInput ist eine Subklasse der Klasse UIOutput . Sie übernimmt Eingabedaten des Benutzers, wie beispielsweise einen Text aus einem Texteingabefeld, Passwörter aus einem Passworteingabefeld oder - neu in JSF 2.2 - Dateien aus einem Dateiuploadfeld. Tabelle tab:input-comps zeigt die Tags der von UIInput abgeleiteten Eingabekomponenten mit Beispielen (bis auf h:inputHidden ).
StandardtagBeispiel
h:inputText
h:inputSecret
h:inputTextarea
h:inputFile
Um die Eingaben dieser Komponenten zu konvertieren, zu validieren und um dann Ereignisse zu erkennen und zu behandeln, können folgende Tags aus der Core-Tag-Library verwendet werden: f:converter (siehe Abschnitt Sektion:  Konvertierung ), f:validator (siehe Abschnitt Sektion:  Validierung ) und f:valueChangeListener (siehe Abschnitt Sektion:  Value-Change-Events ). Eingabekomponenten werden häufig mit Labelausgabe-Komponenten verbunden, um in der HTML-Ausgabe ein label -Element zu generieren. Details dazu finden Sie in Abschnitt [Sektion:  Textausgabekomponenten] .

3.6.1 Texteingabefeld h:inputText

Diese Komponente ermöglicht es, ein Texteingabefeld zu erzeugen. In Listing h:inputText im Einsatz sehen Sie nochmals das Eingabefeld für den Vornamen in MyGourmet .
<h:inputText id="firstName"
  value="#{customerBean.customer.firstName}"
  size="30" maxlength="40" required="true"/>
Über eine Value-Expression ist das Eingabefeld des Beispiels mit der Eigenschaft firstName des Objekts customerBean.customer verbunden. Beim Rendern der Ansicht wird der Wert aus der Bean im Eingabefeld angezeigt - er kann vom Benutzer geändert werden. Nach einem Übermitteln des Formulars wird der neue Wert automatisch in die Eigenschaft der Bean zurückgeschrieben - vorausgesetzt die Konvertierung und Validierung waren erfolgreich.
Ist das Attribut required auf true gesetzt, wird ein Validierungsfehler erzeugt, wenn der Benutzer keinen Wert eingibt. Das size -Attribut legt die sichtbare Länge des Eingabefelds auf 30 Zeichen fest, und mit maxlength wird bestimmt, dass die Benutzereingabe maximal 40 Zeichen lang sein darf.

3.6.2 Passworteingabefeld h:inputSecret

Mit dem Tag h:inputSecret wird ein Passworteingabefeld mit verdeckter Eingabe erzeugt. In der gerenderten Ausgabe wird daraus das HTML-Tag <input type={"}password{"}> . Die Benutzereingabe in diesem Eingabefeld wird in Form von Punkten dargestellt. Durch das Setzen des Attributs redisplay auf false wird verhindert, dass beim erneuten Seitenaufbau das eingegebene Passwort im Quelltext der HTML-Seite angezeigt wird. Listing h:inputSecret zeigt die Komponente im Einsatz. Ansonsten funktioniert diese Komponente ähnlich wie h:inputText .
<h:inputSecret redisplay="false"
  value="#{loginBean.password}" />

3.6.3 Mehrzeiliges Texteingabefeld h:inputTextarea

Die Komponente h:inputTextarea wird ebenfalls wie die Komponente h:inputText verwendet. Sie erzeugt allerdings statt eines Feldes mit nur einer Zeile ein größeres, also mehrzeiliges Eingabefeld. Die Anzahl der Spalten und Zeilen wird über die Attribute rows und cols festgelegt. Ein Beispiel finden Sie in Listing h:inputTextarea .
<h:inputTextarea id="textArea" rows="4" cols="7"
  value="#{managedBean.textAreaData}" />

3.6.4 Verstecktes Eingabefeld h:inputHidden

Die h:inputHidden -Komponente ist für den Benutzer unsichtbar und wird verwendet, um Variablen (und damit einen Status) von Seite zu Seite zu transferieren, ohne dass der Status am Server gespeichert werden muss. Es gibt allerdings nur selten Anwendungsfälle, wo dieses Verhalten in JSF gewünscht ist. JSF verwaltet den Status der Seiten der Anwendung für uns, und für andere Daten wird üblicherweise die Benutzersitzung eingesetzt.
Nachdem diese Komponente für den Benutzer keine sichtbare Ausgabe darstellt, gibt es natürlich keine darstellungsspezifischen Attribute wie styleClass oder size . Listing h:inputHidden zeigt die Komponente im Einsatz.
<h:inputHidden id="hidden"
  value="#{managedBean.hiddenField}"/>

3.6.5 Dateiuploadfeld h:inputFile

JSF 2.2: Mit JSF 2.2 hat es endlich die Dateiuploadkomponente mit dem Tag h:inputFile in den Standard geschafft. Der Grund für diese doch sehr lange Verzögerung ist, dass erst mit Version 3.0 die Voraussetzungen für den Dateiupload in den Servlet-Standard aufgenommen wurden.
h:inputFile ermöglicht den Upload einer Datei in eine Bean-Eigenschaft vom Typ javax.servlet.http.Part . Diese Eigenschaft ist wie bei allen anderen Eingabekomponenten über eine Value-Expression im Attribut value mit der Komponente verbunden. Auch in allen anderen Belangen verhält sich h:inputFile wie jede andere Eingabekomponente in JSF.
Damit der Dateiupload richtig funktioniert, muss zwingend das Attribut enctype des umschließenden h:form -Tags auf den Wert multipart/form-data gesetzt werden. Nur so ist gewährleistet, dass die Daten korrekt zum Server übertragen werden. Listing h:inputFile mit h:form zeigt ein einfaches Beispiel zum Uploaden einer Datei beim Klick auf eine Schaltfläche.
<h:form id="form" enctype="multipart/form-data">
  <h:inputFile id="file" value="#{bean.file}"/>
  <h:commandButton value="Upload" action="#{bean.upload}"/>
</h:form>
Die im letzten Beispiel referenzierte Managed-Bean finden Sie in Listing Managed-Bean für Dateiupload . Bei einem Übermitteln (Submit) des Formulars speichert JSF die hochgeladene Datei in der Eigenschaft mit dem Namen file vom Typ javax.servlet.http.Part .
public class Bean {
  private Part file;
  private String fileContent;

  public void upload() {
    try {
      fileContent = new Scanner(file.getInputStream())
          .useDelimiter("
A").next();
    } catch (IOException e) {// Error handling}
  }

  public Part getFile() {
    return file;
  }

  public void setFile(Part file) {
    this.file = file;
  }
}
Über das Interface Part stehen alle wichtigen Informationen der Datei wie der Name, der Mime-Type, die Größe und natürlich der Inhalt zur Verfügung. In der Action-Methode upload wird der Dateiinhalt aus dem zur Verfügung gestellten Input-Stream gelesen und in das Feld vom Typ String geschrieben. Dort steht er dann zur weiteren Verwendung in der Managed-Bean bereit.
h:inputFile unterstützt wie jede andere Eingabekomponente das Hinzufügen von Validatoren, um die Gültigkeit der hochgeladenen Datei zu überprüfen:
<h:inputFile id="file" value="#{bean.file}"
    validator="#{bean.validateFile}"/>
In der referenzierten Validierungsmethode kann dann zum Beispiel die Größe der Datei überprüft werden:
public void validateFile(FacesContext ctx,
    UIComponent comp, Object value) {
  if (((Part)value).getSize() > 1024) {
    new ValidatorException(new FacesMessage("file too big"));
  }
}
Mit h:inputFile können Sie übrigens auch Dateien mittels Ajax hochladen. Die Handhabung unterscheidet sich dabei nicht von anderen Komponenten und funktioniert wie in Kapitel Kapitel:  Ajax und JSF beschrieben.

3.7 Auswahlkomponenten

In diesem Abschnitt zeigen wir Ihnen mehrere Komponenten zur Auswahl von Werten. Abschnitt [Sektion:  Boolesche Auswahl] beginnt mit der einfachsten Variante und zeigt die boolesche Auswahl. Anschließend geht es mit Komponenten zur Auswahl von Werten aus einer Liste weiter: Abschnitt [Sektion:  Einfache Auswahl] zeigt Komponenten zur Auswahl eines Wertes und Abschnitt [Sektion:  Mehrfache Auswahl] Komponenten zur Auswahl mehrerer Werte. Abschnitt [Sektion:  Definition der Auswahlmöglichkeiten] demonstriert abschließend, wie die Auswahlmöglichkeiten definiert werden.

3.7.1 Boolesche Auswahl

Mit der Auswahlkomponente UISelectBoolean , die unter dem Tag h:selectBooleanCheckbox verfügbar ist, kann ein boolescher Wert an eine Auswahlkomponente gebunden werden. UISelectBoolean ist eine Subklasse von UIInput und wird als HTML-Checkbox gerendert wie Tabelle fig:component-selectboolean zeigt.
Standard-TagBeispiel
h:selectBooleanCheckbox
In MyGourmet wird UISelectBoolean bereits für die Eigenschaft useCreditCard verwendet. Listing Auswahlfeld im Einsatz zeigt das entsprechende Tag.
<h:selectBooleanCheckbox id="useCreditCard"
    value="#{customerBean.customer.useCreditCard}"/>
Ein kleiner Tipp: Der Getter für einen boolean -Wert kann mit is beginnen, lautet also für unser Beispiel isUseCreditCard() . Für Auswahlfelder, die auf einen Boolean -Wert referenzieren (also nicht den primitiven Datentyp), ist der GettergetUseCreditCard() zu nennen. Der Code für die Eigenschaft useCreditCard ist in Listing Eigenschaft einer Bean für ein Auswahlfeld zu finden.
private Boolean useCreditCard = Boolean.FALSE;
public Boolean getUseCreditCard() {
  return useCreditCard;
}
public void setUseCreditCard(
    Boolean useCreditCard) {
  this.useCreditCard = useCreditCard;
}

3.7.2 Einfache Auswahl

Die UISelectOne -Komponente ermöglicht die Auswahl eines einzelnen Objekts aus einer Auswahlliste. Die Klasse UISelectOne ist ebenfalls eine Subklasse von UIInput . Für diese Komponente gibt es Standard-Tags für die Darstellung der Objekte als Optionsfeld ( h:selectOneRadio ), Listenfeld ( h:selectOneListbox ) oder Klappmenü ( h:selectOneMenu ). Beispiele, wie die Standard-Tags im Browser dargestellt werden, finden sich in Tabelle fig:component-selectone .
Standard-TagBeispiel
h:selectOneRadio
h:selectOneListbox
h:selectOneMenu
Mit dem value -Attribut der UISelectOne -Komponente wird der selektierte Wert über eine Value-Expression an die Eigenschaft einer Bean gebunden. Weist der gebundene Wert nicht den Datentyp String auf, muss ein passender Konverter ausgewählt werden.
Zur Demonstration von UISelectOne wird das Beispiel um die Eigenschaft gender erweitert. Listing Optionsfeld im Einsatz zeigt das Tag als Optionsfeld.
<h:selectOneRadio id="gender" required="true"
    value="#{customerBean.customer.gender}">
  <f:selectItem itemLabel="Female" itemValue="f"/>
  <f:selectItem itemLabel="Male" itemValue="m"/>
</h:selectOneRadio>
Hier wird durch das Setzen von required={"}true{"} das Auswählen einer der beiden Möglichkeiten erzwungen. In Listing Eigenschaft gender finden Sie die notwendigen Änderungen an der Klasse Customer .
private Character gender;
public Character getGender() {
  return gender;
}
public void setGender(Character gender) {
  this.gender = gender;
}

3.7.3 Mehrfache Auswahl

Nachdem wir schon wissen, was die UISelectOne -Komponente kann, ist die Funktionalität der Komponente UISelectMany nicht schwer zu erraten. Diese Komponente ermöglicht es dem Benutzer, keines, eines oder mehrere Objekte aus einer Auswahlliste zu selektieren. Die Klasse UISelectMany ist von der Klasse UIInput abgeleitet. Standard-Tags gibt es für die Darstellung als Auswahlfeld ( h:selectManyCheckbox ), Liste ( h:selectManyListbox ) oder Auswahlmenü ( h:selectManyMenu ) Einige Browser können mit der Darstellung als Auswahlmenü nicht vernünftig umgehen. Selbst wenn die Darstellung möglich ist, gestaltet sich die Benutzerinteraktion schwierig.: - die Darstellung erfolgt dabei gleich wie bei der UISelectOne -Komponente. Beispiele, wie die Standard-Tags im Browser dargestellt werden, finden sich in Tabelle fig:component-selectmany .
Standard-TagBeispiel
h:selectManyCheckbox
h:selectManyListbox
h:selectManyMenu
Pro Objekt oder Objektgruppe für die Auswahlliste wird im Tag der Komponente ein f:selectItem - oder f:selectItems -Tag verschachtelt (siehe Abschnitt [Sektion:  sec:comp-sel-items] ). Mit dem Attribut value werden die selektierten Werte über eine Value-Expression an eine Bean-Eigenschaft gebunden, deren Typ ein Array von primitiven Typen oder Objekten oder eine Liste von Strings ist. Handelt es sich um ein Array von einem anderen Typ als String , wird ein passender Konverter ausgewählt.

3.7.3.1 Auswahlfeld h:selectManyCheckbox

Mit dem h:selectManyCheckbox -Tag kann eine Gruppe von Auswahlfeldern ( Checkboxen ) erzeugt werden, wobei jede einen Wert darstellt, der vom Benutzer ausgewählt werden kann. Die Werte der Auswahlfelder werden durch verschachtelte f:selectItem - oder f:selectItems -Tags angegeben. Der Wert der Checkboxen kann über einen Unified-El -Ausdruck im Attribut value eingebunden werden.
Mit den Attributen enabledClass und disabledClass können CSS-Style-Klassen eingebunden werden, die das Layout der ausgewählten beziehungsweise der nicht ausgewählten Auswahlfelder und des zugehörigen Texts bestimmen. Über das Attribut layout kann die Anordnung der einzelnen Items beziehungsweise Auswahlfelder bestimmt werden: Mit dem Wert pageDirection werden die Auswahlfelder vertikal und mit lineDirection horizontal angeordnet. Wird das Attribut layout nicht angegeben, erfolgt die Darstellung horizontal.
Zur Demonstration wird die Klasse Customer in MyGourmet um die Eigenschaft preferredCategories erweitert. Der Benutzer kann damit bevorzugte Kategorien aus einer Liste von Werten auswählen. Das Tag für eine Auswahl als h:selectManyCheckbox mit zwei fixen Werten (horizontal angeordnete Checkboxen) finden Sie in Listing Auswahlfeld im Einsatz .
<h:selectManyCheckbox id="prefCat"
    value="#{customerBean.customer.preferredCategories}">
  <f:selectItem itemValue="IT" itemLabel="Italian"/>
  <f:selectItem itemValue="GR" itemLabel="Greek"/>
</h:selectManyCheckbox>
Die aus dem Tag in Listing Auswahlfeld im Einsatz gerenderte HTML-Ausgabe ist in Listing HTML-Ausgabe des Auswahlfelds zu sehen.
<table id="form:prefCat">
  <tr>
    <td>
      <input id="form:prefCat:0" type="checkbox"
          name="form:prefCat" value="IT"/>
      <label for="form:prefCat:0"> Italian</label>
    </td>
    <td>
      <input id="form:prefCat:1" type="checkbox"
          name="form:prefCat" value="GR"/>
      <label for="form:prefCat:1"> Greek</label>
    </td>
  </tr>
</table>
Die Klasse Customer erhält dazu die Eigenschaft preferredCategories . Das entsprechende Codefragment finden Sie in Listing Bean-Eigenschaft für ein Auswahlfeld .
private List<String> preferredCategories =
    new ArrayList<String>();
public List<String> getPreferredCategories() {
  return preferredCategories;
}
public void setPreferredCategories(
    List<String> preferredCategories) {
  this.preferredCategories = preferredCategories;
}

3.7.3.2 Listenfeld h:selectManyListbox

Bei sehr vielen Auswahlmöglichkeiten ist die Darstellung als Auswahlfeld unübersichtlich und ein Listenfeld, in dem die Elemente aufgelistet angezeigt werden, praktikabler. Listing Listenfeld im Einsatz zeigt, wie die Eigenschaft preferredCategories mit dem h:selectManyListbox -Tag verwendet wird.
<h:selectManyListbox id="prefCat"
    value="#{customerBean.customer.preferredCategories}">
  <f:selectItem itemValue="IT" itemLabel="Italian"/>
  <f:selectItem itemValue="GR" itemLabel="Greek"/>
</h:selectManyListbox>
Die aus dem Tag in Listing Listenfeld im Einsatz gerenderte HTML-Ausgabe zeigt Listing HTML-Ausgabe des Listenfelds .
<select id="form:prefCat" name="form:prefCat"
    multiple="multiple" size="2">
  <option value="IT">Italian</option>
  <option value="GR">Greek</option>
</select>

3.7.3.3 Menüfeld h:selectManyMenu

Im Unterschied zum Listenfeld wird in einem Menü immer nur ein Element zu einem Zeitpunkt angezeigt. Im Internet Explorer kann über eine Scrollbar zu den restlichen Elementen gescrollt werden, in Mozilla (und seinen Verwandten) wird jeweils nur ein Element angezeigt. Die Mehrfachauswahl ist auf jeden Fall für den Benutzer schwierig zu bewerkstelligen.
Das Beispiel mit den bevorzugten Kategorien als Menü finden Sie in Listing Menüfeld im Einsatz .
<h:selectManyMenu id="prefCat"
    value="#{customerBean.customer.preferredCategories}">
  <f:selectItem itemValue="IT" itemLabel="Italian"/>
  <f:selectItem itemValue="GR" itemLabel="Greek"/>
</h:selectManyMenu>
Der HTML-Code dazu ist in Listing HTML-Ausgabe des Menüfelds zu sehen.
<select id="form:prefCat" name="form:prefCat"
    multiple="multiple" size="1">
  <option value="IT">Italian</option>
  <option value="GR">Greek</option>
</select>

3.7.4 Definition der Auswahlmöglichkeiten

Die Liste der möglichen Werte einer Auswahlkomponente wird in JSF mit den Tags f:selectItem und f:selectItems definiert.

3.7.4.1 Einzelne Auswahlmöglichkeit mit f:selectItem

Das Tag f:selectItem erstellt ein einzelnes Auswahlobjekt und muss als Kind-Tag einer Auswahlkomponente angegeben werden. Im lokalisierbaren Attribut itemLabel wird die Kurzbeschreibung hinterlegt, die dem Benutzer für dieses Auswahlobjekt angezeigt wird. Das Attribut itemDescription gibt eine Beschreibung der Komponente an, die üblicherweise länger als itemLabel ist und durch die Standard-Renderer nicht dargestellt wird. In itemValue steht der serverseitige Wert dieses Objekts. Er muss denselben Datentyp wie der Wert der Elternkomponente aufweisen. Mit dem booleschen Attribut itemDisabled kann der Wert in der Auswahlliste der Komponente deaktiviert werden. Er wird dann im Browser ausgegraut dargestellt und kann nicht selektiert werden Der Internet Explorer interpretiert das Attribut disabled auf dem HTML-Element option erst ab Version 8.: .
Als Variante zur Verwendung dieser Attribute kann im Attribut value eine SelectItem -Instanz referenziert werden, die mit dieser Komponente in Verbindung steht. Wenn dieses Attribut gesetzt ist, werden itemLabel , itemValue und itemDescription nicht verwendet. Das Beispiel in Listing f:selectItem im Einsatz zeigt die Verwendung.
<f:selectItem itemValue="IT" itemLabel="Italian"/>
<f:selectItem itemValue="GR" itemLabel="Greek"
    itemDisabled="#{user.numberOfVisits < 5}"/>
<f:selectItem itemValue="AT" itemLabel="Austrian"/>
<f:selectItem value="#{customerBean.selectMexican}"/>
In diesem Beispiel wird itemDisabled durch einen Unified-El -Ausdruck bestimmt, dieser ist true , wenn der Benutzer die Seite weniger als 5 Mal besucht hat.

3.7.4.2 Mehrere Auswahlmöglichkeiten mit f:selectItems

Das Tag f:selectItems ermöglicht die Definition mehrerer Auswahlobjekte für eine Auswahlkomponente. Die Liste der Optionen wird im Attribut value als Unified-EL -Ausdruck spezifiziert. In JSF-Versionen vor 2.0 muss diese Value-Expression einen Wert vom Typ SelectItem , SelectItem[] , Collection (von SelectItem -Instanzen) oder Map zurückliefern. Bei einer Map wird der Schlüssel als itemLabel und der Wert als itemValue verwendet. Ab JSF 2.0 reicht eine Liste von POJOs (Plain Old Java Objects) - doch dazu etwas später mehr.
Sollen einzelne Werte zusätzlich zu einer dynamischen Auswahlliste angezeigt werden, ist die Verwendung zusammen mit f:selectItem möglich. Mit dieser Kombination kann zum Beispiel auch einer Liste von Werten ein leeres Element hinzugefügt werden. Listing f:selectItems im Einsatz zeigt als Beispiel die Auswahl der bevorzugten Kategorien in MyGourmet mit einer Kombination von f:selectItems - und f:selectItem -Tags.
<h:selectManyListbox id="prefCat" value=
    "#{customerBean.customer.preferredCategories}">
  <f:selectItems value="#{customerBean.categories}"/>
  <f:selectItem itemValue="CN" itemLabel="Chinese"/>
</h:selectManyListbox>
Ausschnitte aus der Managed-Bean für dieses Beispiel finden Sie in Listing Auszug aus Managed-Bean für UISelectItems .
public List<SelectItem> getCategories() {
  if (categories == null) {
    categories = new ArrayList<SelectItem>();
    categories.add(new SelectItem("IT", "Italian"));
    categories.add(new SelectItem("AT", "Austrian"));
  }
  return categories;
}
Listing HTML-Code der UISelectItem- und UISelectItems-Komponente zeigt den erzeugten HTML-Code.
<select id="form:prefCat" name="form:prefCat"
    multiple="multiple" size="5">
  <option value="IT">Italian</option>
  <option value="AT">Austrian</option>
  <option value="CN">Chinese</option>
</select>
JSF erlaubt ab Version 2.0 mit einer Reihe von neuen Attributen für f:selectItems das Generieren der Auswahlobjekte ähnlich der Iteration einer Data-Table über eine Liste. Das Erstellen von SelectItem -Instanzen in der Managed-Bean ist dann nicht mehr notwendig.
Wie bei h:dataTable definiert das Attribut var einen Namen, über den beim Iterieren das aktuelle Element verfügbar ist. Dieser Name kommt dann in den Attributen itemLabel und itemValue in Value-Expressions zum Einsatz, um den Wert und das Label einer einzelnen Option festzulegen.
Sehen wir uns ein kurzes Beispiel an. Listing f:selectItems mit Attribut var zeigt die modifizierten Tags zur Deklaration der Auswahlliste.
<h:selectManyListbox id="prefCat" size="5"
    value="#{customerBean.customer.preferredCategories}">
  <f:selectItems value="#{customerBean.categories}"
      var="cat" itemLabel="#{cat.name}" itemValue="#{cat.abbr}"/>
</h:selectManyListbox>
In Abbildung Datenfluss bei f:selectItems mit Attribut var sehen Sie, wie der dazugehörige Datenfluss aussieht. Die im Attribut value referenzierte Liste enthält fünf Beans vom Typ Category - mit den Eigenschaften name und abbr . Beim Durchlaufen der Liste wird die aktuelle Bean unter dem in var definierten Namen cat abgelegt. Daraus wird eine Instanz der Klasse SelectItem erstellt - mit cat.name als Label und cat.abbr als Wert. Diese Select-Items stellen dann die möglichen Optionen der Auswahlliste dar.
Abbildung:Datenfluss bei f:selectItems mit Attribut var
Objektgruppen: Bei der Verwendung von h:selectItems können einzelne Elemente der Liste auch gruppiert werden. Dazu bietet JSF die von SelectItem abgeleitete Klasse SelectItemGroup . Die Änderungen an der Managed-Bean, um Objektgruppen zu verwenden, sind marginal (Listing Auszug aus Managed-Bean für Objektgruppen ).
public List<SelectItem> getCategories() {
  if (categories == null) {
    categories = new ArrayList<SelectItem>();
    SelectItem[] euItems = {
      new SelectItem("IT", "Italian"),
      new SelectItem("AT", "Austrian")
    };
    SelectItemGroup euGroup = new SelectItemGroup(
        "Europe", null, true, euItems);
    categories.add(euGroup);
    categories.add(new SelectItem("MX", "Mexican"));
  }
  return categories;
}
Der zugehörige HTML-Code ist in Listing HTML-Code der UISelectItem- und UISelectItems-Komponente mit Gruppierung ersichtlich.
<select id="form:prefCat" name="form:prefCat"
    multiple="multiple" size="5">
  <optgroup label="Europe">
    <option value="IT">Italian</option>
    <option value="AT">Austrian</option>
  </optgroup>
  <option value="MX">Mexican</option>
</select>

3.8 Panel-Komponenten

Für die Gruppierung von Komponenten in einem Container wird die UIPanel -Komponente verwendet. Aktionen wie zum Beispiel das Ein- oder Ausblenden aller Komponenten können für die in einem Panel-Tag verschachtelten Komponenten zusammen ausgeführt werden.
Die HTML-Tag-Library stellt die Tags h:panelGrid zur Erzeugung einer Tabelle mit anpassbarer Kopf- und Fußzeile und h:panelGroup zum einfachen Gruppieren von Elementen zur Verfügung.
Mit h:panelGroup gruppierte Elemente werden entweder als Inline-Element oder ab JSF 1.2 wahlweise auch als Block-Element gerendert. Ein Block-Element wird vom Browser immer in einer neuen Zeile gerendert, ein Inline-Element erzeugt keinen Zeilenumbruch, außer die Zeile ist zu Ende. Die Ausgabemethode wird mit dem Attribut layout gesteuert: Der Wert block führt zu einer Ausgabe als <div/> -Element, bei allen anderen Werten wird ein <span/> -Element ausgegeben.
Ein h:panelGrid -Element erzeugt eine Tabelle und ordnet Kindkomponenten in den Zeilen und Spalten an. Dazu muss die Anzahl der Spalten mit dem Attribut columns definiert werden. Dadurch wird das erste enthaltene Element in die erste Zeile in der ersten Spalte, das zweite Element in die erste Zeile in der zweiten Spalte - und so weiter bis zur mit columns definierten Spalte - gesetzt. Das darauffolgende Element wird dann in die zweite Zeile in der ersten Spalte gestellt und der Vorgang setzt sich nach demselben Muster fort (Listing Die Panel-Grid-Komponente h:panelGrid ).
<h:panelGrid columns="3" styleClass="table-background"
    width="40" columnClasses="table-odd-col, table-even-col"
    footerClass="table-footer" headerClass="page-header">
  <f:facet name="header">
    <h:outputText value="Kopfzeile"/>
  </f:facet>
  <h:outputText value="(1,1)"/>
  <h:outputText value="(1,2)"/>
  <h:outputText value="(1,3)"/>
  <h:outputText value="(2,1)"/>
  <h:outputText value="(2,2)"/>
  <h:outputText value="(2,3)"/>
  <f:facet name="footer">
    <h:outputText value="Fußzeile"/>
  </f:facet>
</h:panelGrid>
Die Anzahl der Kindkomponenten in einer h:panelGrid -Komponente sollte immer ein Vielfaches der definierten Anzahl an Spalten sein. Geht das nicht auf oder wird eine leere Zelle benötigt, kann ein leeres h:panelGroup -Element eingefügt werden. Für den Fall, dass Sie in einer Zelle der Tabelle mehrere Komponenten anzeigen wollen, können Sie diese ebenfalls mit einem h:panelGroup -Element gruppieren.
h:panelGrid kann mit Facets um eine Kopf- und eine Fußzeile erweitert werden. Dazu wird einfach ein Facet mit einem definierten Namen - header für Kopfzeilen und footer für Fußzeilen - als Kindelement hinzugefügt.
Design: Das Layout der einzelnen Tabellenteile kann über das Einbinden von CSS-Stylesheet-Klassen in die Attribute columnClasses , footerClass , headerClass und rowClasses bestimmt werden. Wird headerClass spezifiziert, wird diese Klasse auf das Kopfzeilen- Facet angewendet, dasselbe gilt für footerClass und ein Fußzeilen- Facet .
<table class="table-background" width="40">
  <thead>
   <tr>
     <th class="page-header" colspan="3" scope="colgroup">
     Kopfzeile</th>
   </tr>
  </thead>
  <tfoot>
   <tr>
     <td class="table-footer" colspan="3">Fußzeile</td>
   </tr>
  </tfoot>
  <tbody>
   <tr>
     <td class="table-odd-col">(1,1)</td>
     <td class="table-even-col">(1,2)</td>
     <td class="table-odd-col">(1,3)</td>
   </tr>
   <tr>
     <td class="table-odd-col">(2,1)</td>
     <td class="table-even-col">(2,2)</td>
     <td class="table-odd-col">(2,3)</td>
   </tr>
  </tbody>
</table>

3.9 UIViewRoot

Die Komponente UIViewRoot bildet das Wurzelelement des Komponentenbaums ab. Über die UIViewRoot -Komponente kann somit auf alle Elemente des Baums zugegriffen werden, sie selbst wird aber nicht dargestellt. Das Tag der Komponente befindet sich in der Core-Tag-Library und wird mit f:view in eine Seitendeklaration eingebunden.
f:view bietet einige für die tägliche Arbeit mit JSF nützliche Attribute. Über das locale -Attribut kann die Lokalisierung für den Komponentenbaum und die daraus gerenderte Seite gesetzt werden. Gültige Werte für locale sind Zeichenketten, die einen Lokalisierungscode enthalten (wie " de" oder " en" ), oder Instanzen der Klasse java.util.Locale . In JSF 1.2 sind zwei weitere interessante Attribute hinzugekommen: beforePhase und afterPhase bieten die Möglichkeit, mit einer Method-Expression Phase-Listener für die Seite einzubinden. Diese Listener werden vor beziehungsweise nach jeder Phase (außer der Restore-View-Phase) aufgerufen. Die Methode muss dazu folgende Signatur aufweisen:
void phaseListener(javax.faces.event.PhaseEvent ev)
Bleibt nur noch zu klären, warum Phase-Listener, die über die Attribute beforePhase und afterPhase registriert werden, für die erste Phase nicht ausgeführt werden: Es gibt zu Beginn der ersten Phase noch keinen Komponentenbaum. UIViewRoot kann daher auch keine Ereignisse auslösen.

3.10 Nachrichtenkomponenten

Beim Ausführen eines Requests können zum Beispiel bei der Validierung, der Konvertierung oder bei der Ereignisbehandlung Nachrichten ( Messages ) entstehen. Nachrichten werden in JSF zu Instanzen der Klasse FacesMessage . Mithilfe der h:message - oder der h:messages -Komponente können diese Nachrichten für den Benutzer dargestellt werden. Jede Nachricht weist einen Schweregrad (es gibt die Stufen Info , Warn , Error , Fatal ) und eine beschreibende Information auf. Details des JSF-Nachrichtensystems werden in Abschnitt Sektion:  Nachrichten behandelt.
Styling von Nachrichten: Über die Einbindung von CSS-Klassen bzw. CSS-Stilen ist es möglich, Nachrichten je nach Schweregrad unterschiedlich darzustellen. Dazu werden die Attribute infoClass , infoStyle , warnClass und warnStyle , errorClass , errorStyle , fatalClass und fatalStyle mit dem Verweis auf den darzustellenden CSS-Stil oder die darzustellende CSS-Klasse verwendet.
Eine Nachricht - h:message: Um nur eine einzelne FacesMessage für eine bestimmte Komponente anzuzeigen, wird das h:message -Tag eingesetzt. Sollten mehrere Nachrichten für die Komponente generiert werden, wird mit dieser Komponente nur die jeweils erste angezeigt. Mit dem Attribut for wird die ID jener Komponente referenziert, für die die erste Nachricht dargestellt werden soll. In Listing h:message im Einsatz ist das Eingabefeld für den Geburtstag aus MyGourmet mit einem h:message -Tag für die Komponente angegeben.
<h:inputText id="birthday" size="30"
    value="#{customerBean.customer.birthday}">
  <f:convertDateTime pattern="dd.MM.yyyy"/>
  <f:validator validatorId="at.irian.Birthday"/>
</h:inputText>
<h:message for="birthday" showDetail="true" showSummary="true"
   warnStyle="color: green" infoStyle="color: blue"
   errorStyle="color: red"/>
Gibt der Benutzer ein Geburtsdatum in der Zukunft ein, wird ein Validierungsfehler ausgelöst und in der Ausgabe eine Nachricht mit dem CSS-Stil " color: red" erzeugt (der Schweregrad jeder Standard-Validierungsnachricht ist error ).
Ist das Attribut showDetail der Nachrichtenkomponente auf true gesetzt, wird die detaillierte Fehlerinformation angezeigt, ist showSummary auf true gesetzt, erfolgt eine Anzeige der Zusammenfassung der Fehlerinformation. Haben beide Attribute den Wert true , wird die Zusammenfassung und die Detailinformation ausgegeben.
Alle Nachrichten - h:messages: Mehrere Nachrichten können mit der h:messages -Komponente angezeigt werden. Wird das globalOnly -Attribut auf false gesetzt, werden alle Nachrichten angezeigt, ist es auf true gestellt, werden nur Nachrichten ausgegeben, die nicht zu einer Komponente gehören (in der Regel sind das Nachrichten, die durch Event-Listener- oder Action-Methoden ausgelöst wurden). Mit layout wird die Darstellungsart der Nachrichten bestimmt. Mit layout = " list" werden die Nachrichten eine nach der anderen in einem HTML-Listenelement ausgegeben, mit layout = " table" werden die einzelnen Nachrichten in Tabellenzeilen angezeigt.
Jede Seite mit messages-Element!: Vergessen Sie bei der Entwicklung einer Webapplikation nicht, ein Element zur Ausgabe von Nachrichten in die Seite einzufügen, um Validierungs- und Konvertierungsfehler sofort zu erkennen. Typische Auswirkung: Beim Fehlschlagen der Konvertierung oder Validierung wird keine Navigation ausgeführt. JSF greift Ihnen dabei ab Version 2.0 unter die Arme und fügt - wenn keine existiert - automatisch eine h:messages -Komponente in die Ansicht ein - allerdings nur, wenn die Project-Stage auf Development gesetzt ist (siehe Abschnitt Sektion:  Project-Stage ).

3.11 Komponenten zur GET-Navigation

Die Komponente UIOutcomeTarget wurde mit Version 2.0 von JSF in den Standard aufgenommen und bildet einen zentralen Aspekt der erweiterten Unterstützung von GET-Anfragen und Bookmarks. Die Aufgabe dieser Komponente besteht darin, einen Hyperlink zu erstellen, der bei Aktivierung eine einfache GET-Anfragen absetzt, aber trotzdem den Navigationsmechanismus von JSF benutzt.
In der HTML-Tag-Library existieren Tags für zwei Ausprägungen dieser Komponente, die sich lediglich in der Art der gerenderten Ausgabe unterscheiden:
Beide Komponenten haben die Attribute value und outcome , mit denen der Hyperlink definiert wird. Der Wert von value erscheint - je nach Tag - in der gerenderten Ausgabe als Text des Links oder der Schaltfläche. Ausschlaggebend für das Ziel des Links ist der Wert des Attributs , der beim Rendern der Komponente an den Navigation-Handler weitergereicht wird. Dieser versucht einen Navigationsfall zu finden, bei dem from-outcome mit dem Wert von outcome übereinstimmt. Bleibt die Suche erfolglos, wird der Wert von outcome direkt als View-ID interpretiert.
Listing h:link im Einsatz zeigt zwei Beispiele für h:link mit einem direkten Link auf die Ansicht /showCustomer.xhtml . Im Unterschied zur "klassischen" Navigation wird das Ziel der Navigation hier bereits in der Render-Response-Phase bestimmt und nicht erst in der Invoke-Application-Phase beim Postback. Mit f:param ist es möglich, Parameter an den Link anzuhängen, wie das zweite Tag zeigt.
<h:link outcome="/showCustomer.xhtml"
    value="#{msgs.menu_show_customer}"/>
<h:link outcome="/showCustomer.xhtml"
    value="#{msgs.menu_show_customer}">
  <f:param name="id" value="1234"/>
</h:link>
Anders als bei den Befehlskomponenten müssen h:link und h:button nicht in einem h:form -Tag eingebettet sein. Weiterführende Informationen zur Unterstützung von Bookmarks und GET-Anfragen finden Sie in Abschnitt Sektion:  Bookmarks und GET-Anfragen in JSF .

3.12 Ressourcenbezogene Komponenten

Mit JSF 2.0 hat ein standardisiertes Verfahren zur Verwaltung von Ressourcen wie Stylesheets oder Skripte in den Standard Einzug gehalten. Wir wollen an dieser Stelle nur einen kurzen Überblick geben und nicht im Detail auf die Ressourcenverwaltung eingehen. Eine ausführlichere Beschreibung folgt in Kapitel Kapitel:  Verwaltung von Ressourcen .
Folgende neue Tags der HTML-Tag-Library erlauben das komfortable Einfügen von Ressourcen in die Ansicht:
Ressourcen werden im einfachsten Fall durch ihren Dateinamen identifiziert. Optional können sie auch in Bibliotheken gruppiert werden, die ebenfalls einen Namen aufweisen. In den beiden oben genannten Tags können diese Werte direkt in die Attribute name und library eingetragen werden.
Folgendes Tag fügt zum Beispiel das Stylesheet main.css aus der Bibliothek styles in die Ansicht ein:
<h:outputStylesheet name="main.css" library="styles"/>
Intern erstellt JSF daraus den Dateinamen /styles/main.css und versucht anschließend, diese Datei an folgenden Stellen in der angegebenen Reihenfolge zu finden:
  1. /resources im Wurzelverzeichnis der Anwendung
  2. /META-INF/resources in Jar-Dateien im Classpath
Zusätzlich erlaubt JSF die Positionierung einzelner Ressourcen in definierten Bereichen einer Ansicht, wie dem Head oder dem Body . Damit JSF diese Bereiche richtig identifizieren kann, gibt es folgende neue Komponenten in der HTML-Tag-Library :
Beim Einbinden einer Skript-Ressource mit h:outputScript kann der gewünschte Bereich mit dem Attribut target angegeben werden. Die erlaubten Werte sind head , body und form .
Wenn Sie in Ihrer Anwendung Ressourcen einsetzen, sollten Sie in jeder Ansicht h:head und h:body verwenden. Andernfalls ist das korrekte Laden von Ressourcen nicht gewährleistet. Das gilt auch, wenn Sie eine Komponentenbibliothek verwenden, die ihre Ressourcen mit JSF-Hausmitteln verwaltet. In diesem Fall kann es allerdings sein, dass die Bibliothek eigene Komponenten für diesen Zweck anbietet.

3.13 Verhaltens-Interfaces

In JSF gibt es mehrere Interfaces , die ein bestimmtes Verhalten von Komponenten definieren. Bei der Vorstellung der Standardkomponenten wird Ihnen vielleicht aufgefallen sein, dass eine Reihe von ihnen ähnliche Verhaltensmuster aufweisen. Zum Beispiel gibt es einige Komponenten, die über einen Wert verfügen, andere können diesen Wert sogar verändern, und wieder andere lösen ein Action-Event aus, wenn ein Benutzer sie aktiviert.
Als Benutzer der Komponente können Sie aus den von der Komponente implementierten Interfaces neben dem Verhalten auch ablesen, welche Objekte Sie an die Komponente anhängen können. Ein Validator ist zum Beispiel nur für Komponenten erlaubt, deren Wert veränderbar ist.
Hier eine Auswahl der wichtigsten Verhaltens-Interfaces:

3.14 MyGourmet 8: Standardkomponenten

MyGourmet 8 fasst alle Änderungen aus den vorangegangenen Abschnitten über die JSF-Standardkomponenten zusammen. Die einzelnen Neuerungen wurden bereits dort erklärt. Hier soll nur mehr das vollständige Beispiel präsentiert werden. Im Browser sieht die Seite editCustomer.xhtml mit den neuen Feldern wie in Abbildung MyGourmet 8: Ansicht im Browser aus.
Abbildung:MyGourmet 8: Ansicht im Browser
In der Seite showCustomer.xhtml werden die zuvor eingegebenen Daten ausgegeben. Erwähnenswert ist hier die Ausgabe der Liste der bevorzugten Kategorien und der Werte der anderen Auswahlfelder.
Anstatt in der Ansicht über die ausgewählten Kategorien zu iterieren, wird die Eigenschaft preferredCategoriesString der Bean customerBean bei der Ausgabe verwendet. Der Aufbau der darzustellenden Zeichenkette wird in die Backing-Bean verschoben - die Logik ist somit an zentraler Stelle definiert und die Seitendefinition bleibt schlank.
Auf ähnliche Art und Weise wird das ausgewählte Geschlecht ausgegeben. Im Modell wird das Geschlecht als einzelnes Zeichen abgelegt - die Eigenschaft selectedGender in der Backing-Bean dient der Ausgabe. Intern wird dabei das Zeichen in eine lesbare Zeichenkette umgewandelt.
Die entsprechenden Methoden der Klasse CustomerBean finden sich in Listing MyGourmet 8: Auszug der Klasse CustomerBean .
public String getPreferredCategoriesString() {
  StringBuilder categories = new StringBuilder();
  List<String> cats = customer.getPreferredCategories();
  if (cats != null) {
    for (String cat : prefCats) {
      if (categories.length() > 0) {
        categories.append(", ");
      }
      categories.append(getCategoryLabel(cat));
    }
  }
  return categories.toString();
}

public String getSelectedGender() {
  return customer.getGender() != null
      ? getGenderLabel(customer.getGender()) : null;
}

private String getCategoryLabel(String category) {
  FacesContext c = FacesContext.getCurrentInstance();
  return GuiUtil.getResourceText(
      c, "msgs", "category_" + category);
}

private String getGenderLabel(char gender) {
  FacesContext c = FacesContext.getCurrentInstance();
  return GuiUtil.getResourceText(
      c, "msgs", "gender_" + gender);
}
Die Ausgabe des ausgewählten Geschlechts kann alternativ über eine Map mit dem Geschlecht als Schlüssel und der Zeichenkette als Wert erfolgen. In der Seite wird diese Map in einem EL-Ausdruck mit dem Geschlecht des Kunden als Schlüssel verwendet:
#{customerBean.genderMap[
    customerBean.customer.gender]}
Damit ist das Beispiel MyGourmet 8 abgeschlossen. Im Anschluss folgt direkt ein weiteres Beispiel, das der Standardkomponente UIData und der Umschaltung zwischen Listen- und Detailansicht gewidmet ist.

3.15 MyGourmet 9: UIData und Detailansicht

MyGourmet 9 demonstriert den Einsatz der Standardkomponente UIData und die Umschaltung zwischen Listen- und Detailansicht. Dazu erweitern wir die Daten des Kunden um eine Liste von Adressen. Damit diese Adressdaten nicht bei jedem Testlauf eingegeben werden müssen, wird die bisherige Reihenfolge der Seiten umgedreht. Die Startseite ist jetzt showCustomer.xhtml mit der Liste von Adressen. Die Daten des Kunden bleiben editierbar und die einzelnen Adressen können bearbeitet und gelöscht werden. Im Browser sehen die Seiten dann wie in Abbildung MyGourmet 9: showCustomer.xhtmlim Browser und MyGourmet 9: editAddress.xhtmlim Browser aus.
Abbildung:MyGourmet 9: showCustomer.xhtmlim Browser
Abbildung:MyGourmet 9: editAddress.xhtmlim Browser
Ein Ausschnitt von showPersons.xhtml mit den zusätzlichen h:commandLink -Tags zur Navigation auf die Detailseiten und zum Löschen einer Adresse ist in Listing MyGourmet 9: Adressdaten in showCustomer.xhtml zu finden.
<h:dataTable var="address"
    value="#{customerBean.customer.addresses}">
  <h:column>
    <f:facet name="header">
      <h:outputText value="#{msgs.zip_code}"/>
    </f:facet>
    <h:outputText value="#{address.zipCode}"/>
  </h:column>
  <h:column>
    <f:facet name="header">
      <h:outputText value="#{msgs.city}"/>
    </f:facet>
    <h:outputText value="#{address.city}"/>
  </h:column>
  <h:column>
    <f:facet name="header">
      <h:outputText value="#{msgs.street}"/>
    </f:facet>
    <h:outputText value="#{address.street}"/>
  </h:column>
  <h:column>
    <h:commandLink value="#{msgs.edit}"
      action="#{addressBean.edit(address)}"/>
     
    <h:commandLink value="#{msgs.delete}"
      action="#{customerBean.deleteAddress(address)}"/>
  </h:column>
</h:dataTable>
Die Klasse Customer wird um die Eigenschaft addresses erweitert. Die Liste besteht aus Instanzen der Klasse Address mit den Eigenschaften zipCode , city , street und country . Der Einfachheit halber wird die Liste mit zwei Elementen initialisiert, wenn sie leer ist. Listing MyGourmet 9: Adressdaten in Customer zeigt den zugehörigen Code der Klasse Customer .
private List<Address> addresses =
    new ArrayList<Address>();
public List<Address> getAddresses() {
  if (addresses.size() == 0) {
    addresses.add(new Address(
        1010, "Wien", "Stephansplatz 1", "Austria"));
    addresses.add(new Address(
        1040, "Wien", "Karlsplatz 1", "Austria"));
  }
  return addresses;
}
public void setAddresses(List<Address> addresses) {
  this.addresses = addresses;
}
Die Liste der Adressen kann somit bereits ausgegeben werden. Wie kommen wir aber jetzt von der Übersichtsseite zur Detailseite, und das auch noch mit den richtigen Daten? Der oben gezeigte Quelltext von showCustomer.xhtml verrät bereits den kompletten Trick. Der entscheidende Punkt ist der Einsatz einer Method-Expression mit einem Parameter, was die neue Unified-EL ermöglicht. Um die Navigation auf die Detailseite auszulösen, wird das action -Attribut des h:commandLink -Elements auf #{addressBean.edit(address)} gesetzt.
Sehen wir uns zum Abschluss noch das Löschen einer Adresse an. Auch dazu greifen wir auf die neue Unified-EL zurück und verwenden eine Method-Expression mit einem Parameter. Das h:commandLink -Tag zum Löschen einer Adresse ist in Listing MyGourmet 9: Adressdaten in showCustomer.xhtml ersichtlich. Mit der Method-Expression im Attribut action wird die zu löschende Adresse als Parameter an die Methode übergeben. Dadurch haben wir direkt in der Methode Zugriff auf die Adresse, was bislang nicht so einfach möglich war. Den Code der Action-Methode zeigt Listing MyGourmet 9: Action-Methode zum Löschen einer Adresse .
public String deleteAddress(Address address) {
  customer.getAddresses().remove(address);
  return null;
}
Die neue Version der Unified-EL ist ein Teil von Java EE 6 und wird automatisch mit allen Servern geliefert, die Servlet 3.0 und JSP 2.2 unterstützen (dazu zählen zum Beispiel Tomcat 7 oder Jetty 8). Falls Sie einen älteren Server einsetzen, müssen Sie trotzdem nicht auf die wichtigsten Features der neuen Unified-EL verzichten. Abschnitt subsec Konfiguration der Unified-EL zeigt die Verwendung der alternativen EL-Implementierung von JBoss .