Struktur des Flows flow1
 
  Managed-Bean im Flow-Scope
 
  Komplette Definition von Flow flow1 mit XML
 
  Komplette Definition von Flow flow1 mit Java
 
  Flow-Definition mit Flow-Call-Knoten und ausgehendem Parameter
 
  Flow-Definition mit eingehendem Parameter
 
  Flow flow1 mit XML
 
  Definition von Flow login-java mit Java
 
  Definition von Flow login mit XML
 
  Definition von Flow forgotPassword
 
  Definition eines Flows mit Defining-Document-ID
 
  Checkout-Flow

11 Faces-Flows

In Webanwendungen gibt es immer wieder Abläufe, die eine abgeschlossene Einheit bilden, sich aber über mehrere Ansichten erstrecken. Denken Sie zum Beispiel an die Registrierung eines Benutzers, bei der in einer ersten Seite die Login-Daten und in einer zweiten Seite Daten zur Person abgefragt werden. Nachdem dieser Vorgang in sich abgeschlossen ist und immer gleich abläuft, liegt die Idee nahe, daraus ein wiederverwendbares Modul zu erstellen. Genau an dieser Stelle kommen die sogenannten Flows ins Spiel.
Bei Flows handelt es sich um eine Gruppierung mehrerer Seiten, die in einer bestimmten Reihenfolge miteinander verknüpft sind. Ein Flow kann von außen über einen definierten Einstiegspunkt gestartet werden. Einmal gestartet werden die Seiten des Flows bis zum Erreichen eines Ausstiegspunkts in der intern definierten Reihenfolge abgearbeitet. Abbildung Checkout-Flow zeigt als Beispiel einen Flow zum Auschecken eines Warenkorbs.
Abbildung:Checkout-Flow
Der Flow besteht aus den Seiten checkout , shipping , payment und confirm . Die Seite checkout ist dabei als Startseite definiert und bildet den Einstiegspunkt in den Flow. Von der Seite confirm aus kann der Flow beendet werden.
Erweiterungen wie Spring Web Flow oder ADF Task Flows ermöglichen bereits seit mehreren Jahren den Einsatz von Flows in Kombination mit JSF. Mit Version 2.2 haben Flows unter dem Namen "Faces-Flows" auch ihren Weg in die JSF-Spezifikation gefunden.
Im restlichen Kapitel widmen wir uns dem Einsatz von Faces-Flows mit JSF 2.2. Zum Einstieg in das Thema zeigen wir in Abschnitt [Sektion:  Ein erstes Beispiel] ein erstes, einfaches Beispiel. Im Anschluss daran werfen wir in Abschnitt [Sektion:  Definition von Flows] einen genaueren Blick auf die Definition von Flows mit XML und mit Java. Zur optimalen Verwaltung von Daten innerhalb von Flows liefert JSF auch gleich den passenden Scope für Managed-Beans mit, wie Abschnitt [Sektion:  Flow-Scope] zeigt. In Abschnitt [Sektion:  Faces-Flows in Jar-Dateien] folgt eine kurze Anleitung zum Verpacken von Flows in Jar-Dateien. Abschließend zeigt Abschnitt [Sektion:  Beispiel Faces-Flows] noch ein etwas umfangreicheres Beispiel.

11.1 Ein erstes Beispiel

