TP JSF 2 2014-2015

De $1

Introduction

Dans cette séance :

  • Exercices pour comprendre le modèle de navigation de JSF et le fonctionnement de plusieurs "scopes".

Ressources :

En plus du support de cours JSF disponible sur la page du cours, je vous propose les ressources suivantes :

Etude du modèle de navigation PRG (Post Redirect Get)

NOTE : un projet contenant les corrections de cette section (navigation) + de la section suvante (templating) est donnée vers la fin de ce TP.

Objectifs de cette partie :

  1. Présenter les problèmes du POST utilisé par défaut par JSF, vus dans le TP1,
  2. Présenter le modèle PRG qui permet d'éviter la double soumission des formulaires et de pouvoir garder un marque-page des pages affichées.
  3. Introduction au templating avec Facelets

Important : dans ce TP vous utiliserez des backing bean de portée "Requête". Il faut toujours essayer de limiter au maximum la portée des beans pour éviter l'encombrement de la mémoire (ce qui peut être un problème pour les sites Web très fréquentés). Evidemment dans certains cas, les portées "Vue", "Conversation", ou même "Session" sont plus indiquées (par ex la portée "Session" pour un backing bean qui gère les connexions par login/password).

Création et initialisation du projet

1 - Cette fois-ci vous créerez un nouveau projet de type Web Application en choisissant "Java Web", puis "Web Application" (pas "Java EE", puis "Entreprise Application" comme dans le TP 1).

2 - N'oubliez pas de cocher le Framework "Java Server Faces" lors de la création du projet. Pas d'utilisation de PrimeFaces pour ce TP.

3 - Ajoutez dans le projet un fichier beans.xml (click droit / new / Context and dependency injection / fichier beans.xml), sans ce fichier certaines injections de code ne fonctionnent pas.

4 - ATTENTION : Netbeans a "oublié" d'inclure la librairie permettant certaines injections de code, nécessaire aux projets utilisant le scope "SessionScoped", vous ajouterez donc à votre projet, manuellement, la librairie : cdi-api.jar

  • Allez dans le menu Tools / Outil de Netbeans, puis choisissez "Libraries"
  • Faites "Nouvelle librairie / New Library...", et donnez comme nom "CDI 1.2". Clic sur "Add JAAR/Foler..." et indiquez le fichier cdi-api.jar qui se trouve dans glassfish/modules dans le répertoire d'installation de glassfish (sous Windows, il peut être, par exemple, dans C:\Program Files\glassfish-4.1\glassfish\modules). Voilà, dorénavant vous pourrez utiliser cette librairie avec vos projets.
  • Dans le nouveau projet, clic droit sur "Libraries" (dans la fenêtre Projects à gauche) et choisissez "Add Library..." pour ajouter la nouvelle librairie "CDI 1.2".

Vous êtes prêts à travailler...

Exemple 1 : analyse d'un post tout simple

Nous allons étudier une application qui contient 2 pages JSF qui se référencent :

  • formulaire_1.xhtml qui contient un formulaire avec champ de saisie d'un entier ; la soumission du formulaire passe la main à affichage_1.xhtml,
  • affichage_1.xhtml qui affiche les 5 nombres qui suivent le nombre saisi et qui contient un lien pour revenir vers la page fomulaire_1.html

Utilisez simplement le menu "new/JSF Page" pour créer les pages. 

Voici le code des deux pages en question :

formulaire_1.xhtml 

<?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:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:head>
        <title>Application&gt;formulaire_1</title>
    </h:head>
    <h:body>

     <h1>Application&gt;formulaire_1</h1>

     <h:form>
        <h:outputLabel value="Entrez un nombre" for="nombre"/>
        <h:inputText id="nombre" value="#{bean.nombre}"/>
        <h:commandButton value="Valider" action="affichage_1"/>
      </h:form>

    </h:body>
</html>

affichage_1.xhtml

Vous comprenez à quoi sert l'attribut varstatus de <ui:repeat>, utilisé dans l'expression EL #{! status.last ? ', ' : ''} ?

