Présenter les problèmes du POST utilisé par défaut par JSF. 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.
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).
Écrivez une application qui contient 2 pages qui se référencent :
Testez en entrant autre chose qu'un nombre entier (un message doit s'afficher si vous avez bien écrit votre application).
Essayez de faire afficher au début dans la zone de saisie le nombre entré précédemment quand vous saisissez un nouveau nombre.
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 signet sur la page 2 pour un certain nombre. Par exemple 5 ; la page 2 affichera les nombres 6 à 10 qui sont censés représenter une information importante sur le nombre 5...
Ce TP étudie un modèle, appelé PRG, pour ne plus avoir ce genre de problème.
Implémentation du modèle PRG : 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). Modifiez ce que vous avez écrit à l'exercice précédent pour que JSF utilise une redirection à la place d'un forward pour afficher les pages index et page2. Appelez les nouvelles pages index_2 et page2_2.
Pour tester, lancez l'application et, à la main, tapez le bon URL pour faire afficher la page JSF index_2.
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.
Utilisez la mémoire flash pour faire afficher les bons nombres dans la 2ème page. Pour ne pas toucher aux pages déjà écrites, mettez le suffixe "_3" aux nouvelles pages que vous allez écrire.
Vous aurez besoin de modifier le backing bean. Pour ne pas perdre le précédent, créez un nouveau bean pour cet exercice.
Lorsque tout marche bien, pouvez-vous garder un marque-page pour faire à nouveau afficher les nombres qui suivent un certain nombre, par exemple 25 ? Testez pour voir (saisissez d'abord un autre nombre pour ne pas vous faire tromper par le cache du navigateur).
La mémoire flash peut être utile pour conserver facilement une information dans la requête suivante (et on peut même prolonger encore plus avec "keep" ; voir le cours).
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 (nous n'allons plus utiliser la mémoire flash dans cet exercice). Mettez le suffixe _4 aux pages utilisées par cet exercice.
Dans la page qui affiche les 5 nombres ajoutez un paramètre de vue pour récupérer le nombre saisi par l'utilisateur. Modifiez la page index_2 pour utiliser ce paramètre de vue.
Testez votre application. Etudiez en particulier les URL affichés par le navigateur. Est-ce possible de garder un marque-page pour garder, par exemple, les 5 nombres qui suivent le nombre 34 ?
Après avoir testé, ajoutez le fait que le nombre précédemment saisi apparaisse lorsque l'utilisateur saisit un autre nombre.
Dans cet exercice vous allez appliquer les procédés des exercices précédents. La situation se rapproche de celles que vous allez rencontrer dans des développements réels. Vous rendrez cet exercice à la fin de cette session de cours (à la fin de la semaine).
Dans les exercices précédents, un simple calcul permettait de récupérer les informations à afficher (les 5 nombres). Le plus souvent le paramètre passé dans la requête GET est un identificateur et il faut une ressource externe pour récupérer les informations à afficher dans la page résultat. Par exemple, le paramètre peut être une clé primaire et il faut accéder à une base de données pour récupérer les informations à afficher. C'est la situation que nous allons étudier dans cet exercice.
Voici, plus précisément, la situation que vous devez coder :
En fait vous allez écrire cette application en 2 étapes.
Dans Java DB, dans la base qui correspond à ressource GlassFish "jdbc/__default", créez une table PERSONNE.
Cette table a une clé primaire de type entier et 3 autres colonnes qui représentent le nom, la date de naissance d'une personne et le service où elle travaille (représenté par le nom du service). Ajoutez quelques personnes dans la table (avec au moins 2 services). Vous pouvez utiliser ce script SQL qui crée la table et y ajoute quelques employés ; pour l'exécuter le plus simple est de cliquer sur le bouton droit sur la base APP (dans l'onglet "Services"), de choisir "Execute Command..." et de coller le contenu de ce script dans la fenêtre qui s'est ouverte. Il suffit ensuite de cliquer sur l'icône la plus à gauche ("Run SQL").
Utilisez l'architecture apprise en cours pour une application Web JSF : le backing bean ne doit pas accéder directement à la base de données. Vous allez ajouter un bean session de type "façade" qui va jouer le rôle d'un DAO et qui sera utilisé par le backing bean pour récupérer les données. L'accès à la base de données se fera avec JPA , le bean session utilisera une classe entité pour accéder à la base de données.
Pour cela,
Votre projet contiendra 2 pages JSF : index.xhtml et detailsPersonne.xhtml. index permet à l'utilisateur de choisir la personne et detailsPersonne affiche les informations sur la personne.
Vous allez ajouter à la page résultat un listener de type preRenderView (donc un listener dont le code sera exécuté juste avant l'affichage de la page) qui va récupérer les informations dans la base de données pour les mettre dans une propriété du backing bean afin qu'elle puisse être affichées dans la page (la page référencera cette propriété pour afficher les données). Ce listener sera en fait une des méthodes du backing bean et utilisera le bean session pour récupérer les données dans la base.
Vous ajouterez dans le backing bean des méthodes qui seront utilisées pour remplir les listes déroulantes qui sont utilisées pour choisir la personne.
Utilisez Ajax pour refaire afficher uniquement la liste des personnes lorsqu'un service a été choisi.
Il y a ici une difficulté. En effet, la validation du choix dans une liste comprend la vérification que le choix appartient bien à la liste des choix présentés à l'utilisateur. Cette liste sera perdue au moment de la vérification si on reste avec une portée "requête". La façon la plus simple de s'en sortir est d'élargir la portée à la vue (ViewScope) mais cette portée n'existe qu'en JSF et pas avec CDI. Il faudra donc changer les annotations du backing bean :
@ManagedBean
@ViewScoped
au lieu de
@Named
@RequestScope
Voici quelques idées pour enrichir le dernier exercice :