Aide pour Faces Flow

Création du flot

Le plus simple est de réunir toutes les pages du flot dans un répertoire de la racine du site. Toutes les pages du flot ne sont pas obligatoirement dans un répertoire mais, si on le fait, on profite de conventions qui facilitent la définition et la configuration du flot.

On va appeler ce flot flotTransfert et le répertoire s'appelera donc flotTransfert.

Pour créer le répertoire, clic droit dans la racine des pages Web ("Web Pages") puis New > Other > Other > Folder et tapez le nom flotTransfert.

Template pour les pages du flot

Utilisez un template pour ce flot avec (vous pouvez choisir une autre disposition si vous voulez) :

C'est une occasion de voir que les templates peuvent être emboîtés les uns dans les autres (vous le savez déjà si vous avez fait la partie optionnelle du TP sur les templates). Ce template est à l'intérieur du template principal utilisé dans tout le projet. Il sera donc un client du template principal tout en contenant des <ui:insert> pour la barre de navigation et pour le contenu de chaque page du flot.

Créez donc un client du template principal en ne cochant que top et content (tout le reste utilise le contenu par défaut du template principal). Appelez-le "templateFlot" et mettez-le dans le répertoire WEB-INF, comme le template principal.

Dans le contenu prenez exemple sur le contenu du template principal pour créer 2 <div> pour la barre de navigation et pour le contenu des pages du flot, avec des <ui:insert>. Vous obtiendrez par exemple ce code :

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">

  <body>

    <ui:composition template="/WEB-INF/templates/template.xhtml">

      <ui:define name="top">
        Transfert d'argent entre 2 comptes, version avec flot
      </ui:define>

      <ui:define name="content">
        <div id="barreNavigation">
          <ui:insert name="barreNavigation"/>
          <br/><br/>
          <h:form>
            <h:button outcome="sortieFlot" value="Annuler le transfert"/>
          </h:form>
        </div>
        <div id="contenuPage">
          <ui:insert name="contenuPage"/>
        </div>
      </ui:define>

    </ui:composition>

  </body>
</html>
Pour cet exemple la sortie du flot est effectuée en allant à la page qui liste tous les comptes comme on va le voir dans la section suivante.

Configuration du flot

Par convention la définition du flot se trouve dans le fichier <nom du flot>-flow.xml ; pour notre cas ce sera flotTransfert-flow.xml.

Ce fichier est indispensable mais il pourrait être vide si on suivait toutes les conventions sur les flots.

Dans notre cas on se contentera de définir la page de sortie du flot. Les autres informations obligatoires pour la configuration d'un flot sont le id du flot (servira pour la navigation vers le flot) et la page d'entrée dans le flot (elle est définie par convention comme on le verra dans la section suivante).

Voici le contenu de ce fichier de configuration (pour JSF 2.3) :

<faces-config version="2.3" 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_3.xsd">
  <flow-definition id="flotTransfert">
    <flow-return id="sortieFlot">
      <from-outcome>/listeComptes</from-outcome>
    </flow-return> 
  </flow-definition> 
