Page Home (contact) Retour TPs
Découvrir JSF par des exemples de code que vous allez étudier et modifier.
Remarque générale pour la suite : si ça ne marche pas comme vous l'espérez, n'oubliez de regarder les logs de GlassFish (en bas, sous "Output"). Avant chaque exécution, vous pouvez effacer les précédents affichages par clic droit sur la fenêtre des logs et Clear (ou par Ctrl L).
Autre remarque : les choses commencent à se compliquer et parfois GlassFish se perd un peu. Si vous voyez des erreurs étranges du genre
"Avertissement: java.lang.Exception: WEB0113: Virtual server [server] already has a web module [Employes] loaded at [/Employes]; therefore web module [Employes] cannot be loaded at this context path on this virtual server. "
vous pouvez arrêter GlassFish et le redémarrer. C'est souvent suffisant pour remettre les choses en ordre.
Parfois, c'est NetBeans qui se perd. Faire un clean du projet peut arranger les choses (à faire avant de redémarrer GlassFish car c'est plus rapide et ça peut suffire).
Objectif de cet exercice et du suivant : apprendre à ajouter des liens ou des boutons pour se déplacer dans une autre page. Avantages et inconvénients de chaque solution.
Créez un nouveau projet NetBeans "Navigation" de type Java Web. IMPORTANT : dans la dernière page "Frameworks" du wizard pour la création du projet, cochez "JavaServer Faces".
Une page index.xhtml a été créée automatiquement.
Étudiez le fichier web.xml qui a été créé, en particulier la page "welcome" et la définition du servlet "Faces Servlet" qui va traiter toutes les pages JSF, c'est-à-dire les pages dont l'URL commencera par "/faces/" dans le contexte de l'application. Les pages welcome sont celles qui sont affichées (la première trouvée si plusieurs pages) si l'URL ne donne qu'un répertoire et pas une page précise, par exemple http://localhost/appli1/.
Créez une page page2.xhtml : clic droit sur le projet, New > JSF Page... Donnez page2 comme nom (pas page2.xhtml). Pour reconnaître la page, modifiez le titre et le corps de la page générée par NetBeans.
Dans index.xhtml, ajoutez des liens vers page2.xhtml. Utilisez les composants h:commandLink, h:link, h:outputLink, h:commandButton et h:button dans index.xhtml (ne mettez les composants dans un formulaire que si c'est nécessaire).
Lancez l'exécution du projet. Après un certain temps la page index.xhtml va s'afficher dans votre navigateur Web. Cliquez sur les différents liens. Quand page2.xhtml est affichée, comparez les URL affichés par le navigateur après une navigation par chacun des composants. Que remarquez-vous ? Sauriez-vous l'expliquer ?
Examinez les pages sources HTML générées par JSF pour voir comment les divers composants ont été traduits (une commande de votre navigateur permet de les afficher ; par exemple sous Google Chrome, Ctrl-U ou menu de droite Outils > Afficher la source).
Que remarque-t-on ?
Comparaisons et code HTML généré
index.xhtml
Ajoutez des redirections pour les composants qui déclenchent des requêtes POST. Que remarquez-vous pour les adresses affichées par le navigateur. Expliquez.
Vous allez reprendre le TP sur les EJB en utilisant JSF à la place des servlets.
Créez un nouveau projet NetBeans "employes" de type Java Web.
IMPORTANT :
Vérifiez que PrimeFaces a bien été ajoutée dans les librairies du projet et que le fichier beans.xml a bien été créé dans les fichiers de configuration (pour CDI).
Cette fois-ci vous allez utiliser les classes entités du cours sur JPA. Commencez par créer l'entité Departement
avec clic droit sur le projet, puis New > Entity Class.... Indiquez le paquetage ufe.entite
(il faudra aussi changer le source). Laissez cocher la case "Create Persistence Unit". Choisissez la source de données "employes" ; laissez la stratégie de génération des tables à "Create". Écrasez la définition créée par NetBeans avec celle de la classe entité du cours de JPA ; vous pouvez garder les méthodes equals, hascode et String générées par NetBeans. Créez ensuite les autres entités de la même façon ou en utilisant tout simplement l'entrée du menu "Java Class" (plus besoin de créer l'unité de persistance). Après avoir ajouté toutes les entités il ne devrait plus y avoir d'erreurs dans votre projet, sauf peut-être pour la propriété adresse de Client mais n'en tenez pas compte (il semble que NetBeans oublie qu'un attribut peut-être de type Embeddable).
Maintenant vous allez profiter d'un wizard NetBeans qui va créer en une seule fois les beans sessions pour gérer ces entités ainsi que les pages JSF pour faire les opérations "CRUD" de base sur les données liées aux entités que vous venez d'ajouter. Pour cela, clic droit sur le projet, New > "JSF Pages from Entity Classes". Il se peut que vous soyez obligé de passer par l'entrée Other puis choix JavaServer Faces pour trouver "JSF Pages from Entity Classes". Placez les beans session dans ufe.ejb, les classes JSF dans ufe.jsf et les pages JSF dans le répertoire employes. En prime vos pages JSF vont être internationalisées grâce au "Bundle" (laissez "/Bundle") ; vous comprendrez mieux quand vous étudierez le code généré.
Regardez tout le code qui a été généré :
employes
des pages Web, toutes les pages JSF qui vont vous permettre de lancer les opérations CRUD sur vos données. Malheureusement le code n'est pas adapté à PrimeFaces (un projet est en cours chez NetBeans et PrimeFaces pour avoir cette adaptation).template.xhtml
qui contient la "charte graphique" pour cette application. C'est une facilité offerte par JSF que vous n'avez pas eu le temps d'étudier en cours mais qui est très utile. Allez voir comment ce template est utilisé dans toutes les pages JSF de l'application (<ui:composition template="/template.xhtml">
).Bundle.properties
qui contient des chaînes de caractères en anglais utilisées dans les pages JSF ; vous allez créer un autre fichier pour franciser l'application dans l'exercice suivant.ejb
qui contient les façades EJB session pour chacune des entités. Ils se chargent des opérations CRUD pour l'entité qu'ils gèrent. Remarquez qu'ils contiennent une classe interne qui définit un convertisseur par défaut (attribut forClass
) cette entité.jsf
qui contient les backing beans pour épauler les pages JSF. Remarquez la portée "session" de ces beans ; ça n'est pas optimal mais c'est plus simple pour débuter. Chaque backing bean s'occupe des 4 pages List.xhtml
(affiche les données de la table), Edit.xhtml
(modifie une ligne de la table), Create.xhtml
(ajoute une nouvelle instance) et View.xhtml
(affiche les détails d'une seule ligne). Un sous-paquetage jsf.util
contient une classe abstraite pour faciliter la pagination des tables qui affichent les données et une classe qui contient diverses méthodes de classe utilisées par les backings beans. Chaque backing beans crée une instance d'une classe fille anonyme de la classe abstraite qu'elle conserve dans la variable d'instance pagination
.Vous devez absolument comprendre comment fonctionne ce code car il est souvent plus simple pour une nouvelle application d'utiliser ce wizard de NetBeans plutôt que de partir de rien. Mais le plus souvent vous aurez à reprendre ce code pour l'adapter à votre application.
Avant d'étudier en détails et de modifier le code, lancez l'exécution du projet pour mieux comprendre comment l'application fonctionne. Vous comprenez mieux pourquoi vous allez devoir modifier le code généré par NetBeans ? Par exemple, l'adresse des clients n'est pas affichée correctement.
Vous allez commencer par faire simple : enlevez la référence à PrimeFaces au début de la page "welcome".
Ensuite, modifiez le template pour faire afficher un titre de niveau 1 (<h1>
)au début de chaque page : "Gestion des personnes". Testez en faisant afficher plusieurs pages de l'application. Vous voyez comme c'est simple... D'autant plus que NetBeans offre des facilités pour créer de nouveaux templates et pour les utiliser dans des pages JSF (menus New > JavaServer Faces > Facelets Template et New > JavaServer Faces > Facelets Template Client).
Etudier le code généré par NetBeans. Vous avez déjà étudié les classes du paquetage ejb dans le TP sur les EJB. Dans ce TP étudiez plus particulièrement les pages JSF ainsi que les backing beans du paquetage jsf. Voyez comment les backing beans utilisent les EJB sessions, et comment ils sont utilisés par les pages JSF. N'essayez pas trop de comprendre la pagination qui est complexe. Etudiez comment le code permet de lancer la modification d'une ligne de la table des départements (méthode prepareEdit
du backing bean) en admettant que getRowData() renvoie bien le département qui correspond à la ligne sur lequel l'utilisateur a cliqué. Question 1 : à quoi sert return "Edit";
?
Question 2 : Lorsque l'utilisateur a modifié les données sur le département, comment les modifications sont-elles sauvegardées dans la base de données ?
Le fichier Bundle.properties correspond à la langue "par défaut", celle qui est choisie si aucun fichier n'existe pour les langues supportées par le navigateur.
Cet exercice suppose que votre navigateur est configuré pour la locale fr. Si ça n'est pas le cas, remplacez fr par votre locale. Par exemple, pour l'Egypte c'est eg à la place de fr (si je ne me trompe).
Vous allez ajouter un fichier pour le français : copier Bundle.properties
en un fichier Bundle_fr.properties
dans le même répertoire (c'est une convention de nommage utilisée par Java). Pour cela, Ctrl C sur le fichier puis clic sur le répertoire qui contient le fichier et Ctrl V. Changez ensuite le nom du fichier. Cliquez sur le fichier et vous voyez apparaître 3 colonnes :
Vous n'allez pas saisir toutes les valeurs, ça serait trop long. Vous allez modifier certaines valeurs qui apparaissent dans l'affichage des données pour les départements. Ces valeurs ont une clé qui commence par ListDepartement (NetBeans a bien choisi ses clés). Modifiez ces 10 valeurs. Au passage vous pouvez aussi modifier les valeurs pour l'anglais (Name à la place de Nom par exemple).
Il faut aussi modifier le fichier faces-config.xml
pour indiquer que l'application supporte le français :
<locale-config>
<default-locale>en</default-locale>
<supported-locale>fr</supported-locale>
</locale-config>
Ce qui indique ausi que si aucune des langues du navigateur n'est supportée par l'application, c'est l'anglais qui sera affiché.
Pour voir le résultat vous devez relancer l'application (un simple refresh de la page ne suffit pas).
Si vous savez changer la locale de votre navigateur, vous pouvez voir les 2 versions en anglais et dans l'autre langue.
Les entités ont déclaré que l'id doit être généré automatiquement. Il faut donc, soit ne pas afficher l'id, soit l'afficher mais ne pas permettre de le modifier (attribut readOnly="true"
). Pour la création, l'id ne doit pas apparaître.
De toute façon, comme les entités n'ont pas de setter pour id, toute tentative de modification ou de création d'une entité génère une erreur.
Modifiez le code de la page qui modifie un département pour que l'id ne soit pas modifiable. De même modifiez la page qui crée un nouveau département pour que l'id n'apparaisse pas. Testez.
Modifiez la page client/List.xhtml
pour faire afficher la ville dans laquelle les clients habitent (vous pourriez évidemment afficher de la même façon le reste de l'adresse) dans une colonne à la suite du nom des clients.
Maintenant que vous pouvez modifier les données sur un département, saisissez des caractères accentués pour voir s'ils s'affichent correctement. Si ça n'est pas le cas, créez un fichier de déploiement GlassFish (New > Other... > GlassFish > GlassFish Descriptor) et y ajouter <parameter-encoding default-charset="UTF-8" />
.
Gestion de l'id
Afficher la ville
glassfish-web.xml
Etudiez le TP sur la sécurité.
Protégez les pages qui permettent de créer de nouvelles entités en plaçant les pages qui permettent de créer les entités dans un répertoire protégé.