Ein Faces-Flow besteht aus mehreren Knoten, die über die interne Navigation des Flows miteinander verbunden sind. JSF definiert verschiedene Arten von Knoten - für das erste Beispiel sind allerdings nur Knoten für Seiten und Knoten zum Beenden des Flows von Interesse.
Im ersten Beispiel werden wir den Flow mit der ID flow1 erstellen. Dieser Flow besteht aus zwei Seiten, die jeweils einen kurzen Text und einen Link zur Navigation auf die nächste Seite enthalten. Aus Sicht der Funktionalität gibt dieses Beispiel nicht viel her - es eignet sich aber sehr gut zur Demonstration der grundlegenden Struktur und der Funktionsweise von Faces-Flows.
Die Definition unseres Flows mit der ID flow1 erfolgt im gleichnamigen Verzeichnis innerhalb der Webapplikation. Darin legen wir die leere Konfigurationsdatei flow1-flow.xml an - JSF kann den Flow ansonsten nicht korrekt auflösen. Bei unserem Beispiel handelt es sich um einen sogenannten impliziten Flow, der auf einigen Konventionen von JSF aufbaut und dadurch mit einer leeren Konfigurationsdatei auskommt. In Abschnitt [Sektion:  Definition von Flows] füllen wir die Konfiguration dann mit Leben.
Nachdem das Grundgerüst steht, können wir uns um die Seiten des Flows kümmern. Dazu legen wir im Flow-Verzeichnis die Dateien flow1.xhtml und page2.xhtml an. Per Konvention erstellt JSF für jede XHTML-Datei im Flow-Verzeichnis einen Seitenknoten, dessen ID dem Dateinamen ohne der Erweiterung .xhtml entspricht. JSF definiert automatisch den Knoten mit der selben ID wie der Flow selbst zum Startknoten des Flows. Zusätzlich definiert JSF einen Knoten zum Beenden des Flows, dessen ID sich aus der Flow-ID und der Zeichenkette -return zusammensetzt. Unser Flow besteht somit aus den Knoten flow1 , page2 und flow1-return .
Abbildung Struktur des Flows flow1 zeigt den Inhalt unseres Flows mit dem Namen flow1 im Wurzelverzeichnis der Webapplikation.
Abbildung:Struktur des Flows flow1
JSF 2.2 integriert Faces-Flows nahtlos in das bestehende Navigationssystem. Zum Starten eines Flows reicht es aus, dessen ID bei der Navigation anzugeben. Dazu gibt es grundsätzlich zwei Varianten. Soll der Flow über eine GET-Anfrage gestartet werden, muss seine ID im Attribut outcome von h:link oder h:button eingetragen werden. Soll der Flow hingegen über eine POST-Anfrage gestartet werden, muss seine ID im Attribut action von h:commandLink oder h:commandButton angegeben werden. Im zweiten Fall kann die Flow-ID auch der Rückgabewert einer Action-Methode sein.
Unser Flow mit der ID flow1 kann zum Beispiel mit einem der folgenden Tags gestartet werden:
<h:link value="Start flow1" outcome="flow1"/>
<h:commandLink value="Start flow1" action="flow1"/>
JSF navigiert beim Starten des Flows auf die im Startknoten angegebene Seite flow1.xhtml . Für die Navigation innerhalb des Flows werden einfach die IDs der Knoten benutzt. Zum Verlassen des Flows auf der Seite page2.xhtml muss die ID flow1-return des Knotens zum Beenden benutzt werden. Unser Flow kann dann zum Beispiel mit einem der folgenden Tags beendet werden.
<h:button value="Flow beenden" outcome="flow1-return"/>
<h:commandButton value="Flow beenden" action="flow1-return"/>
Nach dem Beenden navigiert JSF automatisch auf die Seite /flow1-return.xhtml .

11.2 Definition von Flows

Das volle Funktionsspektrum der Faces-Flows lässt sich nur mit einer expliziten Definition des Flows entfalten. In dieser Definition wird der Flow mit seinen Knoten konfiguriert. Eine Übersicht aller verfügbaren Knotentypen finden Sie in Abschnitt [Sektion:  Typen von Flow-Knoten] . Die Definition von Flows kann wahlweise mit XML (siehe Abschnitt [Sektion:  Definition mit XML] ) oder mit Java (siehe Abschnitt [Sektion:  Definition mit Java] ) erfolgen.
In diesem Abschnitt konzentrieren wir uns auf Flows, die direkt in der Webapplikation definiert sind. Faces-Flows können aber auch in einer Jar-Datei definiert werden. Details dazu finden Sie etwas später in Abschnitt [Sektion:  Faces-Flows in Jar-Dateien] .

11.2.1 Typen von Flow-Knoten

JSF 2.2 bietet folgende Knotentypen für Faces-Flows:

11.2.2 Definition mit XML

Zur Definition eines Flows mit XML kommt die bereits bekannte XML-Datei im Flow-Verzeichnis zum Einsatz. Der Name dieser Datei setzt sich aus der Flow-ID und der Erweiterung -flow.xml zusammen. Syntaktisch handelt es sich bei dieser Konfigurationsdatei um eine stark eingeschränkte faces-config.xml . Das Wurzelelement faces-config darf nur ein einziges flow-definition -Element mit der Definition des Flows enthalten.
Im Element flow-definition muss im Attribut id die Flow-ID angegeben werden. Innerhalb dieses Elements werden die Knoten des Flows definiert. JSF 2.2 sieht dazu für jeden Knotentyp ein eigenes XML-Element vor. Als erstes Beispiel finden Sie in Listing Flow flow1 mit XML eine Konfiguration für unseren Flow flow1 aus Abschnitt [Sektion:  Ein erstes Beispiel] .
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
    version="2.2">
  <flow-definition id="flow1">
    <flow-return id="flow1-return">
      <from-outcome>/index</from-outcome>
    </flow-return>
  </flow-definition>