<?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:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title>Application&gt;affichage_1</title>
    </h:head>

    <h:body>
        <h1>Application&gt;affichage_1</h1>
        Les nombres : <br/>
        <ui:repeat value="#{bean.nombresSuivants}" var="n" varStatus="status">
            #{n + 1}#{! status.last ? ', ' : ''}
        </ui:repeat>
        <h:form>
        <h:commandLink action="formulaire_1" value="Saisir un autre nombre"/>
        </h:form>
    </h:body>
</html>

Ces pages utilisent un Backing Bean (son nom est "bean") pour stocker la propriété correspondant au champs de formulaire "nombre". C'est la ligne suivante dans formulaire_1.html qui correspond à la propriété :

<h:inputText id="nombre" value="#{bean.nombre}"/>

Voici donc le code du backing bean (que nous avons, dans cet exemple, mis dans le package "jsf"). Pour l'ajouter au projet utilisez le menu "nouveau / jsf managed bean".

Notez bien les import pour "Named" et "RequestScoped". Pour la plupart des "scopes", à par le "ViewScoped" vu lors du TP1, nous utiliserons ces "chemins d'import". Si lorsque vous créez par vous-même un "jsf managed bean" vous avez @ManagedBean au lieu de @Named, c'est qu'il vous manque le fichier beans.xml dans WEB-INF, ajoutez le alors au projet pour ne plus être embêté.

Bean.java :

package jsf;

import java.util.ArrayList;
import java.util.List;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;

@Named(value = "bean")
@RequestScoped
public class Bean {

    private int nombre;

    public int getNombre() {
        return nombre;
    }

    public void setNombre(int nombre) {
        this.nombre = nombre;
    }

    public List<Integer> getNombresSuivants() {
        int nb = 5;
        List<Integer> t = new ArrayList<>(nb);
        for (int i = nombre; i < nombre + nb; i++) {
            t.add(i);
        }
        return t;
    }
}

Regardez déjà comment cet exemple s'articule. Notez dans les pages JSF l'utilisation de <ui:repeat ... /> qui correspond au tag JSTL vu l'an dernier <c:foreach... />. Notez que la collection sur laquelle on itère, donnée par :

#{bean.nombresSuivants}

...correspond encore à un accès à une propriété, la propriété "nombresSuivants" qui existe puisqu'une méthode getNombresSuivants() existe. Rappelons que ce sont les getters et setters qui définissent une propriété et non pas l'existence d'une variable d'instance dans la classe. En particulier ici on a pas de variable d'instance.

Exécutez cet exemple :

  • Testez en entrant autre chose qu'un nombre entier (un message doit s'afficher si vous avez bien écrit votre application) ; est-ce que vous êtes certain que ce message sera toujours affiché si vous passez en mode "Production" ? Testez... et, si ça n'est pas le cas modifiez la page pour faire afficher le message.
  • Essayez de faire afficher au début dans la zone de saisie le nombre entré précédemment quand vous saisissez un nouveau nombre.

ATTENTION, si le message d'erreur: /formulaire_1.xhtml @17,58 value="#{bean.nombre}": Target Unreachable, identifier 'bean' resolved to null apparaît, c'est surement qu'il vous manque beans.xml. On vous l'a dit, ce fichier est nécessaire à tous les projets "JSF" modernes. C'est une bonne pratique de l'avoir par défaut dans tous les projets. Même si ce n'est pas ce que NetBeans propose par défaut.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Remarquez-vous des anomalies quant à l'URL affiché par le navigateur ?

Rechargez la page qui affiche les 5 nombres. Que fait le navigateur ? Expliquez.

Est-ce possible de mettre un bookmark sur la page affichage pour un certain nombre. Par exemple 5 ; la page affichage affichera les nombres 6 à 10 qui sont censés représenter une information importante sur le nombre 5...

Et oui, cela ne marche pas ! Ce TP étudie un modèle, appelé PRG, pour ne plus avoir ce genre de problème.

