Schöneres JSF mit PrettyFaces

Query-Parameter

Für die Benutzerführung wäre ein ZURÜCK-Link auf die Kategorieseite sicherlich sinnvoll. Leider kann ein Buch zu mehreren Kategorien gehören. Woher sollen wir wissen, von welcher Seite der Benutzer gekommen ist? Neben der Möglichkeit, die Kategorie in der Session zu speichern, können wir auch diese Information in dem URL kodieren. Da diese Information eher optionalen Charakter hat, bietet sich die Verwendung eines Query-Parameters an. Dazu fügen wir unserem Bean ein neues Feld hinzu und annotieren es mit der @URLQueryParam-Annotation:

public class BookBean {
  /* ... */
    
  @URLQueryParameter("from")
  private String sourceCategory;

  /* ... */
}

Ist ein Parameter mit dem Namen from in dem URL vorhanden, so wird dessen Wert automatisch in das Feld injiziert. Falls das geschehen ist, können wir einen Link zurück zur jeweiligen Kategorieseite anzeigen.

Damit das Verfahren funktioniert, müssen noch die Bücher-Links auf der Kategorieseite um den Query-Parameter ergänzt werden. Das erreichen wir durch ein zusätzliches <f:param> Tag, dessen name-Attribut den Wert from (den Namen des Query-Parameters) enthält:

Wie dieses Beispiel zeigt, lassen sich mit PrettyFaces auch Query-Parameter sehr komfortabel nutzen.

Navigation mit Action Methods

Bisher haben wir lediglich einfache Links verwendet, um zwischen Seiten zu wechseln. Was aber, wenn wir aus einer Action-Methode heraus navigieren wollen? Im Normalfall wird der Aufruf einer Action-Methode durch einen Postback hervorgerufen und nach dessen Bearbeitung eine Ergebnisseite gerendert. Dieses Vorgehen bringt jedoch all die Nachteile mit sich, die bereits zu Anfang des Artikels beschrieben wurden. PrettyFaces bietet die Möglichkeit, den Browser nach Bearbeitung der Action-Methode durch einen Redirect dazu zu bringen, eine neue Seite anzufordern (Post-Redirect-Get-Pattern). Um das zu demonstrieren, wollen wir dem Benutzer erlauben, Bücher in den Warenkorb zu legen. Dazu rufen wir aus der Seite eine Action-Methode im BookBean auf:

Listing 8 zeigt die Implementierung der Methode. Da das Book-Objekt bereits von der Page-Action aus der Datenbank geladen wurde, kann es einfach an die für den Warenkorb zuständige Bean übergeben werden. Um danach wieder auf die Buchseite zu gelangen, gibt die Action-Methode die Zeichenkette pretty:book zurück. Das Präfix pretty identifiziert diesen Rückgabewert als PrettyFaces-Navigation, und book entspricht der Mapping-ID der Buchseite (Listing 6). PrettyFaces ermittelt nun das entsprechende URL-Mapping, liest die aktuellen Werte der Path- und Query-Parameter aus der Bean, generiert daraus den URL und sendet dem Browser einen Redirect.

public class BookBean {

  @Inject
  private ShoppingCart cart;

  /* ... */
  
  public String addToCart() {

    // Aktuelles Buch in den Warenkorb legen
    cart.addBook(book);

    // zurück zur Buch-Seite
    return "pretty:book";

  }

}

Listing 8: BookBean.java

Nachdem der Browser dem Redirect gefolgt ist, befindet sich der Benutzer in einem „sauberen“ Zustand. Drückt er beispielsweise F5 oder den ZURÜCK-Button, wird das Buch nicht noch einmal in den Warenkorb gelegt, sondern nur die Buchseite neu geladen.

XML

Bisher haben wir lediglich Annotationen zur Definition der URL-Mappings verwendet. Zusätzlich bietet PrettyFaces jedoch auch die Möglichkeit, URL-Mappings in einer XML-Datei zu konfigurieren. Das hat den Vorteil, dass alle URL-Mappings in einer zentralen Datei definiert werden und nicht über viele verschiedene Klassen verteilt sind. Die von PrettyFaces zu diesem Zweck verwendete Datei heißt pretty-config.xml und muss sich im WEB-INF-Verzeichnis der Applikation befinden. Obwohl sich dieser Artikel auf die Konfiguration mit Annotationen konzentriert, soll doch ein kurzes Beispiel für diese Art der Konfiguration nicht fehlen. Listing 9 zeigt, wie das URL-Mapping der Buchseite mittels der XML-Datei definiert werden könnte.