</faces-config>
Die gezeigte Konfiguration definiert im Element flow-return einen Return-Knoten mit der ID flow1-return . Das Navigationsziel für diesen Knoten wird im Element from-outcome auf den Wert /index festgelegt. Wird der Flow über diesen Knoten beendet, benutzt JSF den Wert /index , um eine Seite außerhalb des Flows aufzulösen. Ohne explizite Navigationsregeln ergibt sich daraus die Seite /index.xhtml - mit einer entsprechenden Navigationsregel in der faces-config.xml kann dieser Wert aber auf eine beliebige Seite abgebildet werden.
Auch mit einer expliziten Konfiguration bleiben die in Abschnitt [Sektion:  Ein erstes Beispiel] vorgestellten Konventionen bestehen. Die über die Konventionen definierten Knoten des Flows bleiben also erhalten. In der Konfiguration definierte Knoten haben aber immer Vorrang und überschreiben per Konvention definierte Knoten mit der gleichen ID.
Tipp: Achten Sie darauf, für das Flow-Verzeichnis, für den Namen der Konfigurationsdatei und für die ID in der Konfiguration immer die selbe Flow-ID zu verwenden.
In Listing Komplette Definition von Flow flow1 mit XML finden Sie die komplette Definition unseres Flows inklusive aller View-Knoten und der Definition des Startknotens. Bei den View-Knoten wird die View-ID der anzuzeigenden Seite inklusive des Flow-Verzeichnisses im Element vdl-document eingetragen. Der Startknoten des Flows wird im Element start-node über seine ID bestimmt.
<flow-definition id="flow1">
  <start-node>start</start-node>
  <view id="start">
    <vdl-document>/flow1/flow1.xhtml</vdl-document>
  </view>
  <view id="final">
    <vdl-document>/flow1/page2.xhtml</vdl-document>
  </view>
  <flow-return id="return">
    <from-outcome>/index.xhtml</from-outcome>
  </flow-return>
</flow-definition>
Mit einem Flow-Call-Knoten kann ein Flow aus einem anderen Flow heraus gestartet werden. Dabei ist es sogar möglich, Parameter an den aufzurufenden Flow zu übergeben. Listing Flow-Definition mit Flow-Call-Knoten und ausgehendem Parameter zeigt, wie aus Flow flow1 heraus der Flow flow2 mit dem Parameter param1 aufgerufen wird.
TODO remove belowskip (layout)
<flow-definition id="flow1">
  <flow-call id="flow2">
    <flow-reference>
      <flow-id>flow2</flow-id>
    </flow-reference>
    <outbound-parameter>
      <name>param1</name>
      <value>#{flow1Bean.value}</value>
    </outbound-parameter>
  </flow-call>
</flow-definition>
Der Parameter wird nur korrekt an den aufgerufenen Flow übergeben, wenn dieser einen eingehenden Parameter mit dem selben Namen definiert. Listing Flow-Definition mit eingehendem Parameter zeigt die Definition des eingehenden Parameters param1 im Flow flow2 .
<flow-definition id="flow2">
  <inbound-parameter>
    <name>param1</name>
    <value>#{flow2Bean.value}</value>
  </inbound-parameter>
</flow-definition>
JSF ermöglicht das Registrieren von Methoden, die beim Starten oder Beenden des Flows ausgeführt werden. Die entsprechenden Methoden müssen dazu in der Konfiguration als Method-Expression in den Elementen initializer oder finalizer eingetragen werden (JSF erwartet eine Methode ohne Parameter mit dem Rückgabewert void ):
<initializer>#{bean.initializeFlow}</initializer>
<finalizer>#{bean.finalizeFlow}</finalizer>

11.2.3 Definition mit Java