</faces-config>
Ici la page de sortie sera la liste de tous les comptes. On y arrivera depuis le flot par une navigation en utilisant l'id "sortieFlot" (voir template ci-dessus). Il peut y avoir plusieurs pages de sortie d'un flot (mais une seule page d'entrée dans le flot).

Les 5 pages du flot

Les 5 pages du flot sont décrites dans l'énoncé du TP.

Page d'entrée dans le flot

Comme une méthode, un flot a un point d'entrée et peut avoir plusieurs points de sortie.

Si on utilise les conventions pour les flots, la page d'arrivée a le même nom que le flot (donc que le répertoire qui contient le flot). La page s'appelle donc flotTransfert.xhtml. C'est un client du template du flot.

Mettez dans le contenu de cette page une description de ce que l'utilisateur devra faire. Un lien envoie vers la page qui permet à l'utilisateur de désigner le compte source du transfert (celui à qui on va retirer de l'argent). Si vous voulez vous pouvez aussi y ajouter un petit menu pour aller directement à une des pages du flot. Pour les liens utilisez des requêtes GET (<h:button> ou <h:link>) puisqu'aucune information saisie par l'utilisateur ne doit être enregistrée sur le serveur.

Dans la barre de navigation vous pouvez mettre un titre de niveau <h2>, par exemple <h2>Explications</h2> et un lien vers la page suivante (avec <h:link>).

Une petite difficulté : quand on est déjà dans le flot, l'id du flot n'est pas connu. L'id est utilisé dans le menu du template (pour démarrer le flot) et va donc générer une erreur quand l'utilisateur sera déjà dans le flot. Plusieurs solutions pour contourner ce problème. La première est de désactiver le lien qui contient l'id du flot quand l'utilisateur est déjà dans le flot. Il est aussi possible d'ajouter une page hors du flot qui contient un lien vers le flot et de pointer cette page dans le menu pour entrer dans le flot. La correction contient la première solution.

Autres pages du flot

Utilisez des requêtes POST (avec redirection pour avoir les bons URL) pour enregistrer dans un backing bean les informations données par l'utilisateur. Lorsque l'utilisateur confirme les informations dans la dernière page du flot, il faut lancer l'enregistrement dans la base de données comme ça a déjà été fait avec les versions plus simples du transfert. Il faut ensuite sortir du flot, soit directement à la fin de la méthode qui enregistre les informations (attention, une redirection ne marche pas), soit par un bouton ou lien explicite pour sortir du flot (par une requête GET puisque toutes les informations ont déjà été enregistrées).

Dans la barre de navigation de chaque page du flot vous ajoutez un titre pour que l'utilisateur sache bien ou il est, et des liens qui pemettent de revenir à la page précédente ou de passer à la page suivant, ou d'autres liens ou informations qui vous semblent utiles pour l'utilisation du flot.

Backing bean

Évidemment toutes les pages utiliseront un même backing bean dans lequel les informations données par l'utilisateur seront enregistrées.

Ce backing bean contient toutes les propriétés et méthodes utiles au flot et en particulier l'enregistrement final du transfert d'argent.

Ce backing bean doit avoir la portée "flot" et donc être annoté par (vous devez donner le nom du flot pour le paramètre de @FlowScoped) :

@Named
@FlowScoped("flotTransfert")

La classe doit implémenter Serializable comme pour toutes les portées "longues".

Pour choisir la source et la destination du transfert

PrimeFaces offre plusieurs facilités pour sélectionner une ligne d'une dataTable et pour utiliser ensuite les informations contenues dans cette ligne.

Pour ce cas utilisez par exemple la méthode "RadioButton" du showcase. L'utilisateur cochera le bouton radio de la ligne qui affiche les informations sur le compte qu'il veut sélectionner.

Navigation vers, dans et hors du flot

Les flots s’utilisent sans problème si la navigation n’utilise que des requêtes POST sans redirection.

On connait les problèmes de ces requêtes POST (voir cours sur « PRG »). Si on veut utiliser des requêtes GET ou des redirections après les requêtes POST il faut bien lire ce qui suit sinon des erreurs risquent de survenir si l’utilisateur fait des manipulations non prévues (qu’il faut prendre en compte si on veut une application robuste qui résistent aux mauvaises manipulations de l’utilisateur).

L'entrée dans le flot doit se faire uniquement en passant par la page d'entrée du flot (définie par convention, dans le fichier de définition ou par programmation Java). On peut y aller par une requête POST ou GET. On ne peut pas aller directement dans une des pages du flot sans passer par la page d'entrée du flot.

La sortie du flot peut se faire de 2 façons :

La navigation entre les pages du flot peut se faire comme pour des pages ordinaires en dehors d'un flot (requêtes de type quelconque).