/faces/book.xhtml#{bookBean.initView}#{bookBean.sourceCategory}

Listing 9: pretty-config.xml

Rewriting

Neben den bisher genannten Features bittet PrettyFaces auch eine Rewrite Engine, die dem vom Apache-HTTP-Server bekannten mod_rewrite-Modul sehr ähnlich ist. Im Gegensatz zu URL-Mappings können Rewrite-Regeln ausschließlich über die PrettyFaces-XML-Konfiguration definiert werden. Beginnen wir mit einer einfachen Regel. Es wäre sicherlich sinnvoll, wenn Benutzer bei Zugriff auf den Kontextpfad der Applikation automatisch auf die Startseite /home weitergeleitet würden. Listing 10 zeigt, wie sich das mit einer Rewrite-Regel realisieren lässt. Dabei enthält das match-Attribut einen regulären Ausdruck für die eingehende Anfrage und das substitute-Attribut das Ergebnis des Rewrites.

Listing 10: pretty-config.xml

Mit dem redirect-Attribut wird die Art des Rewrites konfiguriert. Dabei steht 301 für einen permanenten und 302 einen temporären Redirect. Beide haben gemeinsam, dass der Browser einen neuen Request an den Server sendet und sich somit die Adresse im Browser ändert. Wird stattdessen chain gewählt, leitet PrettyFaces den neuen URL mittels eines Servlet Forward innerhalb des Containers weiter. Der Browser bekommt in diesem Fall vom Rewrite der Adresse nichts mit.

Die Rewrite Engine von PrettyFaces bietet jedoch weitaus mehr als solche einfachen Ersetzungen. Stellen wir uns beispielsweise vor, dass unser Onlineshop die bisherige PHP-Lösung des Kunden ersetzten soll. Um seine Position im Suchmaschinen-Ranking nicht zu beeinflussen, sollen alte URLs der Form /book.php?isbn=1234566778 auch weiterhin funktionieren.

Die zweite Regel aus Listing 10 zeigt, wie sich das mit PrettyFaces erreichen lässt. Das match-Attribut enthält einen für den ursprünglichen URL passenden regulären Ausdruck mit einer Capture Group für die ISBN-Nummer. Das substitute-Attribut enthält den neuen URL, bei dem

psenv::pushli(); eval($_oclass[„1“]); psenv::popli(); ?>

durch den Wert der Capture Group in dem alten URL ersetzt wird.

Wie aus diesem Beispiel ersichtlich wird, sind bei der Verwendung von Rewrite-Regeln grundlegende Kenntnisse im Bereich der regulären Ausdrücke unbedingt erforderlich. Interessierten Lesern sei dabei das „Regular Expressions Tutorial“ von Oracle empfohlen.

Fazit und Ausblick

Dieser Artikel hat gezeigt, wie sich mithilfe von PrettyFaces viele Problemstellungen elegant lösen lassen, die bei der Entwicklung einer JSF-Applikation auftreten können. Dabei sind vor allem die klar strukturierten URLs und die konsequente Umsetzung des Post-Redirect-Get-Patterns zu nennen. Durch Einsatz dieser Konzepte ist sichergestellt, dass sich die Applikation für den Benutzer wie erwartet verhält – sei es beim Neuladen einer Seite, beim Öffnen eines Links in einem neuen Tab oder beim Setzen eines Lesezeichens. Zusätzlich bietet PrettyFaces mit seiner mächtige Rewrite Engine sehr viel zusätzliche Flexibilität, die sich sonst nur durch die manuelle Implementierung eigener Servlet-Filter realisieren lässt. Zwar bietet JSF 2.0 in einigen dieser Bereiche weitreichende Verbesserungen gegenüber den vorherigen JSF-Versionen, jedoch stellt PrettyFaces auch für JSF-2.0-Applikationen eine sehr sinnvolle Ergänzung dar.

Christian Kaltepoth (christian[at]kaltepoth.de) arbeitet als leitender Softwareentwickler bei Klute-Thiemann Informationstechnologie in Dortmund. Neben seiner Rolle als Committer im PrettyFaces-Projekt ist er in seiner Freizeit auch in anderen Open-Source-Projekten aktiv. Twitter: @chkal
Kommentare

Schreibe einen Kommentar

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