Nachdem sich ausufernde XML-Konfigurationen immer geringerer Beliebtheit erfreuen, sieht JSF 2.2 zusätzlich die Möglichkeit zur Definition von Flows mit Java vor. JSF setzt dabei ganz auf Contexts and Dependency Injection (CDI) , das ab Version 6 ebenfalls Teil von Java EE ist, und erwartet die Definition von Flows in sogenannten Producer-Methoden. Informationen zu CDI finden Sie in Kapitel Sektion:  JSF und CDI - Abschnitt sec-cdi-prod-meth Producer-Methoden zeigt Details zu Producer-Methoden im Speziellen.
Jeder Flow wird in einer eigenen Producer-Methode als Instanz vom Typ javax.faces.flow.Flow erstellt. Die Producer-Methode kann in einer beliebigen serialisierbaren Klasse definiert werden und muss mit @Produces und dem von JSF definierten Qualifier annotiert sein. Der Name der Methode kann ebenfalls beliebig werden. Die Methode muss einen Parameter vom Typ javax.faces.flow.builder.FlowBuilder haben, der mit dem Qualifier @FlowBuilderParameter annotiert ist. Nur so ist gewährleistet, dass CDI beim Aufruf der Methode eine einsatzbereite Instanz für diesen Typ an die Methode übergibt.
Listing Komplette Definition von Flow flow1 mit Java zeigt die Definition unseres Flows flow1 mit Java. Der daraus resultierende Flow entspricht dem in Listing Komplette Definition von Flow flow1 mit XML mit XML definierten Flow.
public class Flow1 implements Serializable {
  @Produces @FlowDefinition
  public Flow buildFlow(
      @FlowBuilderParameter FlowBuilder flowBuilder) {
    flowBuilder.id("", "flow1");
    flowBuilder.viewNode("start", "/flow1/flow1.xhtml")
        .markAsStartNode();
    flowBuilder.viewNode("final", "/flow1/page2.xhtml");
    flowBuilder.returnNode("return").fromOutcome("/index");
    return flowBuilder.getFlow();
  }
}
Der Flow wird innerhalb der Producer-Methode mit dem von CDI übergebenen FlowBuilder zusammengestellt. Mit einem Aufruf der Methode id wird die ID des zu erstellenden Flows gesetzt. Die Methode erwartet als ersten Parameter die ID des definierenden Dokuments und erst als zweiten Parameter die Flow-ID. Auf diese Dokumenten-ID kommen wir nochmals in Abschnitt [Sektion:  Faces-Flows in Jar-Dateien] zurück - sie bleibt im Moment leer (Achtung: null ist nicht erlaubt).
Die Knoten unseres Flows werden ebenfalls mit Methoden der Klasse FlowBuilder definiert. Die Methode viewNode erstellt einen View-Knoten und erwartet die Knoten-ID als ersten Parameter und die View-ID der anzuzeigenden Seite inklusive des Flow-Verzeichnisses als zweiten Parameter. Analog erzeugt ein Aufruf der Methode returnNode einen Return-Knoten mit der übergebenen Knoten-ID. Das Navigationsziel wird dann über einen Aufruf von fromOutcome direkt in der erzeugten Knoteninstanz gesetzt. Über die Methode markAsStartNode kann ein beliebiger Knoten des Flows als Startknoten festgelegt werden.
Ganz zum Schluss wird der Flow mit einem Aufruf von getFlow() erzeugt und zurückgeliefert.
Die Definition eines Flow-Call-Knotens mit Parameter sieht in der Java-Konfiguration folgendermaßen aus:
flowBuilder.flowCallNode("flow2").flowReference("", "flow2")
    .outboundParameter("param1", "#{flow1Bean.value}");
Ein eingehender Parameter wird mit Java wie folgt definiert:
flowBuilder.inboundParameter("param1", "#{flow2Bean.value}");
Auch in der Java-Konfiguration können Methoden registriert werden, die JSF beim Starten oder Beenden des Flows aufruft:
flowBuilder.initializer("#{bean.initializeFlow}");
flowBuilder.finalizer("#{bean.finalizeFlow}");

11.3 Flow-Scope

Bis jetzt haben wir uns noch keine Gedanken über die innerhalb eines Flows benutzten Daten gemacht. In Abschnitt Sektion:  Konversationen mit JSF haben wir dieses Thema bereits aus Sicht von Geschäftsprozessen behandelt und den Einsatz von Konversationen empfohlen. Managed-Beans in Konversationen funktionieren natürlich auch im Zusammenspiel mit Faces-Flows. JSF 2.2 bietet aber mit dem Flow-Scope eine maßgeschneiderte Lösung für Managed-Beans, die in Flows zum Einsatz kommen.
In JSF hat jeder Flow seinen eigenen Flow-Scope, dessen Lebensdauer beim Starten des zugeordneten Flows beginnt und sich bis zum Beenden des Flows erstreckt. Der Flow-Scope ist dabei immer an das aktuelle Browserfenster beziehungsweise an den Browsertab gebunden. Es gibt somit keine Probleme, wenn die Anwendung in mehreren Fenstern oder Tabs läuft. Die Unterscheidung von Browserfenstern und Browsertabs wird ab Version 2.2 von JSF intern über sogenannte Client-Windows gemacht Achten Sie auf den Parameter jfwid in der URL.: .