Exemple 2 : utilisation de la redirection (modèle PRG)

Dans cet exemple nous allons faire une implémentation du modèle PRG vu en cours : la page résultat est affiché par une redirection (GET) après le POST.

On va commencer par régler le problème de l'URL. Pour cela, on va changer le comportement par défaut de JSF qui utilise le "forward" pour faire afficher les pages JSF (voir cours). Pour utiliser une redirection il suffit d'ajouter aux URLs dans les pages JSF "faces-redirect=true", regardez le passage du cours à ce sujet.

  • Créez deux nouvelles pages JSF, appelez-les formulaire_2.xhtml et affichage_2.xhtml.
  • Recopiez le contenu des pages formulaire.xhtml et affichage.xhtml dans les nouvelles pages, en modifiant les 1 en 2 là où c'est pertinent, ainsi vous pourrez comparer.
  • Modifiez ces pages pour que JSF utilise une redirection à la place d'un forward : lorsqu'on va de formulaire_2.xhtml à affichage_2.xhtml et vice-versa.

Pour tester, lancez l'application et, à la main, tapez le bon URL pour faire afficher la page JSF formulaire_2.xhtml (note vous pouvez aussi éditer la page index.html et vous faire un petit menu avec des liens vers les différentes pages formulaire_1.xhtml, formulaire_2.xhtml etc...).

Est-ce que les URL sont corrects maintenant ?

Rechargez la page qui affiche les nombres. Avez-vous toujours le problème de l'exercice précédent ?

Est-ce que les bons nombres sont bien affichés ? Expliquez.  

Nous avons donc réglé le problème des URL et de la double soumission du formulaire mais l'application ne fonctionne plus pour l'affichage des bons nombres. Nous allons maintenant voir une méthode élégante pour arriver à nos fins et pouvoir conserver une page d'affichage dans un bookmark, tout en conservant les bons URL et sans avoir la double soumission du formulaire. 

Exemple 3 : utilisation des paramètres de vue

Dans cet exercice nous allons utiliser une toute autre façon pour résoudre le problème du passage de la valeur tout en permettant l'affichage synchronisé de l'URL dans le navigateur.

Nous allons aussi régler le dernier problème : il sera possible de conserver les informations dans un marque-page du navigateur.

Reprenez le code de l'exercice sur la redirection. Mettez le suffixe 3 aux pages utilisées par cet exercice : formulaire_3.xhtml et affichage_3.xhtml

Comment passer la valeur de la propriété nombre d'une instance du bean à une autre (n'oubliez pas que la portée du bean est la requête et ce sont donc 2 instances différentes de la classe Bean qui sont utilisées par les 2 pages JSF) ? Nous allons utiliser un paramètre de vue (comme dans le TP 1) :

  • Dans la page affichage_3.xhtml, ajoutez un "paramètre de vue" nommé "nb" (lisez le listing ci-dessous). La valeur du paramètre "nb" de la requête GET sera ainsi conservé dans la propriété "nombre" du bean. Ceci se fait à l'aide des tags <f:metadata> et <f:viewParam ... />.
  • Dans la page formulaire_3.xhtml ajoutez un paramètre (includeViewParams=true) dans l'action du formulaire pour indiquer que vous voulez que les paramètres de vue de la page de destination soient des paramètres de la requête GET ajoutés à l'URL. 

Ainsi la page qui affiche les nombres sera bookmarkables/ajoutable dans le marque page.

Remarque : includeViewParams simplifie les choses lorsque les paramètres sont nombreux ; pour ce cas, avec un seul paramètre, vous auriez aussi pu ajouter plus simplement le passage du paramètre nb en appelant une méthode action du bean (une méthode est obligatoire car il est interdit de mélanger dans l'attribut action une destination avec la valeur d'un paramètre) qui retourne la valeur "affichage_3?faces-redirect=true&amp;nb=" + nombre 

formulaire_3.xhtml :

