JSF ohne Warteschleife

2. Verwalten von Navigation Cases mit Annotations

JSF bietet für die Verwaltung von Navigation Cases die Konfigurationsmöglichkeit über die Datei faces-config.xml. Dort können Sie die Navigation Cases konfigurieren. Diese Konfiguration hat zwei gravierende Nachteile:

  • Sie erfordert vom Entwickler bei der Programmierung bei jedem Bean einen Wechsel zwischen den Bean-Methoden und den Navigation Cases, die möglich sind.
  • Die Datei faces-config.xml wird nur beim Start der Applikation geladen und kann während der Laufzeit nicht geändert werden.

Mit JSF 2.0 gibt es zwar die Möglichkeit, die Navigation direkt in Buttons/Anchors zu definieren, dadurch wird die Verwaltung der Navigation jedoch noch stärker in der Applikation verteilt und damit noch schlechter wartbar.

Steuerung JSF-Version Automatische Aktualisierung möglich Navigationsziel im Quellcode erkennbar
Standard JSF Navigation Cases (faces-config.xml) 1.2, 2.0 Nein Nein
Annotationsbasierte Navigation Cases 1.2, 2.0 Ja Ja

Tabelle 1: Unterschiede bei der Navigationssteuerung mit faces-config vs. Annotations

Diese Nachteile lassen sich auf sehr elegante Weise lösen, und zwar über NavigationCases mit Annotations. Die Anregung dazu stammt aus dem Buch „Java Server Faces 2.0 – The Complete Reference“ von Ed Burns und Chris Schalk. Diese skizzieren die Idee für die Umsetzung eines annotationsbasierenden NavigationHandlers. Die Umsetzung können Sie nun in diesem Artikel nachlesen und dann in ihrer eigenen Applikation einsetzen. Die Grundidee dabei ist, dass über jeder Methode die NavigationCases mittels Annotations definiert werden:

@NavigationCase(outcome=OutcomeConstants.SUCCESS, toViewId="/views/confirm.xhtml", redirect=true)
public void save() {
// .
return OutcomeConstants.SUCCESS;
}

Werden mehrere NavigationCases definiert, dann müssen diese über eine @NavigationCases-Annotation umklammert werden (Listing 3).

@NavigationCases ({
  @NavigationCase(outcome=OutcomeConstants.SUCCESS, toViewId=="/views/confirm.xhtml", redirect=true),
  @NavigationCase(outcome=OutcomeConstants.ERROR, toViewId=="/views/error.xhtml", redirect=true)
 })
 public String save() {
  String forward = OutcomeConstants.SUCCESS;
  try {
   // save
  } catch (Exception e) {
   forward = OutcomeConstants.ERROR;
   // save error message
  }
  
  return forward;
 }

Listing 3

Damit sieht der Entwickler auf einen Blick, welche Navigation Cases definiert wurden und wohin verzweigt wird. Die Verweise beim Attribut toViewId können über eine Konstantenklasse ViewIdConstants zusammengefasst und dann ebenso zentral administriert werden:

@NavigationCases ({
  @NavigationCase(outcome=OutcomeConstants.SUCCESS, toViewId=ViewIdConstants.CONFIRM_PAGE, redirect=true),
  @NavigationCase(outcome=OutcomeConstants.ERROR, toViewId=ViewIdConstants.ERROR_PAGE, redirect=true)
 })

Die Klasse ViewIdConstants enthält dann alle Verweise für die gesamte Applikation:

public class ViewIdConstants {
 public static final String CONFIRM_PAGE = "/views/confirm.xhtml";
 public static final String ERROR_PAGE = "/views/error.xhtml";
}

Da ein Custom NavigationHandler bei jedem Klicken auf einen Command-Button/-Link ausgeführt wird, kann dieser auch bei Bedarf alle Navigation Cases neu initialisieren. Diese Prüfung erfolgt in der Implementierungsklasse AnnotationNavigationHandlerImpl:

NavigationMapDTO maps = null;
log.debug("debug: " + debug.booleanValue());
if (debug.booleanValue()) {
maps = NavigationAnnotationUtil.createNavigationCaseMap();
} else {
   	maps = (NavigationMapDTO)servletContext.getAttribute("navigationHandlerMaps");
 }

Dadurch wird die NavigationCase Map beim Debug-Modus bei jedem Zugriff neu initialisiert, ansonsten aus dem ServletContext geladen. Das Auslesen aller Klassen für die Auswertung der Annotations erfolgt über die Methode NavigationAnnotationUtil.createNavigationCaseMap(). Dort muss das Package der auszuwertenden Backing Beans eingetragen werden.

Anleitung für den Einsatz der NavigationCases in Ihrer Applikation

Die Implementierung des Navigation Handlers wird in der Beispielapplikation unter dem Package „at.fwd.jsf_beispiel.jsf.navigation.*“ bereitgestellt. Damit Sie den NavigationHandler in ihrer Applikation nützen können, müssen Sie nur die Packages unter „at.fwd.jsf_beispiel.jsf.navigation.*“ kopieren. Für die Aktivierung des NavigationHandlers müssen Sie in der faces-config.xml den Navigation Handler deklarieren (Listing 4).


.
 com.sun.facelets.FaceletViewHandlerat.fwd.jsf_beispiel.jsf.navigation.AnnotationNavigationHandlerImpl
 .
 

Listing 4