11.3.1 Managed-Beans im Flow-Scope

In JSF ist eine Managed-Bean im Flow-Scope immer genau einem Flow zugeordnet. Dadurch hängt ihre Lebensdauer von der Ausführung des Flows ab. Die Bean-Instanz wird beim ersten Zugriff nach dem Starten des Flows erstellt und beim Beenden des Flows wieder aus dem Speicher entfernt.
JSF setzt auch beim Flow-Scope voll auf CDI und stellt die Scope-Annotation javax.faces.flow.FlowScoped für CDI-Beans zur Verfügung. Da jeder Flow seinen eigenen Scope hat, muss im Element value von @FlowScoped die ID des verknüpften Flows angegeben werden. Listing Managed-Bean im Flow-Scope zeigt eine CDI-Bean im Flow-Scope des Flows flow1 .
@Named
@FlowScoped(value="flow1")
public class Flow1Bean {
  ...
}

11.3.2 Direkter Zugriff auf den Flow-Scope

Für kleinere Datenmengen muss nicht unbedingt eine Managed-Bean erstellt werden. JSF bietet direkten Zugriff auf den Flow-Scope über Java und über das implizite Objekt flowScope in Unified-EL-Ausdrücken.
Java-seitig erfolgt der Zugriff auf den aktuellen Flow-Scope über folgenden Code:
FacesContext ctx = FacesContext.getCurrentInstance();
Map<Object, Object> flowScope = ctx.getApplication()
    .getFlowHandler().getCurrentFlowScope();
flowScope.put("userName", "Michael Kurz");
Der Zugriff auf den Flow-Scope in einer Value-Expression erfolgt über das implizite Objekt flowScope :
<h:outputText value="#{flowScope.userName}"/>

11.4 Faces-Flows in Jar-Dateien

Spätestens dann, wenn ein Faces-Flow in mehreren Applikationen eingesetzt werden soll, muss man sich Gedanken über dessen Wiederverwendbarkeit machen. JSF 2.2 bietet dazu die Möglichkeit, Faces-Flows in Jar-Dateien zu verpacken - und das unabhängig davon, ob der Flow mit XML oder mit Java definiert ist. Die Definition eines Flows in einer Jar-Datei funktioniert ähnlich einfach wie die Definition in einer Applikation, wenn man einige Details beachtet.
Der erste Unterschied ist der Ablageort des Flow-Verzeichnisses. In Jar-Dateien erwartet JSF das Flow-Verzeichnis mit den XHTML-Dateien immer im Verzeichnis /META-INF/flows . Hier ist zu beachten, dass die in Abschnitt [Sektion:  Ein erstes Beispiel] gezeigten Konventionen für Flows in Jar-Dateien nicht gelten. Daher muss jeder einzelne Knoten explizit in der Konfiguration definiert sein.
Das führt uns auch schon zum nächsten Punkt: Die Definition von Flows mit XML erfolgt in Jar-Dateien zentral für alle Flows in der Datei /META-INF/faces-config.xml . In dieser faces-config.xml kann im Element name ein Name für die Konfiguration bestimmt werden. JSF verwendet diesen Namen als zusätzliche ID für den Flow - die sogenannte Defining-Document-ID . Damit lassen sich Namenskonflikte mit Flows aus anderen Jar-Dateien vermeiden. Listing Definition eines Flows mit Defining-Document-ID zeigt die Definition des Flows mit der ID flow1 und der Defining-Document-ID project1 .
<faces-config ...>
  <name>project1</name>
  <flow-definition id="flow1">
    ...
  </flow-definition>
</faces-config>
Wenn ein Flow mit einer Defining-Document-ID definiert ist, muss diese beim Starten des Flows angegeben werden. Dazu muss auf der startenden Komponente mit dem Tag f:attribute das Attribut to-flow-document-id mit der Defining-Document-ID als Wert gesetzt werden. Der Flow aus Listing Definition eines Flows mit Defining-Document-ID wird wie folgt gestartet:
<h:link value="Flow1 starten" outcome="flow1">
   <f:attribute name="to-flow-document-id" value="project1"/>