<?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:h="http://xmlns.jcp.org/jsf/html">

    <h:head>
        <title>Application&gt;formulaire_3</title>
    </h:head>
    <h:body>

     <h1>Applicationformulaire_3</h1>

     <h:form>
        <h:outputLabel value="Entrez un nombre" for="nombre"/>
        <h:inputText id="nombre" value="#{bean.nombre}"/>
        <h:commandButton value="Valider" action="affichage_3?faces-redirect=true&amp;includeViewParams=true"/>
      </h:form>
    </h:body>
</html>

Dans affichage_3.xhtml qui affiche les 5 nombres on ajoutera un paramètre de vue pour récupérer le nombre saisi par l'utilisateur :

affichage_3.xhtml :

<?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:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <f:metadata>
        <f:viewParam name="nb" value="#{bean.nombre}"/>
    </f:metadata>

    <h:head>
        <title>Applicationaffichage_3</title>
    </h:head>
    <h:body>

     <h1>Application&gt;affichage_3</h1>

        Les nombres : <br/>
        <ui:repeat value="#{bean.nombresSuivants}" var="n" varStatus="status">
            #{n + 1}#{! status.last ? ', ' : ''}
        </ui:repeat>
        <h:form>
        <h:commandLink action="formulaire_3?faces-redirect=true" value="Saisir un autre nombre"/>
        </h:form>
    </h:body>     
</html>

Testez votre application. Etudiez en particulier les URL affichés par le navigateur. Si les nombres affichés sont toujours 1, 2, 3, 4, 5 c'est sans doute que vous avez une version de Mojarra antérieure à la version 2.2.2 (bug déjà vu dans le TP 1). Vous savez comment résoudre ce problème : dans la page affichage_3.xhtml, remplacez xmlns.jcp.org par java.sun.com dans l'espace de noms de f (xmlns:f="http://xmlns.jcp.org/jsf/core").

Est-ce possible de garder un marque-page pour garder, par exemple, les 5 nombres qui suivent le nombre 34 ? Testez.

Exemple 4 : idem mais...

Modification très simple de l'exercice 3: Reprenez le code de l'exercice 3, mettez le suffixe 4 aux pages utilisées par cet exercice : formulaire_4.xhtml et affichage_4.xhtml
Montrez que vous avez compris: ajoutez simplement le fait que le nombre précédemment saisi apparaisse par défaut dans le formulaire lorsqu'on veut saisir un autre nombre !
 

Templating: mise en place de templates de présentation

Ressources http://www.coreservlets.com/JSF-Tutorial/jsf2/#Templating ce site contient tout un ensemble de cours sur JSF. Mais le PDF sur le templating, rien que la page 8, montre le principe général des includes.

Prenez le temps de remarquer dans les pages jsf tout le code qui se répète... dans les titres et les h1, et dans la structure des pages... De plus, j'imagine que la plupart d'entre vous doit encore modifier les urls à la main pour essayer une page formulaire_X au démarrage de l'application.

Nous allons maintenant mettre en place des templates de présentation, pour alléger tout ce code et rendre la navigation pratique.

Les templates sont des "pages types" dans lesquelles ont peut définir des zones que l'on pourra remplacer dans les pages qui se réfèrent à ces pages types. En outre, dans un modèle on peut définir des paramètres (en gros, des variables qui pourront être remplacées par des valeurs, spécifiées dans les pages qui utilisent ces modèles). Et enfin, un modèle peut lui même réutiliser un autre modèle, l'enrichir etc.

Voici ce que l'on désire obtenir :

snap.jpg

C'est une page avec une zone en haut, qui contient un titre (ici la description de la page affichée dans la partie centrale, dans une pseudo hiérarchie application/menu du tp2). La page qui utilise le modèle est ici index.xhtml comme l'indique l'URL. Dans cette page on a indiqué que l'on utilisé le modèle + on a indiqué que la variable qui décrivait le contenu valait Application/Menu du TP2.

Le même modèle va être repris par deux autres modèles : un pour les formulaires de saisie des nombres, l'autre par les pages qui affichent les nombres qui suivent le nombre entré par l'utilisateur.