Danach müssen Sie nur noch bei ihren Methoden die NavigationCase Annotations eintragen und schon können Sie diese nutzen. Wenn der Seam-Debug-Modus aktiviert ist, dann werden die Navigation Cases bei jedem Klick auf einen commandButton oder commandLink neu geladen und können damit zur Laufzeit jederzeit geändert werden.

3. Zugriff auf Beans und deren Attribute mit Eclipse JBoss Tools

Wenn Sie Ihre Facelet-Dateien mit den Standard-Eclipse-Editoren bearbeiten, dann müssen Sie die Namen Ihrer Backing Beans sowie deren Methoden und Attribute manuell eintippen oder diese nachschlagen. Diese zeitraubende Arbeit können Sie sich durch den Einsatz der JBoss Tools sparen.

Mit den Eclipse JBoss Tools können Sie direkt von Ihren Facelet-Dateien (XHTML-Dateien) auf die Managed Beans zugreifen („Content Assist“-Feature). Die JBoss Tools unterstützen dabei sowohl in faces-config.xml deklarierte Managed Beans als auch über JBoss Seam deklarierte Managed Beans (mittels @Name-Annotation). Sobald Sie in der XHTML-Datei eine Expression eingeben, können Sie über die Eingabe von -SPACE auf die Managed Beans, deren Methoden und deren Attribute zugreifen: # {managedBean.attribute}.

Abb. 1: Screenshot – Zugriff auf Managed Beans aus einer Facelet-Datei

Eine genaue Anleitung für das Aktivieren der JSF-Capabilities von JBoss Tools finden Sie im JSF Tools Reference Guide. Für das Aktivieren der Seam Capabilities finden Sie eine Anleitung im Seam Dev Tools Reference Guide.

Eclipse JBoss Tools

Die JBoss Tools gibt es seit dem Jahr 2007 und sind mittlerweile zu einem Sammelbegriff für eine Menge eigenständiger Tools für Eclipse geworden. Für JSF-Entwickler sind dabei insbesondere die JSF-Tools und die Seam-Dev-Tools interessant. Mit den JBoss-JSF-Tools können Facelet-Dateien auch (wenn auch eingeschränkt) grafisch über den Visual Page Editor bearbeitet werden. Die JSF- und Seam-Tools bieten Ihnen folgende Features:

  • Direkter Zugriff auf Ihre Managed Beans und deren Attribute („Content Assist“-Feature)
  • Automatische Prüfung der Gültigkeit aller Referenzen in Ihren Facelet-Dateien (*.xhtml-Dateien)
  • Optische Vorschau und visuelles Bearbeiten der Facelet-Dateien

Abb. 2: Screenshot – Facelet-Dateien visuell bearbeiten

Die JSF-Tools bieten die Möglichkeit, Facelet-Dateien auf deren Gültigkeit zu prüfen. Dabei werden auch die Referenzen auf Beans bzw. deren Attribute auf Gültigkeit geprüft und bei falschen Referenzen als Warnung angezeigt. Damit können Sie beispielsweise nach einem Refactoring von Attributen ihrer Backing Beans automatisch auf fehlende Referenzen in den Facelet-Dateien prüfen. Da die Validierung allerdings bei jedem Build erfolgt, empfiehlt es sich, insbesondere auf langsameren PCs, diese nur bei Bedarf zu aktivieren.

Das optische Bearbeiten der Facelets ist momentan noch rudimentär und erlaubt eine grobe Vorschau, wie das Facelet im Browser aussehen wird. Für ein schnelles Arbeiten mit dem JSF-Editor empfiehlt es sich, die Standardansicht von „Visual/Source“ auf „Source“ zu schalten. Damit verkürzt sich die Ladezeit für das Öffnen von Facelet-Dateien wesentlich. Die Einstellungen können in den Preferences unter JBOSS TOOLS | WEB | EDITORS | VISUAL PAGE EDITORS | GENERAL, „default active editor’s tab“ umgestellt werden.

Es gibt noch weitere JBoss Tools für Hibernate, Web Services, Struts und viele andere mehr. Einen guten Überblick über die verfügbaren Tools gibt Ihnen die aktuelle Dokumentation der JBoss Tools 3.1.0.GA. Veröffentlicht werden die Jboss Tools von Jboss.org als Jboss Community Project unter LGPL.

Beispielapplikation

Sie können mit der Beispielapplikation die Anregungen des Artikels ausprobieren und in Ihre eigene Applikation übernehmen. Das Beispiel finden Sie hier, es wurde mit Eclipse Galileo SR2 und den Jboss Tools 3.1.0.GA erstellt. Die Entwicklertests erfolgten mit Verwendung des FileSynch-Plugins mit Apache Tomcat 6.0. Mit dem FileSynch-Plug-in können Sie alle Änderungen in Ihrem Eclipse-Projekt direkt in einen Applikationsserver Ihrer Wahl synchronisieren. Für Ungeduldige gibt es in der Beispielapplikation auch eine WAR-Datei (jsf-beispiel.war), die Sie gleich in den Applikationsserver Ihrer Wahl kopieren können.

Bei Jboss AS 4.2.3 oder 5.1 können Sie die WAR-Datei 1 : 1 in das Deploy-Verzeichnis kopieren, beim Tomcat 6.0 müssen Sie einige Bibliotheken in das Tomcat-Lib-Verzeichnis kopieren. Nähere Anleitungen dazu finden Sie in der Datei readme.txt.

Johannes Fiala arbeitet selbstständig als Softwarearchitekt und Coach in verschiedenen J2EE-Projekten, insbesondere mit Java Server Faces und JBoss Seam.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.