</h:link>

11.5 Beispiel Faces-Flows

Das Beispiel Faces-Flows enthält neben dem bereits bekannten Flow flow1 in einer XML- und einer Java-Variante zusätzlich den neuen Flow login zum Einloggen eines Benutzers. Anhand dieses Login-Flows wollen wir Ihnen zeigen, wie ein Flow aus einem anderen Flow heraus mit Parametern aufgerufen wird. Den kompletten Quellcode des Beispiels Faces-Flow finden Sie gemeinsam mit den MyGourmet -Beispielen unter http://jsfatwork.irian.at .
Listing Definition von Flow login mit XML zeigt die Definition des Login-Flows mit XML. Dieser Flow liegt direkt in der Applikation im Verzeichnis login . Dort gibt es die Seiten login.xhtml , success.xhtml und error.xhtml , für die JSF per Konvention einen View-Knoten erstellt. Der interessanteste Teil der Definition ist aber der Flow-Call-Knoten für den Flow forgotPassword mit dem Parameter username . Beim Aufruf des zweiten Flows wird der Wert des Parameters aus der Eigenschaft username der Bean loginBean im Flow-Scope ausgelesen und an den Flow übergeben.
<flow-definition id="login">
  <flow-return id="login-return">
      <from-outcome>/index</from-outcome>
  </flow-return>
  <navigation-rule>
    <from-view-id>*</from-view-id>
    <navigation-case>
      <from-outcome>forgotPassword-return</from-outcome>
      <to-view-id>/login/login.xhtml</to-view-id>
    </navigation-case>
  </navigation-rule>
  <flow-call id="forgotPassword">
    <flow-reference>
      <flow-id>forgotPassword</flow-id>
    </flow-reference>
    <outbound-parameter>
      <name>username</name>
      <value>#{loginBean.username}</value>
    </outbound-parameter>
  </flow-call>
</flow-definition>
Der Flow definiert zusätzlich eine Navigationsregel für den Outcome forgotPassword-return , der beim Beenden von Flow forgotPassword zurückgeliefert wird. In diesem Fall wird wieder die Seite angezeigt.
Listing Definition von Flow login-java mit Java zeigt die Java-Variante des Login-Flows.
public class LoginJavaFlow implements Serializable {
  @Produces @FlowDefinition
  public Flow buildFlow(
      @FlowBuilderParameter FlowBuilder flowBuilder) {
    flowBuilder.id("", "login-java");
    flowBuilder.viewNode("start", "/login-java/login-java.xhtml")
        .markAsStartNode();
    flowBuilder.viewNode("success", "/login-java/success.xhtml");
    flowBuilder.viewNode("error", "/login-java/error.xhtml");
    flowBuilder.flowCallNode("forgotPassword")
        .flowReference("", "forgotPassword")
        .outboundParameter("username",
            "#{loginJavaBean.username}");
    flowBuilder.navigationCase().fromViewId("*")
        .fromOutcome("forgotPassword-return")
        .toViewId("/login-java/login-java.xhtml");
    flowBuilder.returnNode("login-return").fromOutcome("/index");
    return flowBuilder.getFlow();
  }
}
Nachdem beide Varianten in der selben Applikation definiert sind, haben wir für die Java-Variante die Flow-ID login-java gewählt. Aus Sicht der Funktionalität gibt es keinen Unterschied zwischen den beiden Ausführungen des Login-Flows.
Der Flow forgotPassword liegt in einem eigenen Maven-Modul und wird in der Applikation als Jar-Datei eingebunden. Der Flow besteht nur aus der Seite forgotPassword.xhtml , die im Verzeichnis /META-INF/flows/forgotPassword abgelegt ist. Die Definition des Flows befindet sich in der Konfigurationsdatei /META-INF/faces-config.xml .
Listing Definition von Flow forgotPassword zeigt die Definition des Flows mit dem eingehenden Parameter. Der Wert des übergebenen Parameters wird beim Starten des Flows im Flow-Scope unter dem Schlüssel username abgelegt.
<flow-definition id="forgotPassword">
  <flow-return id="return">
    <from-outcome>forgotPassword-return</from-outcome>
  </flow-return>
  <inbound-parameter>
    <name>username</name>
    <value>#{flowScope.username}</value>
  </inbound-parameter>
</flow-definition>