Exemples de résultats, ici la page de saisie du nombre du premier exercice (cette page formulaire_1.xhtml utilise le modèle de formulaire, qui utilise le modèle par défaut) :

Snapt1.jpg

et la page d'affichage correspondante (qui utilise un modèle pour l'affichage, qui lui aussi utilise le modèle par défaut) :

Snapt3.jpg

etc... vous avez compris le principe, normalement on va pouvoir factoriser au maximum le code et le nombre de lignes dans les pages .xhtml devrait être réduit en conséquence (en plus d'avoir une présentation plus jolie).

Comment arriver à ce résultat ?

Travail à faire, choses à remarquer :

  1. Commencez par créer une page de type Facelets Template (clic droit sur le projet, puis New/Java Server Faces/Facelet Template), que vous nommerez template_default. Choisissez un layout avec header et barre latérale pour la navigation.
  2. Remarquez la création automatique dans le projet d'un répertoire "resources" qui contient deux feuilles de style css par défaut. Ce répertoire est important car lorsqu'un template ou une page JSF va référencer une feuille de style avec le tag <h:outputStylesheet library="css" name="default.css"/>, la "librairie" css doit être située sous le répertoire "resources".
  3. On n'utilisera pas un classique <link href="./resources/css/default.css" rel="stylesheet" type="text/css" /> de HTML pour inclure une feuille de style car ici les liens vont être "calculés" en fonction de l'URL de la page qui va utiliser le template, et qui peut être située ailleurs.Voir lignes 8 et 9 du code de template_default.xhtml, ci-dessous.
  4. De même, dans le menu de gauche on a des liens vers d'autres pages JSF du projet (formulaire_1.xhtml etc.), on n'utilisera pas un classque <a href="formulaire_1.xhtml"/>... de HTML mais un <h:link outcome="formulaire_1.xhtml" value="formulaire_1"/> qui va lui aussi "calculer" le lien vers la page formulaire_1.xhtml en fonction de la position de la page qui inclut le template. Voir lignes 22 et suivantes du code de template_default.xhtml, ci-dessous.

Copiez-donc ce code pour le template par défaut :

template_default.xhtml

<?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://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <h:outputStylesheet library="css" name="default.css"/>  
        <h:outputStylesheet library="css" name="cssLayout.css"/> 
        <title>Application&gt;<ui:insert name="complementTitreEtH1"/>#{numEx}</title>
    </h:head>

    <h:body>

        <div id="top" class="top">
             <h1>Application&gt;<ui:insert name="complementTitreEtH1"/>#{numEx}</h1>
        </div>

        <div>
            <div id="left">
                <ul>
                    <li><h:link outcome="index.xhtml" value="accueil"/></li>  
                    <li><h:link outcome="formulaire_1.xhtml" value="formulaire_1"/></li>  
                    <li><h:link outcome="formulaire_2.xhtml" value="formulaire_2"/></li>  
                    <li><h:link outcome="formulaire_3.xhtml" value="formulaire_3"/></li>  
                    <li><h:link outcome="formulaire_4.xhtml" value="formulaire_4"/></li>  
                </ul>
            </div>

            <div id="content" class="left_content">
                <ui:insert name="content">Content</ui:insert>
            </div>
        </div>
    </h:body>

</html>
 

Vous pouvez voir le rendu de ce template en cliquant droit dans le code / view.

Ce template définit trois espaces libres que ses clients pourront spécifier:

  • le champs <ui:insert name="complementTitreEtH1"/> avec aucun contenu par défaut;
  • le paramètre #{numEx}
  • le champs <ui:insert name="content">Content</ui:insert> avec pour contenu par défaut: Content

Maintenant, nous allons utiliser ce template par défaut :

  • directement pour la page index.xhtml
  • pour créer deux nouveaux templates: template_formulaire.xhtml et template_affichage.xhtml.

Pour la page index.xhtml, supprimez l'actuelle page index.xhtml créez une nouvelle page Facelet Template Client (clic droit, New/Java Server Faces/Facelet Template Client), nommée index, qui utilise le template qu'on vient juste de créer, et de type "generate root tag html". remplacez le slot nommé complementTitreEtH1 (il ne doit y en avoir qu'un du même nom !) par "Accueil" ; et remplacez le slot nommé content par une dissertation sur le bonheur que procure la simplicité de programmer avec les facelets.

Pour les autre templates créez deux nouveaux Facelet Templates Clients, nommés template_formulaire et template_affichage, qui utilisent le template "template_default", et de type generate root tag ui:composition.  Le contenu de ces pages sont les suivants:

 

template_formulaire.xhtml

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

    <ui:define name="complementTitreEtH1">formulaire_</ui:define>

    <ui:define name="content">
        <h:form>
            <h:outputLabel value="Entrez un nombre" for="nombre"/>
            <h:inputText id="nombre" value="#{bean.nombre}"/>
            <h:commandButton value="Valider" action="#{bean.actionString('affichage', numEx, query)}"/>
          </h:form>
    </ui:define>

</ui:composition>

 

template_affichage.xhtml

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

    <ui:define name="complementTitreEtH1">affichage_</ui:define>

    <ui:define name="content">
        Les nombres : <br/>
        <ui:repeat value="#{bean.nombresSuivants}" var="n">
            #{n + 1},
        </ui:repeat>
        <h:form>
            <h:commandLink value="Saisir un autre nombre" action="#{bean.actionString('formulaire', numEx, query)}"/>
        </h:form>
    </ui:define>

</ui:composition>

 
 

Ces deux templates spécifient les champs complementTitreEtH1 et content, donc les pages formulaire_X.xhtml et affichage_X.xhtml n'auront à priori que le paramètre numEx à spécifier, et on fait ça de la manière suivante: 

<ui:param name="numEx" value="2"/>

<ui:param name="numEx" value="X"/>

Mais attention, regardez bien: on est obligé de calculer la valeur de l'attribut action du commandLink et du commandButton ! On doit donc passer par le backing bean de l'application: Bean. Vous implémenterez donc la méthode actionString dans le backingbean, qui doit avoir pour signature:

public String actionString(String base, String numEx, String query);

où:

  • base est spécifié dans les templates template_formulaire.xhtml et template_affichage.xhtml et prendra les valeurs 'affichage' ou 'formulaire' ;
  • numEx est le numéro de l'exercice et est spécifié dans les pages formulaire_X.xhtml et affichage_X.xhtml ;
  • query est un nouveau paramètre qui correspond à tout ce qui est après le ? dans l'URL qu'on veut appeler (faces-redirect=true par exemple...). Il doit être spécifié de la même manière que numEx  dans les pages formulaire_X.xhtml et affichage_X.xhtml  

Travail à faire:

Maintenant si vous avez bien tout suivi jusque là, et que vous n'avez pas perdu trop de temps avec dissertation sur le bonheur que procure la simplicité de programmer avec les facelets, vous n'avez plus qu'à écrire la méthode actionString dans le backingBean, et vous pourrez réécrire les pages formulaire_X.xhtml comme clientes du template template_formulaire, et les pages affichage_X.xhtml comme clientes du template template_affichage. Si NetBeans dit que template_formulaire.xhtml n'est pas un template, le plus simple est de désigner template_default comme template et ensuite d'aller directement dans le fichier pour changer le template. Ensuite, copiez les pages d'affichage et de formulaire et modifiez-les pour en faire les versions suivantes.

Vous pourrez constater à quel point les pages sont devenues super simples !!!

Pour les numeros d'exercices 3 et 4, n'oubliez pas d'ajouter les lignes 

<f:metadata>
    <f:viewParam name="nombre" value="#{bean.nombre}"/>
</f:metadata>

à l'intérieur du tag ui:composition lorsque c'est nécessaire !

          à vous de jouer !!!

A FAIRE : comprendre où dans le TP1 on fait des POST, où on fait des GET ?