Vous n'êtes pas connecté. Connexion
|
|
Accueil > Intranet Michel Buffa > Cours composants distribués pour l'entreprise > TP2 2015-2016 JSF2
TP2 2015-2016 JSF2De $1Table des matières
IntroductionDans cette séance :
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 suivante (templating) est donnée vers la fin de ce TP. Objectifs de cette partie :
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 d'un projet de type Web Application, activation de CDI
Vous êtes prêts à travailler... Exemple 1 : analyse d'un post tout simpleNous allons étudier une application qui contient 2 pages JSF qui se référencent :
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>formulaire_1</title> </h:head> <h:body> <h1>Application>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 <?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>affichage_1</title> </h:head> <h:body> <h1>Application>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 <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") : 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 #{bean.nombresSuivants} ...correspond encore à un accès à une propriété, la propriété " Exécutez cet exemple :
ATTENTION, si le message d'erreur: <?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 "?
Pour tester, lancez l'application et, à la main, tapez le bon URL pour faire afficher la page JSF formulaire_2.xhtml:
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 allons maintenant voir une méthode un élégante pour arriver à nos fins tout en résolvant le problème du bookmark/marque page. Exemple 3 : utilisation des paramètres de vueDans 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 : 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) :
Ainsi la page qui affiche les nombres sera bookmarkables/ajoutable dans le marque page. Remarque : 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>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&includeViewParams=true"/> </h:form> </h:body> </html> Dans 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>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. Est-ce possible de garder un marque-page pour garder, par exemple, les 5 nombres qui suivent le nombre 34 ? 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 : Templating: mise en place de templates de présentationRessources : 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 : 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 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 et la page d'affichage correspondante (qui utilise un modèle pour l'affichage, qui lui aussi utilise le modèle par défaut) : 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 :
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><ui:insert name="complementTitreEtH1"/>#{numEx}</title> </h:head> <h:body> <div id="top" class="top"> <h1>Application><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:
Maintenant, nous allons utiliser ce template par défaut :
Pour la page Pour les autre templates créez deux nouveaux Facelet Templates Clients, nommés
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
<ui:param name="numEx" value="X"/> Mais attention, regardez bien: on est obligé de calculer la valeur de l'attribut public String actionString(String base, String numEx, String query); où:
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 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 à vous de jouer !!! Correction des exercices précédents
Mots clés:
|
Powered by MindTouch Deki Open Source Edition v.8.08 |