JSF

publicité
http://www.labo-sun.com
[email protected]
JSF
FRAMEWORK WEB
Auteur : Olivier Smedile
Version n° 1.0 – 30 octobre 2006
Nombre de pages : 108
Ecole Supérieure d’Informatique de Paris
23. rue Château Landon 75010 – PARIS
www.supinfo.com
Table des matières
1.
INTRODUCTION.................................................................................................................................................6
1.1. LIMITATIONS DU COUPLE SERVLET/JSP .........................................................................................................6
1.2. PRESENTATION DE JAVA SERVER FACES ........................................................................................................6
1.2.1. Public visé ................................................................................................................................................7
1.3. EVOLUTION DE JSF ..........................................................................................................................................7
1.4. DIFFERENCE AVEC STRUTS ..............................................................................................................................8
2.
ARCHITECTURE DE JSF .................................................................................................................................9
2.1. INTEGRATION DE JSF DANS L’ARCHITECTURE D’UNE APPLICATION JEE....................................................10
2.2. CYCLE DE VIE .................................................................................................................................................11
2.2.1. Restauration de la vue ...........................................................................................................................12
2.2.2. Application des paramètres de la requête............................................................................................12
2.2.3. Validation des entrées utilisateurs........................................................................................................12
2.2.4. Mise à jour des valeurs du modèle .......................................................................................................12
2.2.5. Invocation de l’application ...................................................................................................................12
2.2.6. Rendu de la réponse ..............................................................................................................................12
3.
DEVELOPPER EN JSF.....................................................................................................................................13
3.1. INSTALLATION DE JSF ...................................................................................................................................13
3.2. ACTIVATION DE JSF.......................................................................................................................................14
3.3. PAGES JSF ......................................................................................................................................................15
3.4. RESSOURCES NECESSAIRES ............................................................................................................................15
3.5. DEPLOIEMENT ................................................................................................................................................16
3.5.1. JBoss.......................................................................................................................................................16
3.6. EXEMPLE ........................................................................................................................................................16
4.
LES BRIQUES DE BASE..................................................................................................................................21
4.1. LES COMPORTEMENTS....................................................................................................................................22
4.2. LES COMPOSANTS GENERIQUES .....................................................................................................................23
4.2.1. L’attribut id ............................................................................................................................................24
4.2.2. L’attribut renderer.................................................................................................................................24
4.2.3. L’attribut immediate ..............................................................................................................................24
4.3. LES COMPOSANTS HTML ..............................................................................................................................24
4.3.1. Style CSS ................................................................................................................................................24
4.3.2. Classe CSS .............................................................................................................................................25
4.3.3. Escape.....................................................................................................................................................25
4.3.4. Evénements JavaScript..........................................................................................................................25
4.4. LIAISON COMPOSANTS ET JAVABEANS .........................................................................................................25
4.4.1. Valeur .....................................................................................................................................................26
4.4.2. Instance ..................................................................................................................................................26
4.5. UNIFIED EXPRESSION LANGUAGE .................................................................................................................27
4.5.1. Variables ................................................................................................................................................27
4.5.2. Objets implicites ....................................................................................................................................28
4.5.3. Opérateurs..............................................................................................................................................29
5.
JSF TAG-LIB ......................................................................................................................................................30
5.1. VUE JSF..........................................................................................................................................................30
5.2. TEXTE SIMPLE.................................................................................................................................................30
5.3. LES COMPOSANTS DE SORTIES .......................................................................................................................30
5.3.1. Texte simple............................................................................................................................................31
5.3.2. Message formaté ....................................................................................................................................31
5.3.3. Label .......................................................................................................................................................32
5.4. FORMULAIRE ..................................................................................................................................................32
5.5. LES COMPOSANTS D’ENTREE .........................................................................................................................33
5.5.1. Champ texte............................................................................................................................................33
5.5.2. Champ texte sur plusieurs lignes ..........................................................................................................33
JSF - Framework Web
3 / 108
5.5.3. Champ de mot de passe .........................................................................................................................33
5.5.4. Champ caché..........................................................................................................................................34
5.6. LIEN ................................................................................................................................................................34
5.6.1. Lien simple .............................................................................................................................................34
5.6.2. Lien JSF..................................................................................................................................................35
5.6.3. Paramètres .............................................................................................................................................36
5.7. BOUTON ..........................................................................................................................................................37
5.8. CHECKBOX .....................................................................................................................................................37
5.8.1. Checkbox simple ....................................................................................................................................37
5.8.2. Checkbox multiples................................................................................................................................37
5.9. RADIOBUTTON ...............................................................................................................................................41
5.10. LISTE.............................................................................................................................................................41
5.11. COMBO BOX .................................................................................................................................................42
5.12. IMAGE ...........................................................................................................................................................42
5.13. PANEL ...........................................................................................................................................................43
5.14. TABLEAU ......................................................................................................................................................43
5.14.1. Tableau statique : PanelGrid..............................................................................................................44
5.14.2. Tableau dynamique : DataTable ........................................................................................................46
5.15. MESSAGE D’ ERREUR ....................................................................................................................................49
6.
CONFIGURATION SERVEUR.......................................................................................................................52
6.1. DECLARATION DES JAVABEANS ....................................................................................................................52
6.1.1. Déclaration des List...............................................................................................................................53
6.1.2. Déclaration des Maps............................................................................................................................53
6.1.3. Exemple : Déclaration d'une liste de SelectItem .................................................................................54
6.2. NAVIGATION...................................................................................................................................................56
6.2.1. Mapping global......................................................................................................................................57
6.2.2. Chaînes d’action ....................................................................................................................................57
6.2.3. Exemple ..................................................................................................................................................59
6.3. PARAMETRES DE CONTEXTE ..........................................................................................................................64
7.
LES COMPORTEMENTS................................................................................................................................65
7.1. ACTIONLISTENER ...........................................................................................................................................65
7.1.1. Méthode générique ................................................................................................................................65
7.1.2. Interface ActionListener ........................................................................................................................65
7.2. VALUECHANGE LISTENER .............................................................................................................................66
7.2.1. Méthode générique ................................................................................................................................66
7.2.2. Interface ValueChangeListener ............................................................................................................66
7.3. CONVERSIONS DE DONNEES ...........................................................................................................................67
7.3.1. Conversion standard : Date ..................................................................................................................67
7.3.2. Conversion standard: Number..............................................................................................................68
7.3.3. Convertisseur personnalisé...................................................................................................................69
7.3.4. Convertisseurs pour une Liste d’éléments ...........................................................................................70
7.4. VALIDATION ...................................................................................................................................................74
7.4.1. Validateur personnalisé ........................................................................................................................75
7.4.2. Exemple : Validateur d’email ...............................................................................................................76
8.
CONCEPTS AVANCES ....................................................................................................................................78
8.1. INTERNATIONALISATION ................................................................................................................................78
8.1.1. Internationalisation dynamique ............................................................................................................79
8.1.2. Encodage................................................................................................................................................79
8.1.3. Exemple : Bouton de changement de langue .......................................................................................79
8.2. LA GESTION DES MESSAGES ...........................................................................................................................81
8.2.1. Refaire les messages..............................................................................................................................83
8.3. INTEGRATION JSF ET APPLICATION JEE .......................................................................................................84
8.3.1. Injection de ressource............................................................................................................................84
8.3.2. Injection d’EJB ......................................................................................................................................84
8.3.3. Injection de WebService ........................................................................................................................85
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
3
JSF - Framework Web
8.3.4.
9.
4 / 108
Injection d’unité de persistance ............................................................................................................85
FACELETS ..........................................................................................................................................................86
9.1. INTRODUCTION ...............................................................................................................................................86
9.2. CONFIGURATION ............................................................................................................................................87
9.2.1. Installation .............................................................................................................................................87
9.2.2. Structure d’un projet .............................................................................................................................87
9.2.3. Configuration .........................................................................................................................................87
9.3. CONCEPTS DE BASE ........................................................................................................................................88
9.3.1. Structure d’une page .............................................................................................................................88
9.3.2. JSFC .......................................................................................................................................................89
9.3.3. Template .................................................................................................................................................90
9.4. TEMPLATING DE VUE .....................................................................................................................................92
9.5. BALISES FACELETS ........................................................................................................................................96
9.5.1. Composition ...........................................................................................................................................96
9.5.2. Insert.......................................................................................................................................................98
9.5.3. Define .....................................................................................................................................................98
9.5.4. Decoration..............................................................................................................................................98
9.5.5. Include ..................................................................................................................................................100
9.5.6. Param ...................................................................................................................................................100
9.5.7. Remove .................................................................................................................................................100
9.5.8. Component ...........................................................................................................................................101
9.5.9. Fragment ..............................................................................................................................................101
9.5.10. Balises JSTL et Fonctions .................................................................................................................101
9.6. TEMPLATING DE COMPOSANTS ....................................................................................................................102
9.6.1. Le problème..........................................................................................................................................102
9.6.2. La solution avec Facelets....................................................................................................................102
9.6.3. TagFile .................................................................................................................................................103
9.7. PARAMETRES ................................................................................................................................................106
10.
BIBLIOGRAPHIE..........................................................................................................................................108
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
4
JSF - Framework Web
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
5 / 108
5
JSF - Framework Web
6 / 108
1. Introduction
1.1.
Limitations du couple Servlet/JSP
La première étape pour apprendre à faire du Web en Java est l’apprentissage des Servlet/JSP. Il est
possible de faire un site avec uniquement des Servlet et/ou des JSP, mais il devient vite évident qu’il
est plus simple d’utiliser les JSP pour faire de la présentation et des Servlets pour faire du traitement.
Cependant, le couple Servlet/JSP possède plusieurs limitations :
•
La création de balises personnalisées est assez lourde,
•
Il n’existe pas de balises de haut niveau en JSP,
•
Il n’est pas possible de récupérer facilement les entrées utilisateurs,
•
Il n’existe pas de guide qui indique comment développer en Servlet/JSP. Ainsi chaque
développeur peut organiser son site comme il veut. Ceci rend la maintenance difficile.
1.2.
Présentation de Java Server Faces
Java Server Faces (JSF) est un framework Web. Il fournit des composants de haut niveau pour créer
rapidement un site complexe. Il sert également à faciliter toutes les tâches courantes liées au
développement d’un site Web, validation des données, gestion de la navigation, ....
JSF s’appuie sur le modèle MVC (modèle-vue-contrôleur) pour l’architecture du site et apporte une
notion de composants similaires à ce qu’on peut trouver dans Swing. Ce principe de composants va
permettre la mise en place des écouteurs (clic sur bouton, clic sur un lien, ...) du côté serveur.
JSF offre un mapping HTML/Objet, c’est-à-dire qu’un composant HTML va correspondre à un
composant JSF. Cela permet de travailler en Java avec des JavaBeans ou d’utiliser des balises et du
code JSP. Les 2 méthodes de travail étant bien sûr tout à fait combinables.
Lorsqu’un utilisateur va visiter une page, les composants JSF vont être transformés en HTML et
inversement lorsqu’un serveur reçoit une requête utilisateur. Tout cela, toujours grâce au mapping
HTML/Objet.
Dernier concept intéressant de JSF, c’est que toute la navigation d’un site est définie dans un unique
fichier, appelé fichier de navigation. Ceci permet de centraliser les règles de navigations et d’avoir une
vue directe du plan du site.
JSF fournit les services suivants:
•
Offre un mapping HTML/Objet (Composants JSF)
•
Sauvegarde l’état des composants (côté serveur) entre les requêtes,
•
Transforme les composants JSF en HTML en fonction du navigateur,
•
Gère des événements (clic sur bouton, modification d’un champ, ...) côté serveur,
•
Instancie et attache des objets à la session, à la requête et à l’application,
•
Extensibilité, de nombreux composants JSF sont disponibles. Cela va du composant
calendrier, à l’arbre, en passant par le tableau triable et la barre de progression.
•
Supporte un système de plugin qui permet de modifier son comportement
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
6
JSF - Framework Web
7 / 108
•
Gère la conversion des données (transforme une date en un champ texte, un objet métier en
une chaîne et inversement, ...) ,
•
Valide les requêtes utilisateurs (test de la longueur d’un champ, du type de contenu),
•
Gère les erreurs et exceptions et fournit des messages d’erreurs clairs,
•
Gère la navigation en fonction d’événements et d’interaction avec un modèle de données,
•
Gère l’internationalisation et la localisation du site.
1.2.1. Public visé
JSF a été conçu pour toucher un public large. Du développeur d’application au designer, tout le monde
peut utiliser JSF. Il existe 3 catégories principales de personnes parmi 5 qui peuvent utiliser JSF.
•
Les architectes d’applications qui vont concevoir l’application, définir le plan du site, les
classes qu’il faut utiliser pour lier l’interface graphique avec la couche service de
l’application,
•
Les développeurs d’applications qui vont implémenter toute la mécanique du site,
•
Les créateurs de pages qui vont eux travailler avec du HTML et des balises JSF. Il peut s’agir
de développeurs ou de designers,
Les 2 dernières catégories concernent les personnes qui désirent étendre la capacité de JSF. Il s’agit :
•
Des personnes désirant créer une interface graphique à l’aide de composants,
•
Des éditeurs d’IDE qui vont pouvoir se servir de JSF comme une base qu’ils vont pouvoir
étendre grâce à des composants plus évolués. C’est le cas de Sun qui a créé Sun Java Studio
Creator, un IDE pour faire du JSF.
1.3.
Evolution de JSF
JSF est une spécification proposée au JCP (Java Community Process : www.jcp.org). Ce qui veut dire
qu’il n’existe pas une seule implémentation de JSF, mais un document qui décrit comment doit
fonctionner JSF.
Les spécifications officielles de JSF peuvent être récupérées aux adresses suivantes :
http://jcp.org/en/jsr/detail?id=127 pour JSF 1.0 et http://jcp.org/en/jsr/detail?id=252 pour JSF 1.2.
Sun fournit une implémentation de référence pour chaque version. Apache propose une
implémentation de JSF nommée « MyFaces », celle-ci est actuellement en version 1.1.
Les versions 1.0 et 1.1 de JSF sont sorties sans faire partir de J2EE 1.4. Ce n’est qu’à partir de JEE 5
que la version 1.2 de JSF est devenu un standard.
JSF 1.2 est basé sur les librairies suivantes :
•
JSP version 2.1,
•
Servlet 2.5,
•
JSE 5.0,
•
JEE 5.0,
•
JavaBeans 1.0.1,
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
7
JSF - Framework Web
•
8 / 108
JSTL 1.2.
Tous les serveurs supportant JEE 5 supportent JSF version 1.2. Si votre serveur ne supporte pas JEE 5
ce n’est pas très grave. JSF 1.1 tourne sur un serveur de Servlet/JSP 2.3/1.2 et JSF 1.2 sur un serveur
de Servlet/JSP 2.5/2.1. De manière générale, pour permettre à un serveur non JEE 5.0 de faire tourner
JSF, il faut inclure les librairies relatives à JSF dans vos applications Web. Cependant chaque serveur
possède sa propre configuration et il faut consulter la documentation associée avant de déployer une
application. Ce point sera détaillé dans le chapitre « 3.5 Déploiement ».
Ce cours est valable pour JSF 1.1 et 1.2. Les quelques éléments qui sont spécifiques à JSF 1.2 seront
précisés.
1.4.
Différence avec Struts
Pour ceux qui connaissent Struts, JSF peut fortement y ressembler. Ils ont tous les deux ont été conçus
pour dépasser les limites des Servlet/JSP, ils gèrent:
•
Les JavaBeans managés, c’est-à-dire que leur cycle de vie est géré par le conteneur,
•
La validation de formulaire,
•
La navigation flexible définie dans un seul fichier.
JSF ajoute le support d’événements et l’indépendance vis-à-vis du système de rendu. Les pages JSF
peuvent très bien générer du code XML, SVG, …
Mais outre les possibilités, ils ont également une approche différente dans leur manière de fonctionner.
Struts s’apparente à un modèle action – réponse. L’accès à une page Struts requiert le passage par une
mini Servlet (classe d’action) qui va permettre d’effectuer les traitements et définir la page JSP de
destination suite à une requête.
En JSF, on accède directement à une page et c’est cette page qui peut choisir d’utiliser des JavaBeans
pour effectuer ses tâches. Ce modèle est plus souple car il permet de vraiment réutiliser son code grâce
au principe de composants.
Enfin JSF est un standard qui est intégré à JEE 5 ce qui lui assure un suivi constant de la part de la
communauté Java et des grandes entreprises (Oracle avec ADF/MyFaces, Sun avec Java Studio
Creator 2, ...).
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
8
JSF - Framework Web
9 / 108
2. Architecture de JSF
On peut voir JSF comme un Swing adapté pour le Web. En effet JSF se base sur un système de
composant pour représenter la structure d’une page. Les composants fournissent des méthodes pour
gérer des évènements, la validation des entrées utilisateurs et la conversion de données. Tous les
composants existent sous forme de classe Java, c’est-à-dire qu’il est possible de manipuler les
composants dans du code Java. Mais dans la pratique, on manipule ces composants à l’aide de balises
JSF.
JSF peut s’utiliser avec un autre système de balises telles que HTML ou JSP mais nous verrons dans le
chapitre « 9 Facelets » un autre jeu de balise plus pratique à utiliser avec JSF.
Le système de composant de JSF fournit les éléments suivants:
•
Interaction avec des JavaBeans. Les JavaBeans représentent l’état des éléments à afficher et
permettent d’interagir avec les couches plus basses de l’application,
•
Un système de rendu (Renderer) qui permet de redéfinir comment sera affichée (traduit en
code HTML) une balise JSF,
•
Un système d’événements et d’écouteurs pour effectuer des traitements en fonction des
actions des utilisateurs,
•
Un modèle de conversion qui permet de convertir des types de données,
•
Un système de validation qui permet de vérifier les entrées utilisateurs.
Tous ces services sont manipulés à l’aide d’attributs de balises JSF ce qui facilite grandement la
création de sites.
Dans la pratique le composant est invisible, c’est comme si on associait directement la balise JSF avec
un JavaBean.
Par rapport au modèle MVC, les composants JSF font partie de la vue et la partie modèle est
représentée par des JavaBeans. Le rôle du contrôleur est joué par la Servlet de JSF.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
9
JSF - Framework Web
10 /
108
De plus JSF centralise dans un seul fichier de configuration :
•
La navigation du site,
•
La déclaration des JavaBeans utilisés.
La centralisation de la navigation permet de retrouver l’ensemble du plan du site à un seul endroit et
de visualiser directement le cheminement des requêtes utilisateurs. De plus il est possible de faire de la
navigation conditionnelle.
Les JavaBeans qui sont déclarés dans le fichier de configuration sont dits « beans managés ». C’est le
serveur qui s’occupe de les instancier pour les rendre accessible dans les pages JSF.
2.1.
Intégration de JSF dans l’architecture d’une
application JEE
Pour reprendre le schéma du cours sur l’architecture JEE, JSF correspond aux couches Application et
Client. Il est tout à fait possible d’interagir avec des EJBs ou tout autre type de couche métier. Ce sont
les JavaBeans qui vont vous permettre d’accéder à une couche Service.
Voici un exemple d’architecture JSF + EJB :
Dans le cas de petites applications, il est également possible d’interroger directement une base de
données depuis les JavaBeans.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
10
JSF - Framework Web
11 /
108
Voici un exemple d’architecture de site :
2.2.
Cycle de vie
Nous allons maintenant voir comment un serveur traite une requête. Concrètement JSF est constitué
d’une Servlet. Cette Servlet se charge de transformer les balises JSF en un système de composants que
l'on peut manipuler côté serveur. De plus, elle produit le code HTML qui correspond aux balises JSF.
Lorsqu’un client renvoie une page HTML au serveur, la Servlet va être capable de retrouver l'arbre des
composants qui correspond à cette page grâce à des identifiants placés dans le code HTML.
La Servlet de JSF peut être exécutée dans un conteneur de Servlet ou dans de Portlet.
La classe qui se charge du cycle de vie des pages est « javax.faces.context.FacesContext ». Lorsqu’une
requête arrive sur le serveur, une nouvelle instance de FacesContext est créée et elle prend en charge la
requête.
Voyons plus en détail les phases de traitement des requêtes :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
11
JSF - Framework Web
12 /
108
2.2.1. Restauration de la vue
Lorsqu’une requête arrive sur le serveur, le serveur transmet la requête à la Servlet de JSF. La Servlet
va ensuite construire l'arbre des composants représentant la page. Une fois que tous les composants
JSF sont instanciés, on passe à la phase suivante.
2.2.2. Application des paramètres de la requête
S'il existe des paramètres passés dans la requête, la Servlet va affecter les nouvelles valeurs aux
composants concernés. Par exemple, si un utilisateur envoie un formulaire, les valeurs des champs de
texte vont être affectés aux composants qui représentent ces champs textes.
Certains composants peuvent déclencher un événement dès que leur valeur change. Ces événements
sont traités seulement pendant la phase « Invocation de l’application », ou tout de suite si les
composants qui déclenche l’événement ont l’attribut « immediate » à true.
La gestion des événements pendant le cycle sera revue dans le chapitre sur les événements : « 7 Les
comportements ».
2.2.3. Validation des entrées utilisateurs
Les composants qui acceptent des entrées utilisateurs peuvent définir des règles de validations. Lors de
cette phase, la Servlet vérifie s'il n'y a pas de problèmes de validations. Les événements liés à une
validation sont traités à la fin de cette phase.
La propriété « immediate » des composants permet de forcer le traitement des validations lors de la
phase précédente « Application des paramètres de la requête ».
2.2.4. Mise à jour des valeurs du modèle
À partir de maintenant toutes les opérations de mise à jour du modèle ont été faites. Le modèle
(JavaBean) qui correspond à chaque composant va être mis à jour pour refléter les nouvelles valeurs.
2.2.5. Invocation de l’application
Lors de cette phase, tous les événements sont traités. Cela comprend les événements qui ont été
déclenchés pendant la phase « Application des paramètres de la requête ».
Enfin la navigation va être résolue, c’est-à-dire que la page de destination va être déterminée.
2.2.6. Rendu de la réponse
C'est dans cette dernière phase que la réponse va être rendue sous forme de balises HTML.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
12
JSF - Framework Web
13 /
108
3. Développer en JSF
Quelles sont les étapes nécessaires pour développer une application JSF ? Nous allons voir au travers
de cet « Hello World » les étapes minimales nécessaires à la réalisation d’un site en JSF.
Dans l’ordre, il faut :
•
Installer JSF,
•
Activer JSF dans le fichier « web.xml »,
•
Coder des pages JSF,
•
Créer des JavaBeans (optionnel),
•
Configurer l’application grâce au fichier « faces-config.xml » (optionnel).
3.1.
Installation de JSF
Si vous voulez utiliser JSF 1.2, le plus simple est d’utiliser un serveur conforme à JEE 5. Dans ce cas,
le support de JSF est intégré. Vous pouvez par exemple télécharger GlassFish à l’adresse :
https://glassfish.dev.java.net/
Si vous voulez utiliser JSF 1.1 ou JSF 1.2 sur un serveur qui ne supporte pas JSF, il faut télécharger
une implémentation. Celle de Sun se trouve sur :
http://java.sun.com/javaee/javaserverfaces/download.html
Dans le répertoire « lib » du fichier zip, il y a tous les « jars » nécessaires au développement d’une
application JSF. Ces jars sont nécessaires à la compilation et au déploiement et doivent être placés
dans le répertoire « WEB-INF/lib » d’une archive Web (War).
Les jars nécessaires à JSF 1.1 sont :
•
« jsf-api.jar », contient la définition des classes de JSF (package javax.faces),
•
« jsf-impl.jar », contient l’implémentation des classes de JSF,
•
« jstl.jar », permet l’utilisation des tags JSTL. Ces tags sont référencés par l’implémentation
de JSF,
•
« standard.jar », permet l’utilisation des tags standards. Ces tags sont référencés par
l’implémentation de JSF,
•
« commons-beanutils.jar », classes d’utilitaires pour manipuler les JavaBeans,
•
« commons-digester .jar », permet de manipuler du XML,
•
« commons-collections.jar », extension du framework des Collections,
•
« commons-logging.jar », permet de créer des logs.
Pour JSF 1.2, les seuls jars nécessaires sont:
•
« jsf-api.jar », contient la définition des classes de JSF (package javax.faces),
•
« jsf-impl.jar », contient l’implémentation des classes de JSF,
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
13
JSF - Framework Web
3.2.
14 /
108
Activation de JSF
C’est dans le fichier « web.xml » que l’on active JSF. Il s’agit simplement de faire une redirection de
requête vers la Servlet JSF. Dans notre exemple, nous allons rediriger toutes les requêtes qui
commencent par « /faces/ » vers la Servlet de JSF.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>Nom de l’application</display-name>
<!-- Faces Servlet -->
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<!-- Mapping -->
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
Pour JSF 1.2, le début du fichier est :
<?xml version='1.0' encoding='UTF-8'?>
<web-app version="2.5"
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/web-app_2_5.xsd">
Les pages JSF doivent porter l’extension « .jsp ». Il s’agit d’un paramètre de JSF que l’on peut
modifier, voir chapitre « 6.3 Paramètres de contexte ».
Pour accéder aux pages JSF, il faudra taper une url du style : « /faces/index.jsp », ce qui va permettre
de passer par la Servlet JSF. Si on tente d’accéder directement à une page sans le préfixe « /faces/ »
dans ce cas la Serlvet JSF n’est pas appelée et il va y avoir des erreurs lors du rendu (balises JSF non
interprétées).
Voici un autre exemple de mapping, où l’on va accéder aux pages, en tapant le chemin vers la page
mais en remplaçant le suffixe « .jsp » par « .jsf ».
<web-app>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
14
JSF - Framework Web
15 /
108
Bien qu’on accède aux pages en indiquant l’extension « .jsf » dans le navigateur, les pages que nous
allons coder doivent bien porter l’extension « .jsp ». En effet lors de l’appel d’une page, la Servlet JSF
cherche une page qui porte le même nom mais avec l’extension « .jsp ».
3.3.
Pages JSF
Maintenant que JSF est activé nous pouvons écrire une page JSF. Voici une page basique :
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<title>Première page en JSF</title>
</head>
<body>
<f:view>
Hello World
</f:view>
</body>
</html>
Les 2 premières lignes sont faites pour déclarer les tag-libs utilisées par JSF. La suite est une structure
HTML classique. La seule différence est la présence de la balise JSF <f:view>. C’est la balise mère de
toutes les balises JSF.
Nous voyons dans cet exemple qu’il est possible d’afficher du texte directement comme on le ferait en
HTML. Toutefois il existe des balises qui sont prévues spécifiquement pour l’affichage de texte.
Celles-ci seront vues dans la suite du cours.
3.4.
Ressources nécessaires
Une fois les pages JSF terminées, il ne reste plus qu’à packager l’application. Le War à déployer doit
avoir la structure suivante :
WEB-INF/classes
Contient toutes les classes java (les JavaBeans entre autre)
WEB-INF/lib
Toutes les librairies (jar) nécessaires au projet.
WEB-INF/faces-config.xml
Fichier de configuration (optionnel)
WEB-INF/web.xml
*.jsp
A la racine, il faut placer toutes les pages jsp
Par exemple pour JSF 1.1, ça donne:
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
15
JSF - Framework Web
3.5.
16 /
108
Déploiement
Même si votre serveur supporte JSF, vous pouvez intégrer les jars de JSF dans votre archive Web car
c’est toujours l’API du serveur qui aura la priorité (vos jars de JSF seront ignorés).
Si vous voulez ajouter le support de JSF sur un serveur, vous pouvez copier tous les jars de JSF dans
le répertoire de librairies de votre serveur. Par exemple pour Tomcat, il s’agit du répertoire
« TOMCAT_HOME/shared/lib ». Ce répertoire dépendant du serveur lui-même, il faut consulter la
documentation du serveur.
3.5.1. JBoss
JBoss intègre le support de JSF 1.1 depuis sa version 4.0.3. Ce support se base sur l’implémentation
d’Apache : MyFaces. Si vous voulez utiliser l’implémentation de Sun, il faut supprimer les jars de
MyFaces dans JBoss. Ils se trouvent dans le répertoire :
JBOSS_HOME/server/default/deploy/jbossweb-tomcat55.sar/jsf-lib
Si « default » est la configuration que vous utilisez.
Il faudra ensuite intégrer les jars spécifiques à JSF 1.1 dans votre archive War.
Le supporte de JSF 1.2 n’est pas prévu avant la version 5 de JBoss.
3.6.
Exemple
Nous allons maintenant voir un exemple un peu plus complexe de site Web fait en JSF. Le but est de
vous montrer un aperçu de quelques balises et de quelques mécanismes comme la validation d’un
formulaire, la gestion de la navigation, l’utilisation de JavaBean.
Le site est seulement constitué de 2 pages. La première est un formulaire qui permet à un utilisateur de
s’enregistrer. Quand l’utilisateur clique sur bouton pour s’enregistrer, le serveur traite l’enregistrement
et le renvoie sur la 2ème page qui affiche un message de confirmation.
S’il y a des erreurs de validation du formulaire (champ manquant, mot de passe trop court, ...), des
messages sont affichés directement sur le formulaire.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
16
JSF - Framework Web
17 /
108
Commençons par le code de la page du formulaire, « Inscription.jsp » :
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<title>Inscription</title>
</head>
<body>
<f:view>
<h1>Inscription</h1>
<h:form>
<!-- Le champ texte pour saisir son nom -->
<h:inputText id="nom" required="true" size="21" maxlength="20"
value="#{user.nom}">
<!-- Le label de ce champ texte-->
<h:outputLabel for="nom" value="Nom: "/>
<!-- Validateur: le nom doit compter entre 3 et 20 caractères -->
<f:validateLength minimum="3" maximum="20"/>
</h:inputText>
<!-- Affiche les messages d'erreurs concernant le champ d'identifiant
'nom'-->
<h:message for="nom" style="color: red"/>
<br/>
<!-- Le champ texte pour saisir son prénom -->
<h:inputText id="prenom" required="true" size="21" maxlength="20"
value="#{user.prenom}">
<h:outputLabel for="prenom" value="Prénom: ‡"/>
<f:validateLength minimum="3" maximum="20"/>
</h:inputText>
<h:message for="prenom" style="color: red"/>
<br/>
<!-- Le champ texte pour saisir son mot de passe -->
<h:inputSecret id="motDePasse" required="true" size="21" maxlength="20"
value="#{user.motDePasse}">
<h:outputLabel for="motDePasse" value="Password: "/>
<f:validateLength minimum="3" maximum="20"/>
</h:inputSecret>
<h:message for="motDePasse" style="color: red"/>
<br/>
<h:commandButton value="S'enregistrer" action="success"/>
</h:form>
</f:view>
</body>
</html>
La syntaxe du type « #{user.nom} » permet d’utiliser un JavaBean. Ici « user » est le nom d’un bean et
« nom » est une des propriétés de ce bean.
Commençons par écrire la classe de ce bean. Nous verrons ensuite comment lui attribuer un nom.
package com.labosun;
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
17
JSF - Framework Web
18 /
108
public class Utilisateur {
private String nom;
private String prenom;
private String motDePasse;
public String getNom() {
return nom;
}
public String getMotDePasse() {
return motDePasse;
}
public String getPrenom() {
return prenom;
}
public void setPrenom(String prenom) {
this.prenom = prenom;
}
public void setNom(String nom) {
this.nom = nom;
}
public void setMotDePasse(String motDePasse) {
this.motDePasse = motDePasse;
}
}
Maintenant que la classe du bean est écrite, il faut le déclarer dans le fichier de configuration de JSF
(faces-config.xml). Cela va permettre de lui attribuer un nom qu’on peut utiliser dans les pages JSF
pour y faire référence. Voici la déclaration du bean :
<managed-bean>
<!-- Nom du bean dans les pages JSF -->
<managed-bean-name>user</managed-bean-name>
<!-- Classe du bean -->
<managed-bean-class>com.labosun.Utilisateur</managed-bean-class>
<!-- Portée du bean -->
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
Maintenant que la première partie du site est faite, il faut écrire la page qui affichera le message de
confirmation. Cette page réaffiche uniquement le nom et prénom de la personne qui s’est enregistrée.
Confirmation.jsp :
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<title>Inscription</title>
</head>
<body>
<f:view>
<h1>Inscription réussie</h1>
Bienvenue <h:outputText value="#{user.prenom} #{user.nom}" />
</f:view>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
18
JSF - Framework Web
19 /
108
</body>
</html>
Comme vous pouvez le constater, on réutilise ici la syntaxe « #{user.prenom} » pour faire référence
au bean.
Enfin, la dernière étape est de définir une règle de navigation. Cette règle permet de définir la page de
destination qui sera associée au bouton d’enregistrement dans la page « Confirmation.jsp ». Pour
rappel le code du bouton est le suivant:
<h:commandButton value="S'enregistrer" action="success"/>
L’attribut « action » définit une chaîne qui fait référence à la page de destination.
<navigation-rule>
<!-- Page pour laquelle on définit la règle -->
<from-view-id>/Inscription.jsp</from-view-id>
<navigation-case>
<!--Chaîne qui est utilisée pour référencer la page de destination -->
<from-outcome>success</from-outcome>
<!-- Page de destination -->
<to-view-id>/Confirmation.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Voyons maintenant le résultat. Voici la page d’inscription :
La mise en forme n’est pas très bonne, mais nous verrons dans la suite du cours commet y remédier.
Lorsqu’on s’enregistre, on arrive sur la page de confirmation :
Voici les messages d’erreurs qui sont affichés lorsque la validation d’un des champs échoue :
On remarque ici que les messages d’erreur sont en français, ils sont personnalisés en fonction de la
langue du client. Par contre notre formulaire lui est uniquement en français. Le chapitre « 8.1
Internationalisation » explique comment gérer un site multi langues.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
19
JSF - Framework Web
20 /
108
De plus, les messages d’erreurs ne sont pas très clairs, le chapitre « 8.2.1 Refaire les messages »
explique comment personnaliser les messages d’erreurs.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
20
JSF - Framework Web
21 /
108
4. Les briques de base
La classe mère des composants est « javax.faces.component.UIComponent ». Cette classe définit les
attributs que possèdent tous les composants JSF. Il s'agit de composants non spécifiques au HTML,
mais qui fournissent le même type de fonctionnalités: liens, tableau, formulaire, boutons, menu
déroulant, liste, ... Les composants spécifiques à HTML héritent tous d'un composant standard. Ils se
trouvent dans le package « javax.faces.component.html ».
Dans la pratique on utilise une balise JSF pour utiliser un composant, et les attributs de cette balise
pour appeler les méthodes ou propriétés du composant.
Par exemple, la classe UIComponent définit la propriété « id ». Cette propriété est accessible
directement depuis une balise JSF grâce à l’attribut du même nom : « id ». ce qui donne :
public class UIComponent {
private int id;
public int getId() {...}
public void setId() {...}
}
Et pour n’importe quelle balise JSF on pourra écrire :
<h:baliseJSF id="identifiant" />
Attention:
•
Certaines propriétés ne sont pas directement manipulables depuis les balises JSF.
•
Il existe quelques attributs de balises qui ne portent pas exactement le même nom que la
propriété du JavaBean.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
21
JSF - Framework Web
4.1.
22 /
108
Les comportements
Il existe 5 interfaces qui permettent de définir un comportement pour un composant.
Interface
Description
StateHolder
Indique que le composant possède un état qui doit être sauvegardé entre les
requêtes.
Cette interface est implémentée par UIComponent. Ainsi tous les composants
JSF possèdent un état que le serveur sauvegarde entre les requêtes utilisateurs.
NamingContainer
Indique que tous les composants fils de ce composant doivent avoir un
identifiant unique.
Il n’est pas obligatoire de donner un identifiant aux composants. Si vous n’en
précisez pas, un identifiant est généré automatiquement par le serveur.
ValueHolder
Le composant possède une valeur. Cette valeur peut être interne au composant
ou liée à un JavaBean.
La valeur peut être convertie à l’aide d’un convertisseur. Voir chapitre « 7.3
Conversions de données ».
EditableValueHolder
Hérite de ValueHolder. Cette interface définit que la valeur du composant
peut être modifié et qu’un événement est généré dès que la valeur change.
De plus il est possible de mettre en place un système de validation pour ces
composants.
ActionSource
Indique qu’un composant peut générer un événement suite à une activation de
l’utilisateur.
Exemple : un lien HTML génère une action lorsqu’on clique dessus.
Note : En JSF 1.2, l’interface « ActionSource » a été étendue en « ActionSource2 ».
Les balises JSF des composants qui implémentent ValueHolder possèdent l’attribut « converter ». Cet
attribut permet de convertir la valeur du composant (qu’elle soit interne ou liée à un JavaBean). Cela
sert par exemple à convertir une chaîne de type « 10/05/06 » en un objet Date.
Les balises JSF des composants qui implémentent EditableValueHolder possèdent les attributs :
• « validator », cela permet de définir une méthode ou un composant qui va se charger de
vérifier les entrées utilisateurs.
• « valueChangeListener », dès que la valeur du composant change, un événement est
déclenché
Les balises JSF des composants qui implémentent ActionSource possèdent l’attribut
« actionListener ». Cet attribut permet de définir l’écouteur à appeler (côté serveur) lorsque le
composant est activé par l’utilisateur.
L'utilisation de ces comportements est détaillée dans le chapitre « 7. Les comportements ».
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
22
23 /
108
JSF - Framework Web
4.2.
Les composants génériques
JSF est prévu pour être indépendant du HTML. C’est pourquoi on va retrouver un système de rendu
qui permet de définir comment doit être affiché un composant. Dans la pratique, il n’existe que
l’implémentation pour le HTML.
On va ainsi retrouver 2 hiérarchies de composants, la première pour les composants génériques de
JSF, la deuxième pour les composants HTML.
Voici l’ensemble des composants
package « javax.faces.component ».
génériques
de
JSF,
Classe
(ActionSource)
UIData
(NamingContainer)
UIForm
se
trouvent
tous
dans
le
Description
(interfaces implémentées)
UICommand
ils
Classe mère de tous les composants qui peuvent générer un événement
lorsqu’ils sont activés
Permet de traiter un ensemble de données provenant d’une Collection ou
d’un tableau.
(NamingContainer)
Représente un formulaire. C’est-à-dire un ensemble de composant qui
vont pouvoir être modifiés par l’utilisateur.
UIGraphic
Prend en charge l’affichage d’images.
UIInput (extends UIOutput)
Permet de saisir des données.
(EditableValueHolder)
UIMessage et UIMessages
Permet d’afficher un message provenant du système de message interne
à JSF. Ce point sera vu dans le chapitre « 8.2 La gestion des messages ».
UIOutput
Permet l’affichage de texte.
(ValueHolder)
UIPanel
Regroupe plusieurs composants JSF pour les manipuler comme un
élément unique.
UISelectBoolean (extends UIInput) Permet de définir une valeur booléenne
(EditableValueHolder)
UISelectMany (extends UIInput)
Permet de sélectionner plusieurs éléments parmi une liste
(EditableValueHolder)
UISelectOne (extends UIInput)
Permet de sélectionner un élément parmi une liste
(EditableValueHolder)
Tous ces composants supportent les attributs suivants.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
23
JSF - Framework Web
24 /
108
4.2.1. L’attribut id
L’attribut « id » permet de donner un nom unique à un composant. L'utilisation d'identifiant n'est pas
obligatoire, elle sert uniquement à référencer des composants dans la page. Un identifiant doit se
conformer aux règles suivantes :
•
L’identifiant doit commencer par une lettre (voir la méthode Character.isLetter()) ou un
underscore '_'.
•
Les caractères suivants peuvent être des lettres (voir la méthode Character.isLetter()), des
chiffres (voir la méthode Character.isDigit()), le tiret '-' ou un underscore '_'.
Exemple :
<h:baliseJSF id="identifiant" />
Note : Pour optimiser les performances de JSF il est recommandé d’utiliser des identifiants le plus
court possible.
4.2.2. L’attribut renderer
Cet attribut vous permet de choisir si un composant sera affiché ou non. Pour ne pas afficher un
composant il suffit de mettre « renderer » à false.
Exemple :
<h:baliseJSF renderer="false" />
Cet attribut peut servir à afficher un message seulement si une recherche n’a donné aucun résultat.
4.2.3. L’attribut immediate
Comme vu dans le chapitre « 2.2 Cycle de vie », cet attribut permet de déterminer dans quelle phase
du cycle de vie d'une requête les événements sont traités.
4.3.
Les composants HTML
Les composants HTML se basent sur les composants génériques pour fonctionner. Ils se trouvent tous
dans le package « javax.faces.component.html ». Plutôt que de lister tous les composants HTML ici,
nous les verrons dans le chapitre « 5 JSF Tag-lib » où vous pourrez directement voir comment les
utiliser dans une page JSF à l’aide de balises.
En plus des attributs standard, les composants génériques proposent les attributs suivants :
4.3.1. Style CSS
L’attribut « style » permet de définir le code CSS d’une balise. Voici un exemple qui utilise la balise
<h:outputText>, cette balise sera vue plus tard dans le cours.
<h:outputText style="font-size : 150%; color: red" value="Hello"/>
Ceci sera traduit par le code HTML :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
24
JSF - Framework Web
25 /
108
<span style="font-size : 150%; color: red">Hello</span>
4.3.2. Classe CSS
L’attribut « styleClass » permet de définir la classe CSS d’une balise.
Exemple :
<h:baliseJSF styleClass=”titre1” />
4.3.3. Escape
Certains composants possèdent l'attribut « escape ». S'il est mis à true, les caractères '<', '>' et '&' sont
convertis en HTML.
4.3.4. Evénements JavaScript
Il est possible de définir les attributs javascript pour les balises concernées. On retrouve ainsi:
« onclick, ondblclick, onblur, onchange, onclick, ondblclick, onfocus, onkeydown, onkeypress,
onkeyup, onmousedown, onmousemove, onmouseout, onmouseover, onmouseup, onreset, onselect, et
onsubmit ».
Il faut consulter la documentation HTML pour savoir quels composants possèdent tel attribut.
4.4.
Liaison composants et JavaBeans
Les JavaBeans représente la partie modèle d’après le modèle MVC. Ils permettent de bien séparer les
différents concepts de l’application. Un composant peut être lié à un JavaBean de 2 manières
différentes :
•
uniquement la valeur du composant est liée avec une propriété du JavaBean (uniquement pour
les composants qui possèdent une valeur).
•
l’instance du composant elle-même est liée à une propriété du JavaBean.
Toutes les expressions qui utilisent des JavaBean depuis une page JSF sont écrites en EL (Expression
Language). Il s’agit d’un langage spécifique aux pages Web en Java. A partir de JSF 1.2 ce langage a
été unifié avec le langage spécifique à JSP sous le nom Unified Expression Language.
Nous nous contenterons ici d’utiliser la structure la plus simple de ce langage. Le prochain chapitre
« 4.5 Unified Expression language » l’aborde plus en détail.
Une expression en EL commence par « #{ » et se termine par « } ». Dans une expression, on utilise
une notation objet. On peut utiliser n’importe quelle variable en l’appelant par son nom. A partir de
cette variable on peut appeler n’importe quelle méthode ou propriété. Ce qui donne :
#{javaBean.method}
#{javaBean.property}
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
25
JSF - Framework Web
26 /
108
4.4.1. Valeur
Pour lier la valeur d’un composant il faut utiliser l’attribut « value » et spécifier une référence vers une
propriété de JavaBean en EL. Ce qui donne :
<h:baliseJSF value=”#{javaBean.property}” />
Il y a des restrictions sur les types de valeur que l'on peut associer à un composant JSF.
Composant
Valeurs possibles
UIInput, UIOutput,
UISelectItem, UISelectOne
Une primitive, une String, un Number ou n'importe quelle classe pour
laquelle il existe un convertisseur de données.
Voir le chapitre « 7.3 Conversions » pour plus d'informations sur les
conversions.
UIData
Tableau de JavaBean, liste de JavaBean,
JavaBean simple,
java.sql.ResultSet, javax.servlet.jsp.jstl.sql.Result ou javax.sql.RowSet.
UISelectBoolean
boolean ou Boolean
UISelectItems
String, Collection, Tableau ou Map
UISelectMany
Tableau ou List contenant n'importe quel type.
Les restrictions seront reprécisées lorsque nous verrons les balises JSF.
4.4.2. Instance
Dans le cas où l’on voudrait lier l’instance d’un composant avec une propriété d’un bean, la propriété
doit être du même type que le composant JSF. On utilise l’attribut « binding » pour référencer la
propriété du JavaBean.
Par exemple, je veux lier le composant HtmlOutputText à un JavaBean. Je vais déclarer mon bean :
public class LinkedBean {
private HtmlOutputText composant;
public HtmlOutputText getComposant() {
return this.composant;
}
public void setComposant(HtmlOutputText c) {
this.composant = c;
}
}
Et je peux ensuite lier mon JavaBean de la manière suivante :
<h:outputText binding=”#{linkedBean.composant}” />
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
26
JSF - Framework Web
27 /
108
La différence entre l’attribut « value » et l’attribut « binding » est que dans le premier cas on lie la
valeur .
Par exemple un champ texte accepte un « String », un « Number » ou un type primitif. L’attribut
« value » peut donc être de type « String », « Number » ou primitf.
Le champ texte est représenté par la classe « HtmlInputText ». La hiérarchie de cette classe est la
suivante :
java.lang.Object
javax.faces.component.UIComponent
javax.faces.component.UIComponentBase
javax.faces.component.UIOutput
javax.faces.component.UIInput
javax.faces.component.html.HtmlInputText
L’attribut binding peut donc avoir pour type, n’importe quelle classe de cette hiérarchie.
4.5.
Unified Expression language
L'Unified EL (Unified Expression Language) est un langage créé pour uniformiser la syntaxe utilisée
dans les pages Web lorsque l'on veut accéder à un objet Java. Cette syntaxe particulière a fait son
apparition dans JSP 2.0 et dans JSF 1.0 sous le nom Expression Language. Les JSP et JSF utilisaient
alors 2 versions différentes de l’EL. Ce n’est qu’avec JSP 2.1 et JSF 1.2 que le langage a été unifié
sous le nom « Unified Expression Language ».
Par défaut, les Servlet version 2.3 et inférieures ignorent cette syntaxe. Il est possible de changer ce
comportement grâce à la directive:
<%@ page isELIgnored ="true|false" %>
En JSP, une expression unified EL est sous la forme « ${ } ». En JSF, on utilise la syntaxe « #{} ».
Sans rentrer dans les détails qui dépassent le cadre de ce cours, sachez simplement que le mélange de
code JSP avec « ${} » et de code JSF avec « #{} » pose problème.
Le plus sûr dans vos applications est de n’utiliser que du code JSF et remplacer tout ce qui est balises
JSP par leur équivalent en balises Facelets (voir chapitre « 9 Facelets »).
4.5.1. Variables
Il est possible de référencer n'importe quel objet accessible dans la page avec son nom de variable. Par
exemple si on écrit:
#{person}
Le conteneur Web va chercher un objet qui porte le nom « person » dans la page, la requête, la session
ou l'application.
Pour accéder à une variable ou une méthode d'un objet, il faut utiliser l'opérateur « . ». Voici comment
accéder à la propriété « name » de la variable « person ».
#{person.name}
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
27
JSF - Framework Web
28 /
108
Voici comment accéder à la méthode « checkLogin » de la variable « person » :
#{person.checkLogin}
Pour accéder aux valeurs d’un tableau ou d’une liste il faut utiliser l’opérateur « [] ».
Exemple, on veut obtenir l’élément d’indice 2 dans un tableau :
#{uelBean.tab[2]}
Dans le cas d'une liste, l'expression « #{bean[property]} » est équivalente à « bean.get(property) ». Si
l'exception IndexOutOfBoundsException est levée, null est renvoyé. Pour toutes les autres exceptions,
une erreur est renvoyée.
Exemple :
On souhaite accéder au premier élément d’une liste :
#{uelBean.liste[0]}
Dans le cas d'une Map, l'expression « #{bean['clef']} » est équivalente à « bean.get(clef) » ou null si la
map ne contient pas la clef. Attention de bien entourer le nom de la clef par des apostrophes.
Exemple :
On veut obtenir la valeur correspond à la clef « login » :
#{uelBean.map['login']}
L’opérateur « [] » peut également servir à appeler une propriété ou une méthode. Dans ce cas, il faut
entourer le nom de la propriété ou méthode par des apostrophes (comme pour l’accès aux éléments
d’une Map).
Exemples :
Accès à la propriété « name » de la variable « person ».
#{person['name']}
Ceci est équivalent à :
#{person.name}
Appel de la méthode « checkLogin » de la variable « person ».
#{person['checkLogin']}
Ceci est équivalent à :
#{person.checkLogin}
4.5.2. Objets implicites
Il existe des objets implicites dans les pages JSF. Ils sont toujours accessibles et peuvent être récupérés
grâce à une expression EL.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
28
JSF - Framework Web
29 /
108
Nom de l'objet
Description
applicationScope
Une Map qui associe le nom des attributs d'application à leur valeur.
cookie
Une Map qui associe le nom des cookies à leur valeur.
facesContext
L'instance FacesContext courante
header
Une Map qui contient les en-têtes HTTP associées à leur valeur.
headerValues
Une Map qui associe chaque nom d'en-tête HTTP à un tableau de String. Le
tableau contient toutes les valeurs d'un en-tête.
initParam
Une Map qui contient les paramètres d'initialisation de l'application Web.
param
Une Map qui associe le nom des paramètres de la requête à leur valeur.
paramValues
Une Map qui associe chaque nom de paramètre de la requête à un tableau de
String. Le tableau contient toutes les valeurs d'un paramètre.
requestScope
Une Map qui associe les attributs de la requête à leur valeur.
sessionScope
Une Map qui associe le nom des attributs de sessions à leur valeur.
view
Le composant racine de l'arbre de composant actuel.
4.5.3. Opérateurs
L’unified EL permet d’utiliser la majorité des opérateurs de Java. La nouveauté vient du fait que
certains opérateurs ont maintenant leur équivalent en mot-clef.
•
Arithmétiques : +, -, *, /, %. Avec les deux mot-clefs : « div » et « mod ».
•
Logiques : &&, ||, !. Avec les mot-clefs : « and », « or » et « not ».
•
Relationnels : ==, « eq », !=, « ne », <, « lt », >, « gt », <=, « le », >=, « ge ». Ces opérateurs
permettent de comparer des types primitifs et des String.
•
Ternaire : expression ? val1 : val 2.
•
instanceof
•
« empty » permet de tester si une valeur est null ou si un tableau, liste est vide.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
29
JSF - Framework Web
30 /
108
5. JSF Tag-lib
Voyons maintenant l'ensemble des balises utilisables dans une page JSF.
Toutes les balises qui manipulent un composant JSF (non HTML) sont préfixées par « f » par défaut.
Le nom de la balise est celui du composant sans le préfixe « UI ».
Toutes les balises qui manipulent un composant HTML sont préfixées par « h » par défaut. Le nom de
la balise est celui du composant sans le préfixe « Html ».
5.1.
Vue JSF
La première balise à utiliser pour faire du JSF est <f:view>, cette balise permet de déclarer la vue qui
va contenir toutes les autres balises.
<f:view>
<!-- Balises JSF -->
</f:view>
5.2.
Texte simple
La balise <f:verbatim> génère un composant UIOutput à partir de son contenu. C’est la plus simple
pour afficher du texte, mais il ne s’agit pas d’une balise spécifique à HTML. Il n’est donc pas possible
d’utiliser tous les attributs propres à HTML comme le style CSS.
Exemple d’utilisation :
<p> <f:verbatim>Hello Verbatim</f:verbatim> </p>
Ce qui produit le code HTML:
<p>Hello Verbatim</p>
5.3.
Les composants de sorties
Les balises permettant d’afficher du texte sont :
•
<h:outputText>
•
<h:outputFormat>
•
<h:outputLabel>
Elles correspondent aux composants :
•
HtmlOutputText.
•
HtmlOutputFormat,
•
HtmlOutputLabel,
Ils héritent tous de UIOuput qui implémente ValueHolder.
L’attribut « value » permet de définir le texte à afficher. Cet attribut peut être associé à une primitive,
une String, un Number ou n’importe quelle classe pour laquelle il existe un convertisseur de données
(voir le chapitre « 7.3 Conversions » pour plus d'informations sur les conversions).
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
30
JSF - Framework Web
31 /
108
5.3.1. Texte simple
La balise la plus simple pour afficher une seule ligne de texte est :
<p> <h:outputText value="texte"/> </p>
Ce qui sera traduit par le code HTML :
<p>texte</p>
Voici un autre exemple, mais cette fois-ci, nous allons inclure du texte à l’intérieur de la balise.
<p> <h:outputText value="Another test of " style="color: red">
outputText
</h:outputText> </p>
Ce qui produit le code HTML :
<p>outputText <span style="color: red">Another test of </span></p>
Et en graphique, cela donne :
outputText Another test of
On remarque ici, que le texte à l’intérieur de la balise est affiché avant le texte de l’attribut « value »,
de plus seulement ce texte utilise le style CSS.
Note : Il est possible d’afficher un texte provenant d’un fichier de ressource. Ceci sera vu lors du
chapitre « 8.1 Internationalisation ».
5.3.2. Message formaté
La balise <h:outputFormat> affiche un message formaté grâce à la méthode format() de la classe
MessageFormat. Il est possible de passer des paramètres en imbriquant des balises <f:param/>.
Exemple de code JSF :
<p> <h:outputFormat value="outputFormat is {0}"><br />
<f:param value="great" /> <!-- Passage d'un paramètre -->
</h:outputFormat> </p>
Ce qui donne en HTML :
<p>outputFormat is great</p>
Autre utilisation :
<h:outputFormat
value="Arrondi à 2 chiffres: {0,number,#.##}, à 1 chiffre: {0,number,#.#}">
<f:param value="#{basic.nb}" />
</h:outputFormat>
Ce qui donne :
Arrondi à 2 chiffres: 4,15, à 1 chiffre: 4,2
Pour plus de détails sur les patterns utilisables, il faut consulter la documentation de la classe
MessageFormat.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
31
JSF - Framework Web
32 /
108
5.3.3. Label
La balise <h:outputLabel> représente la balise <label> en HTML. Elle permet d’affecter un label à un
composant d’entrée utilisateur (tel qu’un champ texte, une checkbox, …). Cette balise s’utilise en tant
que balise fille de l’élément auquel elle fait référence. L’attribut « for » contient l’identifiant pour
lequel on utilise ce label.
Exemple :
<h:inputText id="address" value="your address here"> <!-- champ texte -->
<h:outputLabel for="address" value="Address:" />
</h:inputText>
Ce qui va générer le code HTML suivant :
<label for="address">Address:</label>
<input id="address" type="text" name="address" value="your address here" />
Il est également possible d’utiliser la balise <h:outputLabel> toute seule. Exemple :
<h:outputLabel for="city" value="City:" />
<h:inputText id="city" value="Strasbourg" />
Voici au final ce qu’on obtient en combinant les 2 exemples précédents :
5.4.
Formulaire
Cette balise représente un formulaire. Le composant implémente « NamingContainer », ce qui veut
dire que toutes les balises à l’intérieur d’un formulaire doivent posséder un identifiant unique.
Exemple :
<h:form>
</h:form>
JSF va ajouter quelques informations lors de la traduction de cette balise en HTML. Le type d’envoi
du formulaire est toujours en « POST » et l’encodage en « application/x-www-form-urlencoded ».
<form
id="_id0" method="post" action="/HW/04-Form.jsf"
enctype="application/x-www-form-urlencoded">
<input type="hidden" name="_id0" value="_id0" />
</form>
Voici un dernier exemple qui illustre l’ajout d’identifiant pour toutes les balises filles d’un formulaire :
<h:form>
<h:outputText id="name" value="texte" />
</h:form>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
32
JSF - Framework Web
33 /
108
Et en HTML :
<form
id="_id1" method="post" action="/HW/04-Form.jsf"
enctype="application/x-www-form-urlencoded">
<span id="_id1:name">texte</span>
<input type="hidden" name="_id1" value="_id1" />
</form>
Tous les composants qui n’ont pas d’identifiant s’en voient attribuer un. Les identifiants utilisés sont
préfixés par l’identifiant du formulaire ce qui permet d’utiliser plusieurs fois le même identifiant dans
des formulaires différents.
5.5.
Les composants d’entrée
Les composants pour permettre de saisir des données sont :
•
HtmlInputText,
•
HtmlInputTextarea,
•
HtmlInputSecret,
•
HtmlInputHidden.
Ils héritent tous de UIInput qui implémente EditableValueHolder. L’attribut « value » de ces balises
permet d’affecter une valeur par défaut à un champ. La valeur peut être liée à une primitive, une
String, un Number ou n'importe quelle classe pour laquelle il existe un convertisseur de données.
Il est possible d’utiliser l’attribut « required » pour indiquer qu’un champ est obligatoire.
5.5.1. Champ texte
La balise la plus simple pour permettre la saisie de texte est <h:inputText>.
<h:inputText maxlength="20" size="20" value="default value"/>
Ce qui va générer le code HTML :
<input type="text" value="default value" maxlength="20" size="20" />
5.5.2. Champ texte sur plusieurs lignes
La balise <h:inputTextArea> permet de saisir un texte sur plusieurs lignes
<h:inputTextarea cols="10" rows="10" />
En HTML, ça donne :
<textarea cols="10" rows="10"></textarea>
5.5.3. Champ de mot de passe
La balise <h:inputSecret> permet de saisir un mot de passe. L’attribut « redisplay » permet que le mot
de passe soit conservé lorsque la page est rechargée (cet attribut est à false par défaut).
<h:inputSecret redisplay="false" value="#{bean.password}" />
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
33
JSF - Framework Web
34 /
108
Ce qui donne le code HTML:
<input type="password" />
5.5.4. Champ caché
La balise <h:inputHidden> permet d’inclure un champ caché dans une page.
<h:inputHidden value="#{bean.cache}"/>
Ce qui donne le code HTML:
<input type="hidden" value="valeur" />
5.6.
Lien
Il existe 2 types de liens en JSF:
•
les liens simples, qui ne déclenchent aucun événement côté serveur.
•
les liens qui vont déclencher un événement côté serveur et qui vont permettre de gérer la
navigation du site à partir d'un seul fichier.
Tous les liens internes à votre site (qui renvoie sur votre site) doivent être du 2ème type. En effet grâce
à ces liens plus évolués, vous allez pouvoir définir la navigation de votre site dans le fichier de
configuration de JSF.
5.6.1. Lien simple
La balise <h:outputLink> permet d’afficher un lien. Elle utilise le composant « HtmlOutputLink » qui
hérite de UIOutput qui implémente ValueHolder.
L’attribut « value » permet de définir l’url du lien. La valeur peut être associée à une primitive, une
String, un Number ou n’importe quelle classe pour laquelle il existe un convertisseur de données. Il
n’existe pas d’attribut pour définir le texte du lien. A la place, il suffit d’imbriquer une balise
d’affichage tel que <h:outputText>.
Exemple :
<h:outputLink value="url">
<h:outputText value="Texte du lien" />
</h:outputLink>
Il est possible d’imbriquer plusieurs balises pour définir le texte:
<h:outputLink value="url">
<h:outputText value="Texte " />
<h:outputText value="du " />
<h:outputText value="lien" />
</h:outputLink>
Ce qui dans les 2 cas sera traduit par le code HTML :
<a href="url">Texte du lien</a>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
34
JSF - Framework Web
35 /
108
Toutes les urls sont relatives à l’url courante. Il est possible de se référer à la racine du site en
préfixant l’url par « / ».
Si on a l’url suivante :
http://localhost:8080/JSFCours/faces/testLiens.jsp
Où « JSFCours » est le contexte du site et « faces » le mapping vers la servlet JSF. Alors :
•
« index.jsp » pointe vers « http://localhost:8080/JSFCours/faces/index.jsp »
•
« /index.jsp » pointe vers « http://localhost:8080/index.jsp »
Il est possible de récupérer le contexte du site et le mapping vers la servlet JSF grâce aux expressions
suivantes :
•
#{facesContext.externalContext.requestContextPath}, contexte du site
•
#{facesContext.externalContext.requestServletPath}, mapping vers la Servlet de JSF. Cette
chaîne est vide si le mapping est en mode suffixe.
•
#{facesContext.externalContext.requestPathInfo}, le chemin vers la page actuelle en partant
de l’url de la Servlet de JSF.
Par exemple si on a l’url « http://localhost:8080/JSFCours/faces/testLiens.jsp » alors on récupèrera les
valeurs suivantes :
•
facesContext.externalContext.requestContextPath = /JSFCours
•
facesContext.externalContext.requestServletPath = /faces
•
facesContext.externalContext.requestPathInfo = /testLiens.jsp
5.6.2. Lien JSF
Le composant pour créer un lien est « HtmlCommandLink ». Il hérite de UICommand qui implémente
« ActionSource ».
Ce type de lien n’utilise pas d’URL pour indiquer la page sur laquelle aller mais une chaîne. Cette
chaîne doit être référencée dans le fichier de navigation de JSF. C’est grâce à ce fichier que JSF sait à
quelle page de destination correspond telle chaîne d’action. Voir chapitre « 6.2 Navigation ».pour plus
de détails sur les chaînes d’actions.
Pour créer un lien on utilise la balise <h:commandLink>. Cette balise doit se trouver à l’intérieur
d’une balise <h:form> pour fonctionner.
L'attribut « value » permet de définir le texte du lien (mais pas l’url de destination). La valeur peut être
liée à une primitive, une String, un Number ou n’importe quelle classe pour laquelle il existe un
convertisseur de données.
La chaîne d’action se précise grâce à l’attribut « action ». Si on n’en précise aucune, le lien retourne
sur la page actuelle.
Exemple :
<h:form>
<h:commandLink action="success" value="lien JSF" />
</h:form>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
35
36 /
108
JSF - Framework Web
Tout comme pour la balise <h:outputLink> il est possible d’imbriquer des balises qui vont définir les
éléments qui peuvent servir de lien.
L’équivalent de l’exemple précédent donne alors :
<h:form>
<h:commandLink action="success">
<h:outputText value="lien JSF" />
</h:commandLink>
</h:form>
Ce qui dans les 2 cas produit un code HTML similaire à :
<form method="post" action="/HW/06-Liens.jsf"
enctype="application/x-www-form-urlencoded">
<a href="#">lien success</a>
</form>
Note : Le code généré a été simplifié pour ne montrer que l’essentiel.
5.6.3. Paramètres
Il est possible de passer des paramètres à un lien en imbriquant des balises <f:param>. Cette balise
possède l’attribut « name » qui est le nom du paramètre et l’attribut « value » qui est la valeur du
paramètre.
<h:form>
<h:outputLink value="index.jsp">
<h:outputText value="index.jsp"/>
<f:param name="id" value="2"/>
<f:param name="sortBy" value="price"/>
</h:outputLink>
<br/>
<h:commandLink>
<f:param name="id" value="6"/>
<f:param name="sortBy" value="name"/>
</h:commandLink>
</h:form>
La valeur des
paramètres
peut ensuite être
« #{param.NomParamètre} ». Ce qui dans notre cas donne :
récupérée
grâce
à
l’expression
<h:outputText value="id=#{param.id}, sortBy=#{param.sortBy}" />
La présence d’un paramètre peut être testé grâce à l’expression : « #{!empty param.NomParamètre} ».
Ce qui peut par exemple servir à afficher des balises seulement si un paramètre existe. Exemple :
<h:outputText value="(Ne s'affiche que si le paramètre 'id' existe) id=#{param.id}"
rendered="#{!empty param.id}"/>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
36
JSF - Framework Web
5.7.
37 /
108
Bouton
Le composant pour créer un bouton est « HtmlCommandButton ». Il hérite de UICommand qui
implémente ActionSource (et ActionSource2 pour JSF 1.2). Un bouton fonctionne comme le lien de la
classe HtmlCommandLink.
Exemple :
<h:form>
<h:commandButton action="chaîne" value="Envoyer" />
</h:form>
Ce qui donne le code HTML:
<input type="submit" value="Envoyer" />
5.8.
Checkbox
Il existe 2 composants pour afficher des checkbox:
•
<h:selectBooleanCheckbox> pour afficher une seule checkbox,
•
<h:selectManyCheckbox> pour afficher une série de checkbox.
5.8.1. Checkbox simple
L’attribut « value » détermine si la case est cochée. La valeur peut être un boolean ou Boolean.
Exemple :
<h:selectBooleanCheckbox id="choix" value="#{bean.property}"/>
En HTML :
<input id="choix" type="checkbox" />
Pour afficher un texte à côté de la checkbox, il faut imbriquer une balise qui affiche du texte comme la
balise <h:outputLabel> par exemple.
Exemple :
<h:selectBooleanCheckbox id="choix" value="#{bean.property}">
<h:outputLabel for="choix" value="le texte de la checkbox" />
</h:selectBooleanCheckbox>
5.8.2. Checkbox multiples
Pour afficher plusieurs checkbox il faut utiliser la balise <h:selectManyCheckbox>. Elle possède
l'attribut « layout » qui permet d'afficher les cases horizontalement ou verticalement. Les valeurs sont:
•
•
« lineDirection » pour que les cases s’affichent sur la même ligne,
« pageDirection » pour afficher une case par ligne.
La liste des cases sélectionnées par l'utilisateur peut être stockée dans un objet de type List ou Array.
Cette liste est référencée par l'attribut « value ». Elle définit également les cases qui sont cochées par
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
37
JSF - Framework Web
38 /
108
défaut. Nous verrons plus tard comment définir cette liste de cases sélectionnées, nous allons d’abord
voir comment définir le label et la valeur de chaque case.
Pour définir l'ensemble des cases qui seront affichées vous pouvez:
•
imbriquer autant de balises <f:selectItem> qu'il y a de choix,
•
imbriquer une seule balise <f:selectItems>. Cette balise va référencer une liste de SelectItem.
5.8.2.1.
SelectItem
La balise imbriquée <f:selectItem> représente une case à cocher. Ses attributs « itemValue » et
« itemLabel » représentent respectivement la valeur et le label d'une case. La valeur de chaque case
peut être liée à une primitive, une String, un Number ou n’importe quelle classe pour laquelle il existe
un convertisseur de données. Voir chapitre « 7.3 Conversions de données » pour plus de détails.
Exemple:
<h:selectManyCheckbox id="ville" layout="pageDirection"
value="#{bean.selectedVilles">
<f:selectItem itemValue="StrasValue" itemLabel="Strasbourg" />
<f:selectItem itemValue="LyonValue" itemLabel="Lyon" />
<f:selectItem itemValue="ParisValue" itemLabel="Paris" />
</h:selectManyCheckbox>
Ce qui donne :
Voici la classe du bean:
public class Bean {
private List selectedVilles = new ArrayList();
public List getSelectedVilles() {
return selectedVilles;
}
public void setSelectedVilles(List selectedVilles) {
this.selectedVilles = selectedVilles;
}
}
Ici, la valeur des items est de type « java.lang.String », « #{bean.selectedVilles} » contient les villes
sélectionnées. C’est-à-dire les chaînes qui sont définies par l’attribut « itemValue ».
Par exemple si l’utilisateur coche la case « Strasbourg » alors « selectedVilles » va contenir
uniquement « StrasValue ». Si l’utilisateur coche les 2 cases, « selectedVilles » va contenir
« StrasValue » et « LyonValue ».
Il faut bien faire attention que la valeur des cases puisse être incluse dans l’objet List ou Array qui
contient les cases sélectionnées. C’est-à-dire que dans notre cas on peut utiliser un tableau de String
(String[]) pour contenir les villes sélectionnées. Mais on ne peut pas utiliser un tableau d’entier (int[])
car les valeurs des cases sont de type String.
Encore une fois, si vous voulez que la valeur d’une case soit d’un type que vous avez créé vous-même,
il faut utiliser un convertisseur. En effet, JSF doit pouvoir convertir la valeur référencé par
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
38
JSF - Framework Web
39 /
108
« itemValue » en un objet de type String (lors de la traduction en HTML et recréer l’objet à partir de
cette même String lors de la reconstruction de l’arborescence d’objet lors de la réception d’une
requête).
5.8.2.2.
SelectItems
Si vous ne voulez pas initialiser la liste des cases dans les balises JSF, il suffit de créer une liste, une
Map ou un tableau de SelectItem dans un JavaBean (ou à partir du fichier de configuration de JSF). Le
constructeur de cette classe prend en paramètre la valeur et le nom de l'item.
Prenons comme exemple la création de la liste dans un JavaBean. Le chapitre « 6.1.3 Exemple :
Déclaration d'une liste de SelectItem » décrit la création dans le fichier de configuration.
Le JavaBean précédent devient:
public class Bean {
private List selectedVilles = new ArrayList();
private List allVilles = new ArrayList();
public Bean() {
//On construit la liste des villes disponibles
allVilles.add(new SelectItem("StrasbourgValue", "Strasbourg :"));
allVilles.add(new SelectItem("LyonValue", "Lyon :"));
//éléments sélectionnés par défaut
selectedVilles.add("LyonValue");
}
public List getAllVilles() {
return allVilles;
}
public void setAllVilles(List allVilles) {
this.allVilles = allVilles;
}
public List getSelectedVilles() {
return selectedVilles;
}
public void setSelectedVilles(List selectedVilles) {
this.selectedVilles = selectedVilles;
}
}
Il ne reste plus qu'à référencer la liste de SelectItem à l'aide de la balise <f:selectItems>, ce qui donne:
<h:selectManyCheckbox id="ville" value="#{bean.selectedVilles}">
<f:selectItems value="#{bean.allVilles}" />
</h:selectManyCheckbox>
Comme dans le cas de la balise <f:SelectItem>, la valeur des cases doit être de type primitif ou
Number. Si ce n’est pas le cas, il faut fournir un convertisseur.
Si vous voulez utiliser un tableau pour stocker les villes, il faut le déclarer de la manière suivante :
SelectItem[] allVilles ;
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
39
JSF - Framework Web
40 /
108
Si vous voulez utiliser un objet de type Map, dans ce cas les clefs de la map seront les labels des cases
à cocher et les valeurs de la Map correspondront à la valeur des cases à cocher.
Exemple :
Map allVillesMap = new HashMap();
allVillesMap.put("Strasbourg :", "StrasbourgValue ");
allVillesMap.put("Lyon :", "LyonValue ");
5.8.2.3.
Utilisation de groupes
Il est possible de créer des groupes de SelectItem, pour ça il faut forcément utiliser la balise
<f:selectItems>. La création des groupes va se faire grâce à la classe SelectItemGroup. Le constructeur
de cette classe prend en paramètre :
•
Le nom du groupe,
•
Sa description,
•
Son activation (false pour actif et true pour inactif),
•
Un tableau de SelectItem qui compose ce groupe
Une fois un SelectItemGroup instancié, il suffit de l’ajouter à la liste qui contient tous les SelectItem.
Il est possible de mélanger des SelectItem et des SelectItemGroup.
Exemple :
//Liste des villes
List allGroupVilles = new ArrayList();
//France
SelectItem[] villesFrance = new SelectItem[3];
villesFrance[0] = new SelectItem("StrasValue", "Strasbourg”);
villesFrance[1] = new SelectItem("LyonValue", "Lyon :");
villesFrance[2] = new SelectItem("ParisValue", "Paris :");
//Création du groupe pour la France
SelectItemGroup franceGroup = new SelectItemGroup("France",
"Villes de France", false, villesFrance);
//Allemagne
SelectItem[] villesAllemagne = new SelectItem[2];
villesAllemagne[0] = new SelectItem("KehlValue", "Kehl :");
villesAllemagne[1] = new SelectItem("BerlinValue", "Berlin :");
//Création du groupe pour l’Allemagne
SelectItemGroup allemagneGroup = new SelectItemGroup(
"Allemagne", "Villes d'Allemagne", false, villesAllemagne);
SelectItem londres = new SelectItem("LondresValue", "Londres :");
allGroupVilles.add(franceGroup);
allGroupVilles.add(londres);
allGroupVilles.add(allemagneGroup);
Ce qui donne de manière graphique :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
40
JSF - Framework Web
5.9.
41 /
108
RadioButton
La balise <h:selectOneRadio> permet de définir une liste de boutons radio. Elle utilise le composant
« HtmlSelectOneRadio » qui implémente « EditableValueHolder ».
La liste des radios boutons va être construite en imbriquant des balises <f:selectItem> ou une balise
<f:selectItems>, voir chapitre « 5.8.2 Checkbox multiples » pour le fonctionnement de ces balises.
Attention cependant, car dans le cas de boutons radio, seul un bouton peut être coché à la fois,
contrairement aux checkbox.
La valeur du bouton radio sélectionné peut être associée à une primitive, une String, un Number ou
n'importe quelle classe pour laquelle il existe un convertisseur de données.
Exemple :
<h:selectOneRadio layout="lineDirection" value="#{bean.color}>
<f:selectItem itemValue="rouge" itemLabel="rouge"/>
<f:selectItem itemValue="blanc" itemLabel="blanc"/>
<f:selectItem itemValue="jaune" itemLabel="jaune"/>
</h:selectOneRadio>
La propriété référencée par l'attribut « value » doit être de même type que la valeur des items. Ici
« #{bean.color} » doit être de type String, puisque la valeur des items est aussi de type String.
5.10.
Liste
Il existe 2 composants pour afficher une liste:
•
<h:selectOneListbox> pour afficher une liste avec un seul item sélectionnable (même
fonctionnement que <h:selectOneRadio>).
•
<h:selectManyListbox> pour afficher une liste à choix multiples (même fonctionnement que
<h:selectManyCheckBox>).
L'attribut « size » vous permet de définir le nombre d'éléments que peut afficher la liste.
Exemple :
<h:selectManyListbox id="color" value="#{bean.colors}">
<f:selectItem itemValue="rouge" itemLabel=" Rouge:"/>
<f:selectItem itemValue="blanc" itemLabel=" Blanc:"/>
<f:selectItem itemValue="jaune" itemLabel="jaune"/>
</h:selectManyListbox>
Ce qui donne :
<select id="color" size="3">
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
41
JSF - Framework Web
42 /
108
<option value="rouge">Rouge:</option>
<option value="blanc">Blanc:</option>
<option value="jaune">Jaune:</option>
</select>
De manière graphique ça donne :
5.11.
Combo Box
Une combo box se créée avec la balise <h:selectOneMenu>. Son fonctionnement est similaire à la
balise <h:selectOneRadio>, voir chapitre « 5.9 RadioButton ».
Exemple :
<h:selectOneMenu id="ville" value="#{bean.selectedVilles}">
<f:selectItems value="#{bean.allVilles}" />
</h:selectOneMenu>
De manière graphique ça donne :
5.12.
Image
La balise <h:graphicImage> permet d’insérer une image. Elle possède les attributs :
•
•
« url », définit l’adresse de l’image
« alt », le descriptif de l’image
<h:graphicImage url="url de l'image" alt="description"/>
Il est possible de faire des images qui servent de liens, pour cela il suffit d’imbriquer une balise
<h:graphicImage> dans une balise de lien (<h:outputLink> dans l’exemple qui suit) :
<h:outputLink value="http://java.net">
<h:graphicImage value="java-dot-net.jpg" />
<h:outputText value="java.net" />
</h:outputLink>
En HTML, ça donne:
<a href="http://java.net"><img src="java.jpg" alt="" />java.net</a>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
42
JSF - Framework Web
5.13.
43 /
108
Panel
La balise <h:panelGroup> permet de regrouper plusieurs éléments JSF pour qu’ils soient considérés
comme une seule balise. Certaines balises ne peuvent pas avoir qu’un seul enfant, dans ce cas, on
utilise <h:panelGroup>.
Exemple :
<h:panelGroup>
<h:outputText value="first child" />
<f:verbatim><br /></f:verbatim>
<h:outputText value="second child" />
</h:panelGroup>
Ce qui va produire le code HTML suivant :
first child<br />second child
Notez l’utilisation de la balise <f:verbatim> autour de la balise <br/>. Si on l’enlève, le code ne
fonctionne pas sous JSF 1.1 mais marche toujours sous JSF 1.2.
Exemple :
<h:panelGroup>
<h:outputText value="first child" />
<br />
<h:outputText value="second child" />
</h:panelGroup>
Il donne le code HTML suivant :
<br />first childsecond child
La balise <br/> est affichée avant le reste.
5.14.
Tableau
Il existe 2 manières de définir un tableau en JSF : PanelGrid et DataTable. Il n'y a que la manière de
créer le tableau qui diffère, le résultat final est le même. Les 2 balises sont <h:panelGrid> et
<h:dataTable>. Elles possèdent les attributs communs suivants :
•
footerClass : liste des classes CSS (séparées par des espaces) pour le pied de page du tableau,
•
headerClass : liste des classes CSS (séparées par des espaces) pour l’en-tête du tableau,
•
captionClass (uniquement JSF 1.2) : liste des classes CSS (séparées par des espaces) pour le
titre
L’attribut « columnClasses » permet de définir une liste de style CSS pour chaque colonne. Les
classes CSS d’une même colonne sont séparées par des espaces. Ce qui donne :
class1.1 class1.2 class1.3 ...
Dès que toutes les classes d’une colonne sont déclarées, il faut utiliser une virgule pour passer à la
déclaration des classes de la colonne suivante. Ce qui donne
class1.1 class1.2 class1.3, class2 class2.1, class3, class4 class4.1 class 4.2 ...
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
43
JSF - Framework Web
44 /
108
Dans ce cas, si le tableau possède 4 colonnes, les classes CSS « class1.1 », « class1.2 » et « class1.3 »
seront pour la 1ère colonne, « class2 » et « class2.1 » pour la 2ème et ainsi de suite jusqu’à la 4ème
colonne.
Si la liste des classes CSS ne correspond pas au nombre de colonnes de votre tableau alors :
•
S’il y a plus de colonnes que de styles CSS, les styles CSS sont réutilisés en boucle.
•
S’il y a moins de colonnes que de styles CSS, les styles CSS en trop ne sont pas utilisés.
L’attribut « rowClasses » permet de définir le style CSS des lignes et fonctionne de la même manière.
5.14.1.
Tableau statique : PanelGrid
Ce type de tableau se crée avec la balise <h:panelGrid>. Quand on utilise ce tableau, c’est que l’on
connaît à l’avance son nombre de lignes et colonnes. Il n’est donc pas adapté pour itérer sur une liste
et générer des lignes dynamiquement.
Pour décrire le contenu du tableau, on va imbriquer des balises. Une balise imbriquée correspond à
une case du tableau. La position de la case dans le tableau dépend de l’ordre de déclaration des balises.
On va décrire les éléments à partir de la case tout en haut à gauche jusqu’à la case tout en bas à droite.
Il n’y a aucune balise qui indique la fin ou le début d’une ligne.
JSF va déterminer la position d’une case en prenant sa position dans la liste des balises imbriquées
modulo le nombre de colonnes du tableau. Le nombre de colonnes se précise grâce à l’attribut
« columns », par défaut il vaut 1.
Exemple :
<h:panelGrid border=”1” columns="2">
<h:outputText value="A" />
<h:outputText value="B" />
<h:outputText value="C" />
<h:outputText value="D" />
</h:panelGrid>
Comme le tableau possède 2 colonnes, tous les 2 composants JSF va effectuer un retour à la ligne.
Ce qui va donner de manière graphique :
A
B
C
D
Si maintenant on met 3 colonnes, le retour à la ligne ne se fera que toutes les 3 balises :
<h:panelGrid border="1" columns="3">
<h:outputText value="A" />
<h:outputText value="B" />
<h:outputText value="C" />
<h:outputText value="D" />
</h:panelGrid>
Ce qui va donner de manière graphique :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
44
JSF - Framework Web
A
B
45 /
108
C
D
5.14.1.1. Regroupement d’éléments
Si on veut utiliser plus d’une balise pour représenter une case, il faut utiliser la balise <h:panelGroup>.
Exemple :
<h:panelGrid columns="2" border="1" rules="all">
<h:outputText value="A" />
<h:panelGroup>
<h:outputText value="B" />
<f:verbatim><br /></f:verbatim>
<h:outputText value="B bis" />
</h:panelGroup>
<h:outputText value="C" />
<h:outputText value="D" />
</h:panelGrid>
Le code HTML correspondant est :
<table border="1" rules="all">
<tbody>
<tr>
<td>A</td>
<td>B<br />B bis</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</tbody>
</table>
5.14.1.2. En-tête et pied de page
Une en-tête ou un pied de page se déclare grâce à la balise <f:facet>. Elle possède l’attribut « name »
qui indique de quelle partie il s’agit. Les valeurs possibles sont :
•
« header », s’il s’agit de l’en-tête,
•
« footer », s’il s’agit du pied de page.
•
« caption », s’il s’agit du titre (uniquement en JSF 1.2)
La balise <f:facet> n’accepte qu’un seul enfant, il faut utiliser la balise <h:panelGroup> pour
imbriquer plusieurs balises.
Exemple :
<h:panelGrid border="1" columns="2" rules="all">
<f:facet name="header">
<h:outputText value="En-tête" />
</f:facet>
<f:facet name="footer">
<h:panelGroup>
<h:outputText value="Pied " />
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
45
JSF - Framework Web
46 /
108
<h:outputText value="de page" />
</h:panelGroup>
</f:facet>
<!--Ne marche pas en JSF 1.1-->
<f:facet name="caption">
<h:outputText value="caption" />
</f:facet>
<h:outputText value="A" />
<h:outputText value="B" />
<h:outputText value="C" />
<h:outputText value="D" />
</h:panelGrid>
Ce qui donne le code HTML :
<table border="1" rules="all">
<thead>
<tr>
<th colspan="2" scope="colgroup">En-tête</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="2">Pied de page</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
</tbody>
</table>
Et en graphique:
5.14.2.
Tableau dynamique : DataTable
La balise <h:dataTable> permet de générer un tableau dynamiquement. Elle sert à parcourir une liste
d’éléments. Il est possible de parcourir les objets suivants :
•
une liste de java beans,
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
46
JSF - Framework Web
•
un tableau de java beans,
•
un java bean,
•
un objet de type javax.faces.model.DataModel,
•
un objet de type java.sql.ResultSet,
•
un objet de type javax.servlet.jsp.jstl.sql.ResultSet,
•
un objet de type javax.sql.RowSet.
47 /
108
L’attribut « value » permet de préciser quel élément on veut parcourir. L’attribut « var » est le nom de
la variable qui va contenir l’objet sur lequel on se trouve pendant le parcours.
Ainsi le début de la balise est sous cette forme:
<h:dataTable value="#{bean.listeElements}" var="itemDeLaListe" />
Pour définir le contenu du tableau, il faut se servir de la balise <h:column>. On va retrouver autant de
ces balises qu’il y a de colonne. Toutes les balises imbriquées à celle-ci vont définir le contenu d’une
case.
<h:dataTable id="items" value="#{bean.listeElements}" var="itemDeLaListe">
<h:column>
<%-- 1ère colonne--%>
<h:outputText value="#{itemDeLaListe.property1" />
</h:column>
<h:column>
<%-- 2ème colonne--%>
<h:outputText value="#{itemDeLaListe.property2}" />
</h:column>
</h:dataTable>
Si la liste « bean.listeElements » contient 5 éléments, on va se retrouver avec un tableau de 5 lignes et
de 2 colonnes.
Si on ne souhaite parcourir qu’une partie de la liste on peut utiliser l’attribut « first » pour définir le
premier élément à partir duquel on veut commencer le parcours et « rows » pour le nombre d’éléments
à parcourir.
5.14.2.1. En-tête et pied de page
Comme pour les tableaux PanelGrid, les en-têtes, pieds de page et titres se définissent à l’aide de la
balise <f:facet>.
Pour définir l’en-tête (pied de page) d’une colonne, il faut imbriquer la balise <f:facet> dans une balise
<h:column>.
Pour définir l’en-tête (pied de page) pour tout le tableau, il faut placer la balise <f:facet> directement
sous <h:dataTable>.
Exemple :
<h:dataTable id="items" value="#{bean.listeElements}" var="itemDeLaListe">
<h:column>
<%-- 1ère colonne--%>
<f:facet name="header">
<%-- En-tête spécifique à la colonne--%>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
47
JSF - Framework Web
48 /
108
<h:outputText value="Property 1" />
</f:facet>
<h:outputText value="#{itemDeLaListe.property1}" />
</h:column>
<h:column>
<%-- 2ème colonne--%>
<f:facet name="header">
<%-- En-tête spécifique à la colonne--%>
<h:outputText value="Property 2" />
</f:facet>
<h:outputText value="#{itemDeLaListe.property2}" />
</h:column>
<%-- pied de page général--%>
<f:facet name="footer">
<h:outputText value="Pied de page"/>
</f:facet>
</h:dataTable>
5.14.2.2. Exemple : affichage d’une table d’une base de donnée
Finissons par un exemple qui va illustrer comment afficher le contenu d’une table d’une base de
données à l’aide d’un tableau.
Nous allons commencer par créer le JavaBean qui va lire le contenu de la base. Quand on l’instancie,
il fait une simple requête de type « SELECT » sur une table, puis il stocke le résultat dans un objet de
type ResultSet. C’est ce dernier qui sera lu directement par la balise <h:dataTable>.
Vous remarquerez ici que l’on n’utilise pas une connexion fournie par le serveur d’application. En
effet, le but ici est simplement de montrer comment lire un ResultSet depuis un tableau en JSF.
package com.labosun;
public class DataBaseBean {
private ResultSet personRS;
public DataBaseBean() {
initConnection();
}
//Getter et setter pour personRS
public ResultSet getPersonRS() {
return personRS;
}
public void setPersonRS(ResultSet personRS) {
this.personRS = personRS;
}
private void initConnection() {
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection cnx = DriverManager.getConnection(
"jdbc:mysql://localhost/jsfCours", "login", "pass");
Statement st = cnx.createStatement();
this.personRS = st.executeQuery("select * from person");
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
48
JSF - Framework Web
49 /
108
} catch (Exception e) {
//Gestion des exceptions (non détaillé ici)
}
}
}
Voici maintenant la déclaration du bean dans le fichier de config.
<managed-bean>
<managed-bean-name>dbBean</managed-bean-name>
<managed-bean-class>com.labosun.DataBaseBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
Enfin le code JSF qui va nous permettre d’utiliser notre ResultSet. L’attribut « value » de la balise
<h:dataTable> prend directement le ResultSet en paramètre. Ensuite la valeur de chaque ligne va être
accessible sous forme d’un tableau. Ce qui va permettre d’accéder à une colonne comme s’il s’agissait
d’une propriété.
<h:dataTable value="#{dbBean.personRS}" var="personDB" rules="all" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="Nom" />
</f:facet>
//Accès à la colonne lastName (notation sous forme de tableau)
<h:outputText value="#{personDB['lastName']}" /><br />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Prénom" />
</f:facet>
//Accès à la colonne firstName (notation pointée)
<h:outputText value="#{personDB.firstName}" />
</h:column>
</h:dataTable>
5.15.
Message d’erreur
Lorsqu’une erreur arrive dans une page (formulaire non valide, champ requis manquant, …) un
message qui contient un détail de l’erreur est créée. Ces messages peuvent ensuite être affichés grâce
aux balises <h:message> et <h:messages>. Le mécanisme de création et d’utilisation des messages est
expliqué dans le chapitre « 8.2 La gestion des messages ». Ici, nous verrons seulement comment les
afficher.
Les messages possèdent une importance (propriété « severity ») qui peut prendre les valeurs
suivantes :
•
« SEVERITY_INFO », message d’information,
•
« SEVERITY_WARN », une erreur peut avoir eu lieu,
•
« SEVERITY_ERROR », pour indiquer une erreur,
•
« SEVERITY_FATAL », erreur très grave
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
49
JSF - Framework Web
50 /
108
Il existe 2 types de messages, les messages spécifiques à un composant et les messages globaux.
•
La balise <h:message> affiche les messages relatifs à un composant. L’attribut « for » doit
renseigner l’identifiant du composant pour lequel on veut afficher les messages.
•
La balise <h:messages> permet d’afficher les messages globaux et les messages spécifiques à
un composant.
Ces 2 balises possèdent les attributs :
Attribut
Type
Valeur
par défaut
Description
showDetail
boolean
false
Indique si le détail des messages doit être affiché.
showSummary
boolean
true
Indique si le résumé des messages doit être affiché.
La balise <h:messages> possède en plus les attributs suivants :
Attribut
Type
Valeur
par défaut
Description
globalOnly
boolean
false
Indique si les messages spécifiques à un composant doivent
être affichés.
layout
String
list
Permet de définir le rendu des différents messages. Les
valeurs possibles sont :
•
« list » pour afficher les messages sous forme de
liste HTML,
•
« table » pour afficher les messages dans un tableau
HTML.
Exemple :
<h:inputText id="number">
<f:validateLongRange minimum="1" maximum="10" />
</h:inputText>
<h:message for="number"/>
<h:commandButton id="submit" action="success"/>
La balise <f:validateLongRange> permet de tester si le nombre rentré par l’utilisateur est compris
entre 1 et 10. Si la valeur rentrée par l’utilisateur n’est pas comprise entre 1 et 10, un message
s’affiche.
L’aspect visuel des messages peut être changé en fonction de leur importance grâce aux attributs CSS :
Nom
Description
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
50
JSF - Framework Web
errorClass
Classe CSS à utiliser pour les messages d’un niveau « ERROR ».
fatalClass
Classe CSS à utiliser pour les messages d’un niveau « FATAL ».
infoClass
Classe CSS à utiliser pour les messages d’un niveau « INFO ».
warnClass
Classe CSS à utiliser pour les messages d’un niveau « WARN ».
51 /
108
Il existe également les attributs « errorStyle », « fatalStyle », « infoStyle » et « warnStyle » pour
définir le style directement.
Il est possible d’afficher n’importe quel composant seulement s’il y a des erreurs grâce à l’attribut
« rendered ».
<h:outputText value="Il y a une erreur"
facesContext.maximumSeverity}" />
rendered="#{! empty
L’expression « #{! empty facesContext.maximumSeverity} » permet de tester si la liste des messages
d’erreur est vide.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
51
JSF - Framework Web
52 /
108
6. Configuration Serveur
La configuration de JSF se fait dans le fichier « faces-config.xml » qui doit être placé dans le
répertoire WEB-INF d’une application Web.
La structure basique de ce fichier en JSF 1.1 est :
<?xml version="1.0"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config
1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
</faces-config>
Pour JSF 1.2, le fichier à la forme suivante :
<?xml version='1.0' encoding='UTF-8'?>
<faces-config 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/web-facesconfig_1_2.xsd"
version="1.2">
</faces-config>
Toute la configuration va ensuite se retrouver entre les balises <faces-config>.
6.1.
Déclaration des JavaBeans
Pour configurer tous les JavaBeans qui se trouvent dans les pages JSF on utilise une ou plusieurs
déclarations du genre :
<managed-bean>
<managed-bean-name>nom du bean dans la page JSF</managed-bean-name>
<managed-bean-class>class du bean</managed-bean-class>
<managed-bean-scope>( application|session|request|none)</managed-bean-scope>
<managed-property>
<property-name>nom de la propriété</property-name>
<property-class>type de la propriété</property-class>
<value>valeur par défaut</value>
</managed-property>
</managed-bean>
•
« managed-bean-name » référence le nom du bean dans une page JSF. Si plusieurs pages
utilisent le même nom, la configuration sera appliquée à toutes les pages.
•
« managed-bean-class » est le nom de la classe du bean. Attention le package dans lequel se
trouve le JavaBean fait partie du nom de la classe.
•
« managed-bean-scope » définit la portée du bean« managed-property » permet d’initialiser
une propriété d’un bean.
Les valeurs possibles pour la portée sont :
•
« application » initialise le bean pour toute l’application.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
52
JSF - Framework Web
•
« session » pour toute la session
•
« request » uniquement pour la durée d’une requête
•
« none » le bean est crée à chaque fois qu’on l’utilise.
53 /
108
6.1.1. Déclaration des List
Une liste se déclare grâce à la balise <list-entries>. Il suffit ensuite d'imbriquer autant de balises
<value> qu'il y a de valeur. La valeur null peut être obtenu grâce à la balise <null-value>. Si vous
souhaitez préciser le type d'objet que contient la liste, il faut utiliser la balise <value-class>.
Exemple:
<managed-bean>
<managed-bean-name>villeList</managed-bean-name>
<managed-bean-class>java.util.ArrayList</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<list-entries>
<value-class>java.lang.String</value-class>
<value>Strasbourg</value>
<value>Bordeaux</value>
<value>Paris</value>
<value>Nice</value>
<null-value />
</list-entries>
</managed-bean>
6.1.2. Déclaration des Maps
Une Map se déclare grâce à la balise <map-entries>. Pour chaque entrée dans la map, il faut une balise
<map-entry>. Cette balise ne contient que 2 sous éléments, la balise <key> pour représenter la clef et
la balise <value> pour la valeur qui lui est associée.
Tout comme pour les listes, il est possible de préciser le type d'éléments que contient la map. La balise
<key-class> précise la classe des clefs utilisées et la balise <value-class> précise la classe des valeurs
utilisées. Ces 2 balises se placent directement en tant que balise fille de <map-entries>.
Enfin, il est possible d'utiliser la balise <null-value> pour utiliser la valeur nulle.
Exemple:
<managed-bean>
<managed-bean-name>dicoMap</managed-bean-name>
<managed-bean-class>java.util.HashMap</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<map-entries>
<key-class>classe des clefs</key-class>
<value-class>classe des valeurs</value-class>
<!-- Première entrée -->
<map-entry>
<key>Valeur de la clef1</key>
<value>Valeur associée à la clef</value>
</map-entry>
<!-- Deuxième entrée -->
<map-entry>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
53
JSF - Framework Web
54 /
108
<key>Valeur de la clef2</key>
<value>Valeur associée à la clef</value>
</map-entry>
</map-entries>
</managed-bean>
6.1.3. Exemple : Déclaration d'une liste de SelectItem
Maintenant que nous savons déclarer des listes, voyons comment créer une liste de SelectItem. Tout
d'abord il faut déclarer une liste qui va contenir uniquement des objets de type
« javax.faces.model.SelectItem ». Ensuite il suffit de déclarer chaque élément de la liste comme étant
un bean. Pour finir il faut déclarer autant de bean de type « javax.faces.model.SelectItem » qu'il y a
d'éléments.
<!-- Déclaration de la liste -->
<managed-bean>
<managed-bean-name>villes</managed-bean-name>
<managed-bean-class>java.util.ArrayList</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<list-entries>
<value-class>javax.faces.model.SelectItem</value-class>
<value>#{ville0}</value>
<value>#{ville1}</value>
</list-entries>
</managed-bean>
<!-- Déclaration du premier bean -->
<managed-bean>
<managed-bean-name>ville0</managed-bean-name>
<!-- La classe est javax.faces.model.SelectItem -->
<managed-bean-class>javax.faces.model.SelectItem</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<!-- Les 2 seules propriétés à définir sont value et label -->
<managed-property>
<property-name>value</property-name>
<value>Stras</value>
</managed-property>
<managed-property>
<property-name>label</property-name>
<value>Strasbourg</value>
</managed-property>
</managed-bean>
<!-- Déclaration du deuxième bean -->
<managed-bean>
<managed-bean-name>ville1</managed-bean-name>
<managed-bean-class>javax.faces.model.SelectItem</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>value</property-name>
<value>Lyon</value>
</managed-property>
<managed-property>
<property-name>label</property-name>
<value>Lyon</value>
</managed-property>
</managed-bean>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
54
JSF - Framework Web
55 /
108
Comme on peut le voir ici, ce type de déclaration est très lourd. Il est plus court de déclarer les objets
directement dans un JavaBean.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
55
JSF - Framework Web
6.2.
56 /
108
Navigation
La navigation du site se définit à l’aide de plusieurs règles de navigation. Chaque règle définit toutes
les pages de destination possibles à partir d’une page source. Une règle se définit à l’aide de la balise
<navigation-rule>.
<navigation-rule>
<from-view-id>/Page de départ</from-view-id>
<navigation-case>
<from-outcome>chaîne renvoyé par la page</from-outcome>
<to-view-id>/Page de destination</to-view-id>
</navigation-case>
</navigation-rule>
La balise « from-view-id » définit la page source. On peut ensuite inclure autant de balises
« navigation-case » que nécessaire, chaque balise définit une page de destination possible.
La balise « from-outcome » est la chaîne qui sera renvoyée par un bouton ou un lien. Il est possible
d’utiliser des espaces dans cette chaîne. Enfin la balise « to-view-id » est la page de destination.
Prenons l’exemple suivant, on est sur la page « index.jsp » et l’on veut se rendre à la page
« achat.jsp ». On peut commencer par écrire la règle de navigation :
<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/achat.jsp</to-view-id>
</navigation-case>
</navigation-rule>
L’utilisation du « / » au début des urls permet de faire référence à la racine du site.
Il suffit maintenant d’insérer un composant qui renvoie la chaîne « achat » dans la page « index.jsp ».
Le renvoi de chaîne d’action se fait grâce à l’attribut « action ».
Exemple avec un lien:
<h:form>
<h:commandLink action="success" value="Vers la page achat"/>
</h:form>
Exemple avec un bouton:
<h:form>
<h:commandButton action="success" value="Vers la page achat"/>
</h:form>
A noter que cette déclaration fonctionne aussi bien pour un mapping de Servlet en mode préfixe ou
suffixe.
Ainsi si on utilise le mapping suivant :
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
Le préfixe « /faces/ » sera automatiquement rajouté dans les URLs de navigation.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
56
JSF - Framework Web
57 /
108
Si on utilise le mapping :
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
On accèdera bien aux pages avec l’extension « .jsf ».
6.2.1. Mapping global
Il est également possible de définir une règle de navigation pour un ensemble de pages. Pour cela il
faut utiliser le caractère « * » pour représenter un ensemble de pages. Ce qui donne par exemple :
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>error</from-outcome>
<to-view-id>/error.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Dans ce cas, toutes les pages qui retournent la chaîne « error » renverront sur la page « error .jsp».
Une autre solution pour faire un mapping global, est de ne pas mettre de balise <from-view-id>.
6.2.2. Chaînes d’action
Voyons maintenant plus en détail les différentes manière de configurer la navigation. Il existe en fait 2
balises pour définir les chaînes d’actions : <from-action> et <from-outcome>. Elles peuvent être
utilisées seules ou ensemble, ce qui nous fait 3 manières de déclarer un cas de navigation.
•
Si on ne spécifie que « from-outcome », la chaîne peut correspondre soit à la valeur de
l’attribut action soit à une chaîne retournée par une méthode qui gère la navigation.
•
Si on spécifie les 2. Dans ce cas, la navigation ne sera vraie que si la méthode définie dans
« from-action » retourne la chaîne spécifiée par « from-outcome ».
•
Si on ne spécifie que « from-action », la valeur doit être une référence à une méthode.
Quelque soit la valeur retournée par cette méthode, la navigation sera vraie.
Les chaînes d’actions couramment utilisées pour la balise « from-outcome » sont :
Outcome
Signification
success
Fonctionnement correct, passage à la page suivante.
failure
Erreur dans la page, passage à la page d’erreur
logon
L’utilisateur doit s’authentifier, passage à la page de login
no results
La recherche n’a donné aucun résultat. Retour à la page de recherche.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
57
JSF - Framework Web
6.2.2.1.
58 /
108
From-outcome
C’est la balise que nous avons utilisée pour les exemples précédents. On peut également utiliser une
méthode d’un JavaBean pour retourner la chaîne d’action. Il est possible d’utiliser n’importe quelle
méthode de n’importe quel JavaBean. La seule contrainte à respecter est que la méthode ait le
prototype suivant :
public String methodName();
Il suffit ensuite d’écrire la balise JSF de la manière suivante :
<h:commandLink action="#{bean.method}" value="Vers la page xxx"/>
Prenons un exemple, on déclare la règle suivante :
<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/achat.jsp</to-view-id>
</navigation-case>
</navigation-rule>
On peut ensuite écrire une méthode qui retourne « success ».
public class NaviBean {
public String getSuccessString() {
return "success";
}
}
On va ensuite déclarer notre lien de la manière suivante dans la page « index.jsp ».
<h:form>
<h:commandLink value="Vers la page achat" action="#{navi.getSuccessString}"/>
</h:form>
Ici « navi » est le nom du bean précédent.
6.2.2.2.
From-action et from-outcome
Illustrons le fonctionnement de « from-action » avec « from-outcome » avec le cas le plus simple :
<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-action>#{navi.valideAchat}</from-action>
<from-outcome>achat</from-outcome>
<to-view-id>/achat.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{navi.valideAchat}</from-action>
<from-outcome>mustLogin</from-outcome>
<to-view-id>/login.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Les 2 balises <from-action> sont identiques, ce qui va permettre de déterminer la navigation, c’est la
balise <from-outcome> qui va déterminer la page de destination. Si la méthode « valideAchat »
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
58
JSF - Framework Web
59 /
108
retourne « achat », on va sur la page achat, si elle retourne « mustLogin », on va sur la page de login.
Si elle retourne autre chose alors le cas n’est pas traité et on reste sur la même page.
Pour utiliser ces règles de navigation, il faut déclarer une action qui référence une méthode. Exemple :
<h:commandLink value="Valide les achats" action="#{navi.valideAchat}"/>
Voici un exemple de méthode qui retourne aléatoirement la chaîne « achat » ou « mustLogin » ce qui
permet de tester notre règle de navigation.
public class NaviBean {
public String valideAchat() {
Random r = new Random();
int choice = r.nextInt(2);
if( choice == 0) {
return "achat";
} else {
return "mustLogin";
}
}
}
6.2.2.3.
From-action
Avec cette balise, la navigation se base uniquement sur la méthode d’action qui a été appelée.
Par exemple avec la déclaration suivante :
<navigation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-action>#{navi.valideAchat}</from-action>
<to-view-id>/achat.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Ici, peu importe la chaîne de retour de la méthode, on va dans tous les cas sur la page « achat ».
Il suffit ensuite de déclarer un lien de la manière suivante :
<h:commandLink action="#{navi.valideAchat}" />
6.2.3. Exemple
Finissons cette partie par un exemple de site constitué de plusieurs pages. Le but de ce mini site est de
gérer le contenu d’une liste de String. Pour cela on utilisera un bean qui contiendra un objet de type
List<String>.
Le site sera constitué :
•
« list.jsp » : page principale, celle-ci permet de lister les éléments. Elle possède un lien vers la
page de suppression, de détail et de création.
•
« detail.jsp » page de détail, elle affiche le détail d’un élément, elle possède un lien vers la
page de suppression, et la page principale.
•
« delete.jsp » page de suppression, elle affiche un message de confirmation et retourne ensuite
à la page principale.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
59
JSF - Framework Web
•
60 /
108
« new.jsp » page de création, elle permet de créer un nouvel élément. Elle possède un lien vers
la page principale.
Pour savoir quel élément on doit supprimer lorsque l’on passe de la page principale à la page de
suppression, on utilisera le passage de paramètre comme vu lors du chapitre « 5.6.3 Paramètres ».
Voici ce que donnent les règles de navigation :
<navigation-rule>
<from-view-id>/list.jsp</from-view-id>
<navigation-case> <!-- Lien vers la page de détail -->
<from-outcome>edit</from-outcome>
<to-view-id>/edit.jsp</to-view-id>
</navigation-case>
<navigation-case> <!-- Lien vers la page de suppression -->
<from-outcome>delete</from-outcome>
<to-view-id>/delete.jsp</to-view-id>
</navigation-case>
<navigation-case> <!-- Lien vers la page de création -->
<from-outcome>new</from-outcome>
<to-view-id>/new.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/delete.jsp</from-view-id>
<navigation-case> <!-- Lien vers la page principale -->
<from-outcome>success</from-outcome>
<to-view-id>/list.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/new.jsp</from-view-id>
<navigation-case> <!-- Lien vers la page de création -->
<from-outcome>success</from-outcome>
<to-view-id>/list.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/edit.jsp</from-view-id>
<navigation-case> <!-- Lien vers la page de suppression -->
<from-outcome>delete</from-outcome>
<to-view-id>/delete.jsp</to-view-id>
</navigation-case>
<navigation-case> <!-- Lien vers la page principale -->
<from-outcome>list</from-outcome>
<to-view-id>/list.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Le bean qui va servir dans les pages est le suivant :
public class NaviExempleBean {
private List<String> elements; //Liste des éléments
private String newElt;
//Sert pour l'ajout de nouvel élément
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
60
JSF - Framework Web
61 /
108
/**
* Initialise une liste d'éléments avec des valeurs par défaut
*/
public NaviExempleBean() {
this.elements = new ArrayList<String>();
elements.add("salade");
elements.add("jambon");
elements.add("pêche");
elements.add("tomate");
elements.add("patate");
}
//Getters et setters
...
/**
* Créé un nouvel élément et l'ajoute à la liste.
* @return success si la création réussie, failure sinon
*/
public String create() {
if (newElt != null) {
this.elements.add(newElt);
newElt = null;
return "success";
} else {
return "failure";
}
}
/**
* Supprime l'élément dont la valeur est égale au paramètre de requête "idElt".
* @return success pour indiquer la fin de la suppression
*/
public String delete() {
String element = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get("idElt");
FacesMessage fm;
if (element != null) {
elements.remove(element);
fm = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Suppression réussie", "");
} else {
fm = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Suppression râtée", "");
}
FacesContext.getCurrentInstance().addMessage(null, fm);
return "success";
}
}
Et sa déclaration :
<managed-bean>
<managed-bean-name>naviEx</managed-bean-name>
<managed-bean-class>com.labosun.NaviExempleBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
61
JSF - Framework Web
62 /
108
La page « list.jsp » :
<f:view>
<h:form>
<h1>Liste</h1>
<!-- Permet d'afficher les messages d'erreurs -->
<h:messages />
<h:dataTable value="#{naviEx.elements}" var="elt" rules="all"
border="1">
<h:column>
<f:facet name="header">
<h:outputText value="Nom" />
</f:facet>
<h:outputText value="#{elt}" />
</h:column>
<h:column>
<!-- Lien pour supprimer -->
<h:commandLink value="supprimer" action="delete">
<!-- on passe le paramètre idElt à la page de suppression -->
<f:param name="idElt" value="#{elt}" />
</h:commandLink>
</h:column>
<h:column>
<!-- Lien pour éditer -->
<h:commandLink value="détail" action="edit">
<!-- on passe le paramètre idElt à la page de détail-->
<f:param name="idElt" value="#{elt}" />
</h:commandLink>
</h:column>
</h:dataTable>
<h:commandLink value="Créer un nouvel élément" action="new" />
</h:form>
</f:view>
Voici ce qu’elle donne dans un navigateur :
La page « edit.jsp » :
<f:view>
<h:form>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
62
JSF - Framework Web
63 /
108
<!-- On utilise le paramètre idElt pour savoir quel élément il faut afficher-->
<h:outputText value="Détail de #{param['idElt']}" /><br />
<h:commandLink value="Supprimer cet élément" action="delete">
<f:param name="idElt" value="#{param['idElt']}" />
</h:commandLink>
<h:commandLink value="Retour à la liste" action="list" />
</h:form>
</f:view>
Voici le résultat :
La page « new.jsp » :
<f:view>
<h:form>
<h1>Nouvel élément</h1>
<h:inputText id="name" value="#{naviEx.newElt}">
<h:outputLabel for="name" value="Nom:" />
</h:inputText>
<h:commandButton value="Valider" action="#{naviEx.create}" /><br />
<h:commandLink value="Annuler" action="success" />
</h:form>
</f:view>
Voici le résultat en image :
La page « delete.jsp » :
<f:view>
<h:form>
<!-- On utilise le paramètre idElt pour savoir quel élément il faut supprimer-->
<h:outputText
value="Etes-vous sûr de vouloir supprimer l'élément: #{param['idElt']} ?" />
<h:commandLink value="Oui" action="#{naviEx.delete}">
<!-- on repasse toujours le paraètre idElt pour que le bean puisse savoir quel élément
supprimer -->
<f:param name="idElt" value="#{param['idElt']}" />
</h:commandLink>
<h:commandLink value="Non" action="success" />
</h:form>
</f:view>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
63
JSF - Framework Web
6.3.
64 /
108
Paramètres de contexte
Le fonctionnement de conteneur JSF peut être modifié à l'aide de paramètres de « context ». Ces
paramètres doivent être modifiés dans le fichier « web.xml ».
<context-param>
<param-name>Nom du paramètre</param-name>
<param-value>Valeur du paramètre</param-value>
</context-param>
Les paramètres standard sont:
javax.faces.CONFIG_FILES
Liste des fichiers (séparé par des virgules) dans lesquels il
faut chercher des paramètres de configuration.
Par défaut un conteneur JSF cherchera uniquement le
fichier « faces-config.xml ».
javax.faces.DEFAULT_SUFFIX
Extension des fichiers qui contient le code JSF.
Par défaut « .jsp »
javax.faces.LIFECYCLE_ID
Permet de définir l'instance de LifeCycle pour gérer tout le
cycle de vie de l'application.
L'instance par défaut est:
LifecycleFactory.DEFAULT_LIFECYCLE
javax.faces.STATE_SAVING_METHOD
Permet de définir le mode de sauvegarde des données.
Les 2 valeurs valides sont:
•
« server », les informations sont stockées dans la
session de l'utilisateur
•
« client », les informations sont stockées côté client
sous la forme d’un champ caché
Par défaut, « server » est utilisé.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
64
JSF - Framework Web
65 /
108
7. Les comportements
7.1.
ActionListener
Tous les composants qui implémentent « ActionSource » (UICommand) peuvent générer un
événement. C'est-à-dire qu'une méthode est appelée lorsque l'utilisateur clique sur un élément.
L'événement est traité côté serveur, lorsque le client envoie la page au serveur.
Voici pour rappel le cycle de vie d’une requête JSF :
Les événements de type ActionListener sont traités pendant la phase « Invocation de l’application ». Si
le composant qui déclare l’événement a l’attribut « immediate » à true, alors l’événement est traité
pendant la phase « Application des paramètres de la requête ». Attention cependant, car pendant cette
phase, tous les éléments ne sont pas encore à jour (les javabeans sont mis à jour seulement pendant la
phase « Mise à jour du modèle »). L’ordre de mise à jour des éléments est l’ordre de déclaration des
balises.
Il existe 2 manières de prendre en charge l’événement côté serveur. La première solution est d’associer
une méthode d’un JavaBean générique. La deuxième est de créer une implémentation de l’interface
« ActionListener ».
7.1.1. Méthode générique
Pour créer une méthode qui gère un événement, il faut qu’elle ait le prototype suivant :
public void nomMethode(javax.faces.event.ActionEvent e);
La méthode peut se trouver dans n'importe quel bean, mais il doit être référencé en tant que bean géré
par le conteneur. Pour utiliser la méthode il suffit de faire référence à elle grâce à l’attribut
« actionListener ».
Exemple :
<h:commandButton value="Send" actionListener="#{nomDuBean.nomMethode}" />
7.1.2. Interface ActionListener
Il est également possible de créer une classe qui implémente « javax.faces.event.ActionListener ». Il y
a juste la méthode « processEvent(ActionEvent) » à implémenter.
Exemple :
package listeners;
public class GereEvent implements ActionListener {
public void processAction(ActionEvent actionEvent) {
//Gestion de l'événement
}
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
65
JSF - Framework Web
66 /
108
}
Cet ActionListener peut se référencer de 2 manières différentes. Il est possible d’utiliser l’attribut
« actionListener » comme vu précédemment. Mais on peut aussi utiliser la balise. <f:actionListener>.
L’attribut « type » de cette balise permet de préciser la classe de l’ActionListener qu’on utilise.
Exemple :
<h:commandLink value="avec l’interface">
<f:actionListener type="listeners.GereEvent" />
</h:commandLink>
7.2.
ValueChange Listener
Les composants qui implémentent « EditableValueHolder », c’est-à-dire toutes les classes filles de
UIInput (UISelectBoolean, UISelectMany, UISelectOne) possèdent une valeur éditable par
l’utilisateur. Lorsque que la page sera envoyée au serveur, toutes les valeurs qui ont été modifiées vont
générer un événement côté serveur. La gestion de cet événement est similaire à ActionListener.
Voici pour rappel le cycle de vie d’une requête JSF :
Les événements de type ValueChangeListener sont traités pendant la phase « Validation des entrées
utilisateurs ». Si le composant qui déclare l’événement a l’attribut « immediate » à true, alors
l’événement est traité pendant la phase « Application des paramètres de la requête ». Si c’est le cas,
alors toutes les opérations de conversions et de validation liées à ce composant vont être réalisées
avant la gestion du ValueChangeListener.
Attention cependant, car pendant cette phase, tous les éléments ne sont pas encore à jour (les
javabeans sont mis à jour seulement pendant la phase « Mise à jour du modèle »). L’ordre de mise à
jour des éléments est l’ordre de déclaration des balises.
7.2.1. Méthode générique
Une méthode qui gère l’événement doit avoir le prototype suivant :
public void check(javax.faces.event.ValueChangeEvent event);
Le JavaBean qui déclare la méthode doit être référencé en tant que JavaBean géré par le conteneur. La
méthode peut ensuite être référencée grâce à l’attribut « valueChangeListener ».
<h:inputText valueChangeListener="#{nomDuBean.nomMethode}" />
7.2.2. Interface ValueChangeListener
L’autre solution consiste à implémenter « javax.faces.event.ValueChangeListener » et de redéfinir la
méthode « processValueChange (ValueChangeEvent) ».
Exemple :
package listeners;
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
66
JSF - Framework Web
67 /
108
public class BeanValueChangeListener implements ValueChangeListener {
public void processValueChange(ValueChangeEvent event) {
//Gestion de l'événement
}
}
Cet écouteur peut se référencer soit grâce à l’attribut « valueChangeListener » comme vu
précédemment, soit grâce à la balise. <f:valueChangeListener>. L’attribut « type » de celle-ci permet
de préciser la classe de l’écouteur qu’on utilise.
Exemple :
<h:inputText value="valeur">
<f:valueChangeListener type="listeners.BeanValueChangeListener" />
</h:inputText >
7.3.
Conversions de données
Les composants JSF qui implémentent ValueHolder (toutes les classes filles de UIOutput) possèdent
une valeur. Cette valeur peut être une date, un nombre, un email, … Il n’y a pas de restrictions sur la
valeur qu’on peut associer à un composant à condition que la valeur puisse être convertie d’un objet
vers un String et inversement.
Cette transformation est nécessaire, car lors de la phase « Application des paramètres de la requête »,
la Servlet JSF doit être capable de reconstruire l’objet qui représente la valeur à partir de la requête
cliente (qui est sous forme de String). Ensuite, lors de la phase du rendu, l’objet doit être traduit en
String. JSF gère tout seul la conversion des primitives et des objets standard de Java : Boolean,
Number.
Toutes les opérations de conversions sont effectuées lors de la phase « Application des paramètres de
la requête ».
Ce principe de conversion permet également de personnaliser l’affichage des objets. Par exemple une
date peut s’afficher sous la forme « JJ/MM/AAAA » ou alors avec le jour en toutes lettres.
Les erreurs de conversions peuvent êtres affichés avec la balise <h:message>.
7.3.1. Conversion standard : Date
La balise <f:convertDateTime> assure la conversion Date - String. Par défaut, une date est affichée de
la manière suivante : « Sat Jul 22 12:56:12 CEST 2006 » ce qui correspond au samedi 22 juillet 2006.
La balise <f:convertDateTime> possède les attributs suivants :
Attribut
Type
Description
dateStyle
String
Définit le format de la date. Les valeurs sont :
default, short, medium, long et full
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
67
JSF - Framework Web
68 /
108
Pour la date du samedi 22 juillet 2006, les différentes valeurs sont :
timeStyle
String
•
Default: « Sat Jul 22 13:05:30 CEST 2006 »
•
short: « 22/07/06 »
•
medium: « 22 juil. 2006 »
•
long: « 22 juillet 2006 »
•
full: « samedi 22 juillet 2006 »
Définit le format du temps. Les valeurs sont :
default, short, medium, long et full
locale
String
Locale
ou La locale pour représenter la date
timeZone
String
ou Définit la zone horaire pour laquelle on représente la date.
TimeZone
pattern
String
Permet de définir un format de date personnalisé. Il faut utiliser un pattern qui à
une forme définie dans la documentation de la classe « SimpleDateFormat » de
J2SE.
S’il cet attribut est défini, il est utilisé à la place de dateStyle et timeStyle
type
String
Permet de préciser si la valeur à représenter est une date, un temps ou les 2. Les
valeurs sont : date (par défaut), time et both.
Exemple d’utilisation :
<h:inputText value="#{bean.date}">
<f:convertDateTime dateStyle="full" />
</h: inputText >
Voyons maintenant un exemple de formulaire qui permet de saisir une date sous la forme
« dd/mm/yy » et qui transforme ensuite la chaîne en un objet Date. Pour cela il faut utiliser l’attribut
« pattern » et définir le format de date à utiliser. Dans notre cas c’est « dd/MM/yy » :
<h:form>
<h:inputText id="date" value="#{bean.date}">
<h:outputLabel for="date" value="Date (dd/mm/yy): " />
<f:convertDateTime pattern="dd/MM/yy" />
</h:inputText>
<h:commandButton value="valider" />
</h:form>
7.3.2. Conversion standard: Number
La balise <f:convertNumber > assure la conversion Number - String. Cette balise possède les attributs
suivants :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
68
JSF - Framework Web
69 /
108
Attribut
Type
Description
currencyCode
String
Code ISO4217 utilisé pour les conversions monétaires.
currencySymbol
String
Symbole monétaire.
locale
String
Locale
integerOnly
boolean
Si « true » seule la partie entière du nombre sera prise en compte.
maxFractionDigits
int
Nombre maximal de chiffres après la virgule.
minFractionDigits
int
Nombre minimal de chiffres après la virgule.
maxIntegerDigits
int
Nombre maximal de chiffres avant la virgule.
minIntegerDigits
int
Nombre minimal de chiffres avant la virgule.
type
String
Définit ce que représente le nombre. Les valeurs possibles sont :
ou La locale pour représenter le nombre.
Number (valeur par défaut), currency, percentage.
7.3.3. Convertisseur personnalisé
Si les convertisseurs de bases ne vous suffisent pas, il est possible de créer le vôtre. Il suffit
d’implémenter « javax.faces.convert.Converter ».
Les 2 méthodes à redéfinir sont :
/**
*
@param value la chaîne à transformer en Object
*/
Object getAsObject(FacesContext context, UIComponent component, String value);
/**
*
@param value L’objet à transformer en String
*/
String getAsString(FacesContext context, UIComponent component, Object value);
Les 2 méthodes ont en paramètre l’instance FacesContext et le composant pour lequel on doit faire la
conversion.
Avant de pouvoir utiliser ce convertisseur, il faut le déclarer. Cela se fait dans le fichier « facesconfig.xml » à l’aide de la balise <converter>.
Exemple de déclaration :
<converter>
<description>Mon premier convertisseur</description>
<converter-id>myConv</converter-id>
<converter-class>com.labosun.converter.MyConverter</converter-class>
</converter>
La balise <description> permet de donner une description au convertisseur.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
69
JSF - Framework Web
70 /
108
La balise <converter-id> va définir l’identifiant du convertisseur dans les pages JSF.
Enfin la balise <converter-class> représente la classe de votre convertisseur.
Il existe 2 manières d’utiliser un convertisseur :
•
grâce à l’attribut « converter »
•
grâce à la balise <f:converter>.
En passant par l’attribut « converter », il suffit de référencer l’identifiant du convertisseur.
Exemple :
<h:outputText value="#{conv.person}" converter="myConv" />
Avec la balise <f:converter>, l’attribut « converterId » doit référencer l’identifiant du convertisseur.
Exemple :
<h:outputText value="#{conv.person}">
<f:converter converterId="myConv" />
</h:outputText>
7.3.4. Convertisseurs pour une Liste d’éléments
Lors du chapitre sur les Checkbox, boutons Radio, listes et Combo Box, nous avons vu qu’il fallait
utiliser un convertisseur pour stocker des objets personnalisés. Pour rappel, les balises concernées
sont :
•
selectManyCheckbox,
•
selectOneRadio,
•
selectOneListBox, selectManyListBox,
•
selectOneMenu
Dans cet exemple, nous allons utiliser la balise selectOneRadio qui va permettre de choisir entre
plusieurs instances de la classe « Person » suivante :
public class Person {
public static int IDS = 0;
private int id;
private String lastName;
private String firstName;
public Person(int id, String firstName, String lastName) {
this.id = id;
this.lastName = lastName;
this.firstName = firstName;
}
//Getters et setters pour toutes les propriétés
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
70
JSF - Framework Web
71 /
108
...
public String toString() {
if (firstName.length() > 1) {
return this.firstName + " " + this.lastName;
} else {
return this.lastName;
}
}
}
Cette classe définie simplement une personne qui possède un identifiant unique, un nom et un prénom.
Nous allons maintenant définir le bean qui va définir la liste des SelectItem. Nous allons commencer
par voir ce qui se passe sans convertisseur de données.
package com.labosun;
public class PersonConv {
/**
* Liste qui simule une source de données
*/
public static final List<Person> PERSONS_LIST = new ArrayList<Person>();
static {
PERSONS_LIST.add(new Person(1, "Jo", "Johnson"));
PERSONS_LIST.add(new Person(2, "Raymond", "Schmitt"));
PERSONS_LIST.add(new Person(3, "Bob", "LeNain"));
}
/**
* Liste de SelectItem pour représenter le contenu d'une balise select....
*/
private List<SelectItem> allPersons;
/**
* Personne actuellement sélectionné pour une balise de type selectOne..
*/
private Person person;
public PersonConv() {
allPersons = new ArrayList<SelectItem>();
for (int i = 0; i < PERSONS_LIST.size() - 1; i++) {
Person p = PERSONS_LIST.get(i);
this.allPersons.add(new SelectItem(p, p.toString()));
}
Person p = new Person(3, "Bob", "LeNain");
this.allPersons.add(new SelectItem(p, p.toString()));
}
//Getters et setters pour toutes les propriétés
...
}
Le constructeur se charge de créer une liste de SelectItem (allPersons) à partir de notre liste de
personnes (PERSON_LIST). Mais la dernière instance de personne n’est pas reprise de la liste, ceci
est volontaire, vous allez comprendre dans la suite pourquoi.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
71
JSF - Framework Web
72 /
108
Voici maintenant notre page JSF. Elle contient autant de boutons radios qu’il y a de personnes dans la
liste et elle affiche l’élément actuellement sélectionné.
<hform>
<h:selectOneRadio id="persRadio1" value="#{personList.person}">
<f:selectItems value="#{personList.allPersons}" />
</h:selectOneRadio>
<h:message for="persRadio1" />
<br />
Résultat:
<h:outputText value="#{personList.person}" />
<br /><br />
<h:commandButton value="Valider" />
</hf:form>
Ce qui donne :
Lorsqu’on tente de valider, on obtient le message d’erreur suivant :
Si on regarde le code HTML, on peut voir la chose suivante :
Jo Johnson <input type="radio" value="Jo Johnson" />
Raymond Schmitt <input type="radio" value="Raymond Schmitt" />
Bob LeNain
<input type="radio" value="Bob LeNain" />
On remarque ici que la valeur des boutons radio (attribut value dans le code HTML) utilise la méthode
toString() de la classe Person. Cela veut dire que lorsque la page JSF est traduite en HTML, les objets
de types Person sont traduits en String grâce à la méthode toString(). Mais lorsque l’arbre des
composants JSF doit être reconstruit, la Servlet JSF ne sait pas comment réinstancier l’objet Person à
partir de cette String. Il faut donc créer un convertisseur qui va se charger de cette traduction.
Pour créer le convertisseur, nous allons nous baser sur l’identifiant de la personne.
package com.labosun;
public class PersonConv implements Converter {
//Code précédent
...
/**
* @param value l'identifiant de la personne
* @return L'objet Person qui correspond à l'identifiant contenu dans value
*/
public Object getAsObject(FacesContext ctx, UIComponent component, String value) {
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
72
JSF - Framework Web
73 /
108
int id = Integer.valueOf(value);
for (Person p : PERSONS_LIST) {
if (p.getId() == id) {
return p;
}
}
return null;
}
/**
* @param value La personne à transformer en String
* @return L'identifiant de la personne sous forme de String
*/
public String getAsString(FacesContext ctx, UIComponent component, Object value) {
if (value == null || !(value instanceof Person)) {
return "";
}
return "" + ((Person) value).getId();
}
}
Il faut déclarer le convertisseur :
<converter>
<converter-id>persConv</converter-id>
<converter-class>com.labosun.PersonConv</converter-class>
</converter>
Il reste maintenant à référencer le convertisseur dans notre balise selectOneRadio :
<h:selectOneRadio id="persRadio1" value="#{personList.person}"
converter="persConv">
<f:selectItems value="#{personList.allPersons}" />
</h:selectOneRadio>
Tout fonctionne très bien pour les 2 premières instances, mais lorsqu’on sélectionne le 3ème bouton, on
obtient le message d’erreur suivant :
Si on regarde le code HTML, on peut voir :
Jo Johnson <input type="radio" value="1" />
Raymond Schmitt <input type="radio" value="2" />
Bob LeNain
<input type="radio" value="3" />
La valeur des boutons radio utilise bien l’identifiant des personnes pour les 3 boutons.
Le message d’erreur spécifique au 3ème bouton est là car JSF va vérifier si l’objet que retourne le
convertisseur appartient bien à la liste des items. Cette vérification se fait à l’aide des méthodes
hashCode() et equals().
Dans notre cas, notre convertisseur retourne des instances provenant de l’objet « PERSONS_LIST »,
et ensuite JSF va vérifier si l’instance retournée appartient bien à la liste « allPersons ». Hors,
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
73
JSF - Framework Web
74 /
108
souvenez vous que seules les 2 premières instances de la liste « allPersons » proviennent de la liste
« PERSONS_LIST ».
Comme la classe Person ne redéfinit pas les méthodes hashCode() et equals(), ce sont celles de la
classe Object qui sont utilisées. C’est-à-dire que l’égalité est basée uniquement sur l’égalité des
références (==). Ceci fonctionne donc seulement pour les 2 premières instances.
Pour que ça fonctionne dans tous les cas, il suffit d’implémenter ces 2 méthodes dans la classe
Person :
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
return this.getId() == ((Person) o).getId();
}
public int hashCode() {
return this.getId();
}
Voilà maintenant tout fonctionne correctement.
En résumé il faut :
•
Créer un convertisseur (Implémenter Converter).
•
Définir le convertisseur dans « faces-config.xml ».
•
Référencer le convertisseur dans la balise select.... (attribut converter)
•
Implémenter les méthodes hashCode() et equals()
Cet exemple est facilement adaptable pour une balise de type selectMany...
7.4.
Validation
JSF permet de valider toutes les données saisies par l’utilisateur. La validation n’est possible que sur
les composants qui implémentent EditableValueHolder. C’est-à-dire les champs textes, les checkbox,
les radio buttons, les listes et les combo box.
La validation est effectuée pendant la phase « Validation des entrées utilisateurs ».
Attention, pendant celle-ci, tous les éléments ne sont pas encore à jour (les javabeans sont mis à jour
seulement pendant la phase « Mise à jour du modèle »).
S’il y a plusieurs validations, l’ordre de traitements des validations est l’ordre de déclaration des
balises.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
74
JSF - Framework Web
75 /
108
Remarque : Si le composant qui déclare la validation a l’attribut « immediate » à true, alors la
validation est traitée pendant la phase « Application des paramètres de la requête ». Cela permet de
forcer une validation à se faire avant toutes les autres.
Par exemple, une personne désire s’enregistrer sur un site. Elle doit saisir le pays et la ville dans
laquelle elle habite. La validation du pays peut se faire en immediate pour être sûr que la validation de
la ville tienne compte du pays.
Pour forcer l’utilisateur à saisir une valeur, vous pouvez mettre l’attribut « required » à true.
Exemple :
<h:inputText required="true" />
Pour effectuer un contrôle plus précis sur les données, il faut utiliser un validateur. JSF fournit 3
validateurs standards. Ils sont utilisables grâce aux balises :
•
<f:validateDoubleRange>, permet de tester si un nombre à virgule se trouve dans une borne.
•
<f:validateLength>, permet de tester la longueur d’une chaîne.
•
<f:validateLongRange>, permet de tester si un nombre entier se trouve dans une borne.
Toutes ces balises possèdent les attributs « minimum » et « maximum » qui définissent les bornes
dans lesquelles doit se trouver une valeur pour être valide.
Exemple d’utilisation :
<h:form>
...
<h:inputText id="name">
<h:outputLabel for="name" value="Name:" />
<f:validateLength minimum="3" maximum="10" />
</h:inputText>
<%-- Affichage du message d'erreur de la validation %-->
<h:message for="name" />
...
</h:form>
Ici le formulaire tout entier ne sera pas validé si la chaîne rentrée pour ce champ texte n’a pas une
longueur comprise entre 3 et 10.
Les erreurs de validations sont affichées par la balise <h:message>.
7.4.1. Validateur personnalisé
Il est possible de créer son propre validateur. Il existe 2 manières de la faire, soit en utilisant une
méthode, soit en implémentant l’interface « javax.faces.validator.Validator ».
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
75
JSF - Framework Web
7.4.1.1.
76 /
108
Méthode générique
N'importe quel JavaBean peut déclarer la méthode, mais il doit être référencé en tant que JavaBean
géré par le conteneur. La méthode qui gère la validation doit avoir le prototype suivant :
public void validate(javax.faces.context.FacesContext context,
javax.faces.component.UIComponent component,
Object value) {
//Gestion de l'événement
}
S’il
y
a
une
erreur
de
validation,
la
méthode
doit
lancer
une
« javax.faces.validator.ValidatorException ». Le constructeur prend en paramètre un objet de type
« javax.faces.application.FacesMessage », c’est-à-dire un message qui est destiné à l’utilisateur. Ce
message sera ensuite affiché grâce à la balise <h:message>.
La méthode peut ensuite être référencée grâce à l’attribut « validator ».
<h:inputText validator="#{nomDuBean.methodName }" />
7.4.1.2.
Interface
Il faut implémenter l’interface « javax.faces.validator.Validator ». La seule méthode à redéfinir est :
public void validate(FacesContext context, UIComponent component, Object value);
Pour utiliser ce validateur, il faut le déclarer dans le fichier « faces-config.xml » à l’aide de la balise
<validator >. Exemple :
<validator>
<!-- Indentifiant du validateur dans les pages JSF -->
<validator-id>emailValidator</validator-id>
<!-- Classe du validateur -->
<validator-class>com.labosun.validation.EmailValidator</validator-class>
</validator>
Le validateur peut ensuite s’utiliser grâce à la balise <f:validator>, l’attribut « validatorId » doit
référencer l’identifiant du validateur.
Exemple :
<h:inputText>
<f:validator validatorId="emailValidator" />
</h:inputText>
7.4.2. Exemple : Validateur d’email
Pour illustrer le fonctionnement d’une validation, nous allons créer un validateur d’email très basique.
Nous vérifierons juste la présence du caractère « @ ».
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
if (value != null) {
String field = (String) value;
if (field.contains("@") == false) {
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
76
JSF - Framework Web
77 /
108
FacesMessage fm = new FacesMessage("L'email n'est pas valide");
throw new ValidatorException(fm);
}
}
}
Nous allons maintenant déclarer notre bean dans le fichier « faces-config.xml ».
<managed-bean>
<managed-bean-name>beanMail</managed-bean-name>
<managed-bean-class>
com.labosun.EmailValidator</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
Il ne reste plus qu’à écrire le code de la page et à référencer la méthode de notre bean grâce à l’attribut
validator.
<h:form>
<h:inputText id="emailMethod" validator="#{beanMail.checkEmail}">
<h:outputLabel for="emailMethod" value="Email:" />
</h:inputText>
<h:message for="emailMethod" />
<br />
<h:commandButton value="Vérifier l'email" />
</h:form>
Quand on rentre un texte qui ne contient pas de « @ », la balise <h:message> affiche le message « Un
email doit contenir un @ ».
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
77
JSF - Framework Web
78 /
108
8. Concepts avancés
8.1.
Internationalisation
L’internationalisation des pages JSF se fait à l’aide de fichiers de ressources. Un fichier de ressources
est un ensemble de clefs valeurs. Voir le tutorial de Sun sur les fichiers de ressources si vous ne
connaissez pas le concept : http://java.sun.com/docs/books/tutorial/i18n/index.html.
Pour utiliser un fichier de ressource depuis une page JSF, il faut utiliser la balise <f:loadBundle>.
Exemple:
<f:loadBundle basename="nomFichier" var="variable"/>
•
L’attribut « basename » référence le nom du fichier de propriétés que l’on veut utiliser.
Attention, si le fichier se trouve dans un package, il faut préfixer le nom du fichier par le nom
du package.
•
L’attribut « var » sera utilisé dans le reste de la page pour référencer ce fichier de propriétés.
Dans la suite de la page, on peut alors utiliser les chaînes définies dans le fichier de propriétés de la
manière suivante :
<h:outputText value="#{variable.nomChaine}"/>
Exemple :
On a le fichier de propriétés « SiteMessages.properties » qui se trouve dans le package com.labosun.
Ce fichier contient l'entrée suivante:
message = coucou
Pour l'utiliser dans une page, il suffit d'utiliser le code suivant:
<f:loadBundle basename="com.labosun.SiteMessages" var="msg"/>
<f:view>
<h:outputText value="#{msg.message}"/>
</f:view>
Dans ce cas, la locale utilisée sera la locale pour l'utilisateur en cours.
Si vous voulez changer la locale par défaut, il faut utiliser le code suivant dans le fichier « facesconfig.xml » :
<application>
<locale-config>
<default-locale>en</default-locale>
</locale-config>
</application>
Le chapitre « 8.1.3 Exemple : Bouton de changement de langue » explique comment changer la locale
pour un utilisateur.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
78
JSF - Framework Web
79 /
108
8.1.1. Internationalisation dynamique
Il est parfois nécessaire d’accéder à un fichier de ressource depuis un JavaBean. Pour cela il faut
utiliser la méthode getBundle de la classe ResourceBundle.
Le premier paramètre de cette méthode est le nom du fichier de ressource à utiliser et le deuxième est
la locale que l'on veut utiliser.
FacesContext context = FacesContext.getCurrentInstance();
String basename = "conf.SiteMessages";
String key = "dynamicMessage";
String message;
try {
ResourceBundle bundle = ResourceBundle.getBundle(
basename,
context.getViewRoot().getLocale());
} catch (Exception e) {
//Gestion de l'erreur
}
//Utilisation d'un message du fichier de ressource
message = bundle.getString(key);
8.1.2. Encodage
Normalement la notion d’encodage a déjà été vue dans le cours JSP, mais pour rappel, il est possible
de changer l’encodage des pages grâce à la directive de page :
<%@ page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
Par défaut c’est la valeur « ISO-8859-1 » qui est utilisée. La liste des encoding disponibles se trouve
sur la page : http://java.sun.com/j2se/1.4.2/docs/guide/intl/encoding.doc.html
8.1.3. Exemple : Bouton de changement de langue
Dans cet exemple, nous allons voir comment changer la langue du site quand l’utilisateur clique sur un
lien. Commençons par créer la page Web. Celle-ci affiche la Locale actuelle et 4 liens qui permettent
de changer la langue du site.
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<body>
<f:view>
<%--On charge le fichier de ressource--%>
<f:loadBundle basename="com.labosun.i18n.ChangeLocaleRB" var="change" />
<%-- Affichage de la locale actuelle--%>
<h:outputText value="#{change.currentLocale} #{changeBean.changeLocale}" />
<br />
<h:form>
<%-- Liens pour changer de langue--%>
<h:commandLink id="FR" value="#{change.french}"
actionListener="#{changeBean.changeLocale}" /><br />
<h:commandLink id="US" value="#{change.english}"
actionListener="#{changeBean.changeLocale}" /><br />
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
79
JSF - Framework Web
80 /
108
<h:commandLink id="CA" value="#{change.canadian}"
actionListener="#{changeBean.changeLocale}" /><br />
<h:commandLink id="DE" value="#{change.deutsch}"
actionListener="#{changeBean.changeLocale}" /><br />
</h:form>
</f:view>
</body>
</html>
Comme vous avez pu le remarquer, cette page utilise un fichier de ressource. Voici le contenu de 2
fichiers de ressources (anglais et français):
Fichier « ChangeLocaleRB_fr.properties »:
currentLocale=La Locale actuelle est
french=Français
english=Anglais
canadian=Canadien
deutsch=Allemand
Fichier « ChangeLocaleRB_en.properties »:
currentLocale=The current Locale is
french=French
english=English
canadian=Canadian
deutsch=Deutsch
Il faut maintenant écrire le bean qui va prendre en charge le changement de langue.
package com.labosun.i18n;
import
import
import
import
javax.faces.component.UIComponent;
javax.faces.context.FacesContext;
javax.faces.event.ActionEvent;
java.util.Locale;
public class ChangeBean {
/**
* Contient la Locale courante
*/
private Locale currentLocale = FacesContext.getCurrentInstance().
getViewRoot().getLocale();
public Locale getCurrentLocale() {
return currentLocale;
}
/**
* On change la locale pour la vue en cours.
* @param newLocale La nouvelle Locale
*/
public void setCurrentLocale(Locale newLocale) {
FacesContext.getCurrentInstance().getViewRoot().setLocale(newLocale);
this.currentLocale = newLocale;
}
public void changeLocale(ActionEvent ae) {
String id = ae.getComponent().getId();
Locale newLocale = null;
//on récupère toutes les Locale disponible
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
80
JSF - Framework Web
81 /
108
Locale[] locales = Locale.getAvailableLocales();
for (int i = 0; newLocale == null && i < locales.length; i++) {
if(locales[i].getCountry().equals(id)) {
newLocale = locales[i];
}
}
if (newLocale == null) {
newLocale = Locale.getDefault();
}
setCurrentLocale(newLocale);
}
}
Enfin il faut déclarer notre JavaBean dans le fichier « faces-config.xml ».
<faces-config>
<managed-bean>
<managed-bean-name>changeBean</managed-bean-name>
<managed-bean-class>com.labosun.i18n.ChangeBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
</faces-config>
8.2.
La gestion des messages
Comme vu lors du chapitre « 5.15 Message d’erreur », toutes les erreurs rencontrées sont remontés à
l’utilisateur via un système de message. De manière plus générale il est possible depuis n’importe quel
type de JavaBean (actionListener, convertisseur, validation, …) d’envoyer un message qui va être
affichée dans une page.
Un message JSF est représenté par la classe « javax.faces.application.FacesMessage ». Chaque
message possède un résumé de l’erreur (propriété « summary »), un détail de l’erreur (propriété
detail), et l’importance de l’erreur (propriété « severity »).
Les messages sont enregistrés dans l’application grâce à la méthode « addMessage(String clientId,
FacesMessage message) » de la classe FacesContext. Le paramètre « cliendId » permet de lier le
message à un composant, s’il est null, alors il s’agit d’un message global. Pour avoir un identifiant
valide, le plus simple est de récupérer directement l’identifiant du composant grâce à la méthode
« UIComponent.getId() ».
Voyons maintenant un exemple de création de message depuis un JavaBean.
Exemple :
package com.labosun.message;
import
import
import
import
javax.faces.application.FacesMessage;
javax.faces.component.UIInput;
javax.faces.context.FacesContext;
javax.faces.event.ActionEvent;
public class MessageBean {
private UIInput nameInput;
public UIInput getNameInput() {
return nameInput;
}
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
81
JSF - Framework Web
82 /
108
public void setNameInput(UIInput nameInput) {
this.nameInput = nameInput;
}
public void check(ActionEvent ae) {
FacesContext context = FacesContext.getCurrentInstance();
//Retrieve component id
String nameId = nameInput.getClientId(context);
FacesMessage f = new FacesMessage(FacesMessage.SEVERITY_WARN,
"Global message summary", "message from MessageBean");
context.addMessage(null, f);
FacesMessage f2 = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Specific message summmary",
"message from MessageBean and specific to component 'name'");
context.addMessage(nameId, f2);
}
La propriété « nameInput » va être liée à l’instance d’un composant pour pouvoir récupérer son
identifiant exact. La méthode check sert d’ActionListener. C’est elle qui génère les 2 messages « f »
et « f2 ». Le premier message est global puisqu’on n’utilise pas d’identifiant lors de l’ajout
« context ». Le deuxième message est spécifique au composant nameInput.
Pour lier la propriété « nameInput » avec le composant de type champ texte de la page JSF, il faut
utiliser l’attribut « binding ».
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<html>
<head>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<f:view>
<h:messages globalOnly="true" showDetail="false" showSummary="true"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
<h:form>
<h:inputText id="name" size="10" binding="#{messageBean.nameInput}">
<h:outputLabel for="name" value="Name:" />
</h:inputText>
<h:message for="name"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
<h:commandButton value="Valider" actionListener="#{messageBean.check}"/>
<br />
<h3>List</h3>
<h:messages showDetail="true" showSummary="true"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
82
JSF - Framework Web
83 /
108
<h3>Table</h3>
<h:messages showDetail="true" showSummary="false" layout="table"
styleClass="errorTable" errorClass="error"
infoClass="info" fatalClass="fatal" warnClass="warn" />
</h:form>
</f:view>
</body>
</html>
Dernière étape, il faut enregistrer le JavaBean dans le fichier « faces-config.xml ».
<managed-bean>
<managed-bean-name>messageBean</managed-bean-name>
<managed-bean-class>com.labosun.message.MessageBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
8.2.1. Refaire les messages
Les messages d’erreurs par défaut ne correspondent pas toujours à votre application. Heureusement il
est possible de les modifier.
En JSF 1.2, tous les composants qui héritent de UIInput permettent de personnaliser les messages très
facilement grâce à 3 attributs :
•
« converterMessage », référence le message à afficher quand la valeur du composant ne peut
pas être convertie par le convertisseur référencé par ce composant.
•
« requiredMessage », référence le message à afficher quand aucune valeur n'a été entrée
•
« validatorMessage », référence le message à utiliser quand la valeur saisie ne peut pas être
validée par le validateur référencé par ce composant.
Pour tous les autres messages et pour JSF 1.1, les messages d'erreurs par défaut se trouvent dans le
fichier de propriétés « Message_fr.properties » qui se trouvent dans le package « java.faces » du jar
« jsf-impl.jar ». Il est possible de redéfinir ces messages en créant un nouveau fichier de propriétés qui
va redéfinir les clefs utilisées. Ce nouveau fichier peut être placé n’importe où dans votre application.
On va ensuite le référencer pour qu’il remplace le fichier par défaut.
Par exemple, nous allons créer le fichier « MyDefaultMessages_fr.properties » dans lequel nous allons
copier les chaînes du fichier original: « Message_fr.properties ».
javax.faces.component.UIInput.REQUIRED=Erreur de validation : Vous devez indiquer une
valeur.
javax.faces.validator.LengthValidator.MAXIMUM=Erreur de validation : la valeur est
sup\u00e9rieure \u00e0 la valeur maximale autoris\u00e9e, ''{0}''
Vous remarquerez que tous les caractères spéciaux sont unicode. Dans ces messages, la syntaxe
« {0} » permet d’insérer un paramètre. Ce mécanisme utilise la classe MessageFormat.
Nous allons maintenant mettre les messages suivants :
javax.faces.component.UIInput.REQUIRED= Message personnalisé: Ce champ est obligatoire.
javax.faces.validator.LengthValidator.MAXIMUM=Message personnalisé: La valeur ''{0}'' est
sup\u00e9rieure \u00e0 la valeur maximale pour ce champ
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
83
JSF - Framework Web
84 /
108
La dernière étape pour que ce fichier soit utilisé à la place du fichier par défaut est de référencer votre
fichier dans le fichier de configuration de JSF. Cela se fait à l'aide de la balise <application>.
<faces-config>
<application>
<locale-config>
<default-locale>fr</default-locale>
</locale-config>
<message-bundle>MyDefaultMessages</message-bundle>
</application>
</faces-config>
8.3.
Intégration JSF et application JEE
La nouvelle spécification JEE 5 apporte des annotations qui peuvent être utilisé pour interagir avec les
couches plus basses de votre application grâce au principe de l’injection. C’est-à-dire que l’on va
déclarer une variable qui va être instanciée par le conteneur. Il faut un serveur conforme à JEE 5 pour
utiliser ces annotations.
8.3.1. Injection de ressource
L’injection de ressource permet par exemple de récupérer une instance du contexte JNDI courant. Elle
s’utilise grâce à l’annotation « @Resource ».
Exemple :
@Resource
private SessionContext ctx;
Lors du déploiement de l’application, la variable « ctx » sera initialisée.
8.3.2. Injection d’EJB
L’injection d’EJB permet de récupérer une instance de l’interface Local ou Remote. Elle s’utilise
grâce à l’annotation « @EJB ».
Exemple :
@EJB
private Store store;
Il est aussi possible d’utiliser l’injection de ressource pour récupérer une instance sur le contexte JNDI
courant et ensuite y rechercher l’EJB.
Exemple :
@Resource
private SessionContext ctx;
Store store = (Store)ctx.lookup("Store");
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
84
JSF - Framework Web
85 /
108
8.3.3. Injection de WebService
Il est possible de récupérer un WebService qui hérite de « javax.xml.ws.Service ». L’injection s’utilise
grâce à l’annotation « @WebServiceRef ».
Exemple :
@WebServiceRef
public StockQuoteService stockQuoteService;
8.3.4. Injection d’unité de persistance
Il est possible de récupérer une instance d’un EntityManager.
Comme en EJB3, l’injection se fait grâce à l’annotation « @PersistenceContext ». Le champ
« unitName » permet de renseigner le nom de l’unité de persistance à utiliser. Pour être valide, ce nom
doit être déclaré dans le fichier « persistence.xml ».
Exemple :
@PersistenceContext(unitName="InventoryManagement")
EntityManager em;
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
85
JSF - Framework Web
86 /
108
9. Facelets
9.1.
Introduction
JSF a été conçu pour fonctionner avec JSP, mais il est évident qu’il existe de nombreux problèmes
quand on mélange les 2. Rien que le langage unified EL doit être utilisé de 2 manières différentes en
fonction du contexte JSP ou JSF (syntaxe ${} et #{}).
Facelets vise à créer un jeu de balise qui s’accorde bien avec JSF et apporte également une nouvelle
manière d’écrire du code JSF. Il n’apporte pas de nouveaux mécanismes internes à JSF, mais se
contente de faciliter l’écriture du code en permettant notamment de créer des templates de code.
Facelets fonctionne avec les implémentations de JSF 1.1 et 1.2 de Sun et Apache MyFaces.
Facelets fournit également les améliorations suivantes :
•
La possibilité de créer des pages en plusieurs fichiers.
•
Un affichage plus précis des erreurs.
•
Création rapide de balises personnalisées
•
Configuration simple
•
Permet d’utiliser les balises JSF sous forme de balise HTML standard (attribut jsfc, voir le
chapitre « 9.3.2 JSFC »)
Pour bien comprendre ce qu’apporte Facelets il faut revenir au cycle de vie d’une page Web. JSF a été
conçu pour être modulable, ce qui veut dire qu’il est possible de changer certains composants dans le
fonctionnement de JSF. Facelets se charge de remplacer le composant qui se charge de la vue, c’est-àdire de la phase « Restauration de la vue » et « Rendu de la réponse » dans le cycle de vie. Les autres
phases du cycle de vie restent inchangées.
Voici un rappel du cycle de vie, les parties en jaune sont les parties gérées par Facelets.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
86
JSF - Framework Web
87 /
108
Grâce au contrôle de ces 2 phases, toute la syntaxe des fichiers peut être modifiée et entièrement
repensée par Facelets.
9.2.
Configuration
Dans ce chapitre, nous allons voir comment installer et configurer Facelets pour l’utiliser dans un
projet.
9.2.1. Installation
Tout d’abord vous devez télécharger la dernière implémentation de Facelets à l’adresse :
https://facelets.dev.java.net/servlets/ProjectDocumentList?folderID=3635&expandFolder=3635&folde
rID=3635
Ce cours est basé sur la version « 1.1.11 ».
Il faut ensuite décompresser l’archive et récupérer le fichier « jsf-facelets.jar ». Dans le cas où vous
n’utiliseriez pas un serveur JEE 5, il faut aussi prendre les fichiers « el-api.jar » et « el-ri.jar » qui se
trouvent dans le répertoire « lib ».
9.2.2. Structure d’un projet
Facelets respecte la même structure qu’une application JSF standard. La seule différence va être
l’extension des pages Web, qui est « .xhtml ». Cette extension n’est pas obligatoire, mais la syntaxe de
Facelets respecte le format XHTML, il est donc plus logique d’utiliser cette extension.
La structure d’un fichier War reste la même que pour JSF. Voici ce que cela donne :
WEB-INF/classes
Contient toutes les classes java (les JavaBeans entre autre)
WEB-INF/lib
Toutes les librairies (jar) nécessaires au projet.
La librairie de Facelets : « jsf-facelets.jar »
Eventuellement : « el-api.jar » et « el-ri.jar »
WEB-INF/faces-config.xml
Fichier de configuration
WEB-INF/web.xml
*.xhtml
A la racine, il faut placer toutes les pages « .xhtml ». Ce sont
les pages Facelets.
9.2.3. Configuration
Nous allons maintenant voir les modifications à apporter au fichier « faces-config.xml » et
« web.xml » pour pouvoir utiliser Facelets.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
87
JSF - Framework Web
88 /
108
Tout d’abord nous allons définir l’extension « .xhtml » comme extension des pages. Comme vu lors
du chapitre « 6.3 Paramètres de contexte », il faut utiliser le paramètre de contexte
« javax.faces.DEFAULT_SUFFIX ».
<web-app>
<!-- Extension .xhtml pour les pages JSF-->
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<!-- Paramètre spécifique à Facelets. Utile pour le développement -->
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
Dans les exemples qui vont suivre, c’est le mapping en mode suffixe « .jsf » qui est utilisé. Ceci
permet d’appeler une page en remplaçant l’extension « .xhtml » par « .jsf ». Pour rappel, voici
comment le déclarer :
<web-app>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
</web-app>
Il faut maintenant que la Servlet JSF passe à la main à Facelets pour la gestion de la vue. Cela se fait
dans le fichier « faces-config.xml » :
<faces-config>
<application>
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>
</faces-config>
Grâce à cette configuration, la gestion de la vue (création de l’arbre des composants JSF, rendu de la
réponse) sera gérée par Facelets et non plus par l’implémentation de JSF.
9.3.
Concepts de base
9.3.1. Structure d’une page
La structure des pages respecte le format XHTML. Voici un premier exemple de page Facelets.
Hello.xhtml :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
88
JSF - Framework Web
89 /
108
<?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"
xmlns:f="http://java.sun.com/jsf/core">
<body>
<h:outputText value="Hello" />
#{param.f}
</body>
</html>
La première différence par rapport à une page JSF classique est que la déclaration des taglibs est
différente. Ici on déclare toutes les librairies sous forme de namespaces depuis la balise <html>.
L’expression « xmlns:ui=http://java.sun.com/jsf/facelets » permet d’utiliser toutes les balises de
Facelets. Tandis que les 2 suivantes permettent d’utiliser les librairies de JSF.
Il n’y a pas de balise <f:view>. Enfin il est possible d’utiliser une expression EL directement dans du
code HTML. Par exemple le code « #{param.f} » affiche directement la valeur du paramètre « f ».
Si on exécute cette page en passant le paramètre « f=Facelets » dans l’url, alors On obtient le texte :
Hello Facelets
Par exemple, si « JSFCoursFacelets » est le contexte du projet et « Hello.jsf » est le nom de la page. Il
faut utiliser l’url : http://localhost:8080/JSFCoursFacelets/Hello.jsf?f=Facelets.
9.3.2. JSFC
Un des problèmes qui se pose avec les balises JSF est que les éditeurs ne savent pas tous rendre une
page de manière graphique. Par contre la plupart des éditeurs de code savent afficher une page HTML.
Une des possibilités qu’offre Facelets pour pouvoir afficher le résultat d’une page sous forme HTML
et sans qu’elle soit exécutée sur un serveur. Ceci se fait grâce à l’attribut « jsfc ».
Voyons un exemple :
<?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"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Formulaire avec JSFC</title>
</head>
<body>
<form jsfc="h:form">
<input id="name" type="text" jsfc="h:inputText"
value="#{bean.name}" required="true">
<label for="name">Nom :</label>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
89
JSF - Framework Web
90 /
108
</input>
<h:message for="name" />
<br />
<button type="submit" jsfc="h:commandButton" value="Valider" />
</form>
</body>
</html>
Prenons la balise <form jsfc="h:form">, Facelets va se charger de l’interpréter en tant que balise
<h:form>, mais du point du vue d’un éditeur de code il s’agit d’une simple balise <form>. L’attribut
« jsfc » sert à définir le type réel de la balise. L’avantage ici de pouvoir travailler avec des balises
HTML standard ce qui permet d’afficher la page de manière graphique dans un simple éditeur.
Les attributs spécifiques à une balise JSF doivent être rajouté à la balise HTML. Un éditeur HTML va
très certainement indiquer que l’attribut n’existe pas pour cette balise, mais cela va fonctionner
correctement pour Facelets. C’est le cas de l’attribut « required » pour la balise <input>.
Pour les balises JSF qui n’ont pas d’équivalent en HTML comme la balise <h:message> par exemple,
il faut l’inclure directement dans le code.
On obtient ainsi un mélange de balises HTML et JSF, sans oublier qu’on peut toujours rajouter des
expressions EL directement dans le code HTML.
9.3.3. Template
Un template est du code Facelets qui peut être réutilisé. C’est un modèle qu’on peut appliquer à
volonté dans un site. C’est un petit peu l’équivalent d’une balise, sauf qu’un template s’écrit de
manière très simple et est plus facilement modulable. Une page qui utilise un template est appelée
« page appelante ». Nous verrons par la suite qu’il existe plusieurs manières d’utiliser un template.
Cette partie du cours se concentre uniquement sur la déclaration basique d’un template.
Tout fichier Facelets peut servir de template. Par défaut, c’est l’ensemble d’une page qui définit le
template.
Template1.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"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title> </title>
</head>
<body>
</body>
</html>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
90
JSF - Framework Web
91 /
108
Ici la page entière est considérée comme un template.
Pour n’utiliser qu’une portion de code comme template, il faut utiliser la balise <ui:composition>.
Template2.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"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title> </title>
</head>
<body>
<ui:composition>
Partie de template
</ui:composition>
</body>
</html>
Ici seul le corps de la balise <ui:composition> sert de template, la partie grisée est ignorée.
Une des manière d’utiliser un template est d’utiliser à nouveau la balise <ui:composition> à la
différence que son attribut « template » doit préciser le nom du fichier de template à utiliser.
TemplateUtilisation.xhtml :
<!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"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title> </title>
</head>
<body>
<ui:composition template="Template1.xhtml">
</ui:composition>
</body>
</html>
Le résultat de cet exemple va être que le contenu de la page « template1.xhtml » sera affiché chez le
client. Cet exemple est plutôt limité vu qu’il est équivalent à une inclusion de page. Nous verrons dans
le prochain chapitre comment créer et utiliser des templates modifiables.
Dans cette exemple, toutes les balises de la page qui utilisent le template sont ignorées. Ce
comportement est spécifique à la balise <ui:composition>, le chapitre « 9.5 Balises Facelets » présente
d’autres balises pour utiliser des templates.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
91
JSF - Framework Web
9.4.
92 /
108
Templating de vue
Maintenant que nous avons la syntaxe de base de Facelets et le concept de template, nous allons
pouvoir voir en pratique ce que cela permet de faire.
Un des problèmes le plus courant lors de la création d’un site Web est que chaque page doit redéfinir
l’ensemble de la mise en page du site. C’est-à-dire redéfinir le titre, le menu, le pied de page, ... . Or
ces éléments sont souvent les mêmes pour toutes les pages du site. Il est plus pratique de ne les
déclarer qu’une seule fois et qu’ils soient ensuite intégrés directement aux autres pages.
Facelets permet de faire cela grâce à son système de template. Voyons avec un premier exemple
comme ça fonctionne.
Tout d’abord il faut écrire la page de template. C’est elle qui décrit la structure du site et les éléments
que les autres pages peuvent modifier. Dans notre exemple, nous allons créer un site qui contient un
en-tête, un menu, un corps et un pied de page.
MainTemplate.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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>
<ui:insert name="Title">Default title</ui:insert>
</title>
</head>
<body>
<div style="background: cornflowerblue; position: absolute; left: 0%; right: 0%; bottom:
95%; top: 0%">
<ui:insert name="Header">
<ui:include src="Header.xhtml" />
</ui:insert>
</div>
<div style="background: darksalmon; position: absolute; left: 0%; right: 90%; bottom: 5%;
top: 5%;">
<ui:insert name="Menu">
<a href="">Default Menu 1</a><br />
<a href="">Default Menu 2</a><br />
<a href="">Default Menu 3</a><br />
</ui:insert>
</div>
<div style="position: absolute; left: 10%; right: 0%; bottom: 5%; top: 5%;">
<ui:insert name="Body">
Default body
</ui:insert>
</div>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
92
JSF - Framework Web
93 /
108
<div style="background: lawngreen; position: absolute; left: 0%; right: 0%; bottom: 0%;
top: 95%">
<ui:insert name="Footer">
Default Footer
</ui:insert>
</div>
</body>
</html>
Il y a 2 balises spécifiques à Facelets dans cette page de template, <ui:insert> et <ui:include>. Tout
d’abord les balises <ui:insert>, ce sont elles qui permettent de définir les parties modifiables du
template. Chaque balise utilise un nom qui sert à identifier une partie.
Dans le cas de la balise :
<ui:insert name="Footer">
Default Footer
</ui:insert>
Elle définit toute la partie du pied de page qui est modifiable. Le texte « Defautl Footer » est le texte
qui s’affiche par défaut, lorsqu’une autre page va utiliser ce template sans modifier le pied de page.
Pour la balise :
<ui:insert name="Header">
<ui:include src="Header.xhtml" />
</ui:insert>
Elle ne définit pas directement l’en-tête par défaut, mais importe un fichier qui va contenir le texte par
défaut. L’import se fait avec la balise <ui:include>.
HeaderTemplate.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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<ui:composition>
Default Header
</ui:composition>
</body>
</html>
Cette page contient le code par défaut de l’en-tête. La balise <ui:composition> sert à définir un bloc de
code qui peut être réutilisé dans d’autres pages. En fait, tout le code qui se trouve autour de la balise
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
93
JSF - Framework Web
94 /
108
<ui:composition> est ignoré, c’est-à-dire qu’il ne va jamais apparaître dans la page HTML que reçoit
le client. Ce comportement est dû à la balise <ui:include> qui ignore le reste de la page dès qu’elle
trouve une balise <ui:composition>. Nous verrons plus en détail le principe d’inclusion dans le
chapitre « 9.5.5 Include ».
Notre template est maintenant prêt, nous pouvons créer la page qui va utiliser ce template.
PageMain.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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Page principale</title>
</head>
<body>
<ui:composition template="MainTemplate.xhtml">
<!-Une balise define doit correspondre à une balise <ui:insert> du template
<ui:define name="Title">Page principale</ui:define>
-->
<ui:define name="Footer">Pied de page</ui:define>
<ui:define name="Body">Corps de la page main redéfini</ui:define>
</ui:composition>
</body>
</html>
La balise <ui:composition> :
<ui:composition template="MainTemplate.xhtml">
...
</ui:composition>
utilise l’attribut « template ». Dans ce cas, elle ne sert pas à déclarer un template (comme dans
HeaderTemplate.xhtml) mais à préciser qu’on veut utiliser un bloc de code existant.
Dans notre cas, on commence par prendre tout le code de la page de l’attribut « template »,
« MainTemplate.xhtml ». Ensuite on remplace les parties modifiables (corps des balises <ui:insert>)
par le contenu des balises <ui:define>. Ici on ne modifie que les parties « Title », « Footer » et
« Body ». L’ordre des balises « define » n’a pas d’importance. Il n’est pas obligatoire de redéfinir des
parties.
Si « JSFCoursFacelets » est le contexte du projet, cette page est accessible à l’adresse :
http://localhost:18080/JSFCoursFacelets/PageMain.jsf
Voici ce que donne cette page de manière graphique :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
94
JSF - Framework Web
95 /
108
Attention :
Dans la dernière page « PageMain.xhtml », toutes les balises <ui:define> qui se trouve en dehors de la
première balise <ui:composition> sont ignorées. De plus tout le code qui ne se trouve pas à l’intérieur
de balises <ui:define> valide est également ignoré. C’est-à-dire que le code suivant va générer la
même page HTML. Toutes les parties grisées ne sont pas incluses dans la page HTML que reçoit le
client.
<?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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Page principale</title>
</head>
<body>
<!-- balise ignoré -->
<ui:define name="Title">Titre non pris en compte</ui:define>
<!-- Seule balise composition valide -->
<ui:composition template="MainTemplate.xhtml">
<!-- balise define valide -->
<ui:define name="Title">Page principale</ui:define>
Ce texte est ignoré
<!-- balise define valide -->
<ui:define name="Footer">Pied de page</ui:define>
<!-- balise define valide -->
<ui:define name="Body">Corps de la page main redéfini</ui:define>
</ui:composition>
<!-- balise ignoré -->
<ui:define name="Menu">Menu non pris en compte</ui:define>
<!-- cette balise composition est complètement ignoré -->
<ui:composition template="MainTemplate.xhtml">
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
95
JSF - Framework Web
96 /
108
<ui:define name="Menu">Menu</ui:define>
<ui:define name="Body">
Encore le Corps
</ui:define>
</ui:composition>
</body>
</html>
Le fonctionnement des différentes balises sera revu en détail dans la suite du cours. Il est possible en
repartant de cet exemple de créer un squelette de page que vous pouvez réutiliser comme vous voulez.
9.5.
Balises Facelets
9.5.1. Composition
La balise <ui:composition> permet :
•
soit de définir une zone de template
•
soit d’utiliser un template en y apportant des modifications éventuelles (utilisation de l’attribut
« template »)
9.5.1.1.
Définition de template
Prenons le premier cas pour définir une zone de template. Exemple :
<ui:composition>
Partie réutilisable
</ui:composition>
Il est possible d’utiliser les balises <ui:insert> et pour définir quelles zones du template sont
modifiables.
9.5.1.2.
Utilisation de template
Un template peut s’utiliser avec la balise <ui:composition>. Dans ce cas, l’attribut « template » doit
définir l’url vers le fichier de template à utiliser. L’utilisation de template suit les règles suivantes :
•
Si le fichier de template contient une ou plusieurs balises <composition> alors seulement le
corps de la première balise est pris en compte.
•
Sinon c’est toute la page qui est prise en compte.
Dans tous les cas, le code qui se trouve autour de la balise <composition> dans la page appelante n’est
pas inclus dans la réponse finale.
Voir le chapitre « 9.4 Templating de vue » pour un exemple d’utilisation de cette balise où seulement
la page appelante utilise la balise <ui:composition>. Nous allons ici voir un 2ème exemple où la page de
template et la page appelante utilisent une balise <ui:composition>.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
96
JSF - Framework Web
9.5.1.3.
97 /
108
Exemple
TemplateAvecComposition.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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<ui:composition>
<div style="...">
<ui:insert name="Header">Header</ui:insert>
</div>
<div style="...">
<ui:insert name="Body">Default body</ui:insert>
</div>
</ui:composition>
</body>
</html>
UtiliseTemplateAvecComposition.xhtml :
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Page principale</title>
</head>
<body>
<ui:composition template="TemplateAvecComposition.xhtml">
<ui:define name="Header">En-tête</ui:define>
<ui:define name="Body">Corps de la page main redéfini</ui:define>
</ui:composition>
</body>
</html>
Le résultat sera :
<div style="...">
En-tête
</div>
<div style="...">
Corps de la page main redéfini
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
97
JSF - Framework Web
98 /
108
</div>
Ici on voit bien que tout ce qui est autour des balises <ui:composition> est ignoré.
9.5.2. Insert
La balise <ui:insert> s’utilise dans un template. Elle permet de définir une portion de code qui peut
être remplacé. L’attribut « name » permet de donner un nom à la portion. Le remplacement est ensuite
effectué par la balise <ui:define> qui possède elle aussi un attribut « name ». Il suffit de faire
correspondre les 2, pour effectuer un remplacement.
Exemple :
<ui:insert name="Partie1">
Partie modifiable
</ui:insert>
Il est également possible d’utiliser la balise sans spécifier de nom. Dans ce cas c’est tout le corps de la
balise qui utilise le template qui sera inclus.
Exemple sans nom :
ParagrapheTemplate.xhtml :
Début paragraphe
<ui:insert />
Fin paragraphe
Page.xhtml :
<ui:composition template="Paragraphe.xhtml">
Milieu du paragraphe
</ui:composition>
La page générée sera :
Début paragraphe
Milieu du paragraphe
Fin paragraphe
9.5.3. Define
La balise <ui:define> permet de remplacer le contenu d’une balise <ui:insert>. Elle possède l’attribut
obligatoire « name » qui doit correspondre au nom d’une balise <ui:insert>.
9.5.4. Decoration
La balise <ui:decorate> permet d’utiliser un template. Elle fonctionne comme la balise
<ui:composition> sauf que tout le code de la page appelante est inclus dans la réponse.
Nous avons la même page de template que dans le chapitre « 9.5.1.3 Exemple ».
TemplateAvecComposition.xhtml :
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
98
JSF - Framework Web
99 /
108
<?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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<ui:composition>
<div style="...">
<ui:insert name="Header">Header</ui:insert>
</div>
<div style="...">
<ui:insert name="Body">Default body</ui:insert>
</div>
</ui:composition>
</body>
</html>
UtiliseTemplateAvecDecoration.xhtml :
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Page principale</title>
</head>
<body>
<ui:decorate template="TemplateAvecComposition.xhtml">
<ui:define name="Header">En-tête</ui:define>
<ui:define name="Body">Corps de la page main redéfini</ui:define>
</ui:decorate>
</body>
</html>
Le résultat sera :
<!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">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Page principale</title>
</head>
<body>
<div style="...">
En-tête
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
99
JSF - Framework Web
100 /
108
</div>
<div style="...">
Corps de la page main redéfini
</div>
</body>
</html>
9.5.5. Include
La balise <ui:include> permet d’inclure une page Facelets. Elle possède l’attribut obligatoire « src »
qui désigne la page à inclure. Le nom de la page peut être écrit directement ou il peut s’agir d’une
expression EL.
Exemple qui permet d’inclure la page « Footer.xhtml » :
<ui:include src="Footer.xhtml" />
L’inclusion suit les règles suivantes :
•
Si le fichier à inclure contient une ou plusieurs balises <composition> alors seulement
l’intérieur de la première balise est pris en compte.
•
Sinon c’est toute la page qui est prise en compte.
Ce mécanisme est intéressant car une page peut quand même définir la balise <html> avec tous les
namespace, ce qui permet de l’éditer dans un éditeur.
9.5.6. Param
La balise <ui:param> permet de passer des paramètres à un bloc de code Facelets. Elle peut s’utiliser à
l’intérieur des balises <ui:define> et <ui :include>.
Elle possède les 2 attributs obligatoires :
•
name
•
value
9.5.7. Remove
La balise <ui:remove> permet de ne pas tenir compte de tout le code qui se trouve dans son corps.
C’est comme si on mettait en commentaire tout un bloc de code (comme pour /* et */). Mais cette
solution présente l’avantage de ne pas avoir à mettre chaque ligne de code en commentaire.
Exemple :
<body>
<h:outputText value="affiché" />
<ui:remove>
<h:outputText value="Pas affiché" />
<form>
<%-- <h:outputText value="Encore pas affiché" /> --%>
<!-- <input type="text" /> -->
<button type="submit" />
</form>
</ui:remove>
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
100
101 /
108
JSF - Framework Web
<h:outputText value="affiché" />
</body>
Ici toute la partie à l’intérieur de <ui:remove> n’est pas prise en compte.
9.5.8. Component
La balise <ui:component> est identique à <ui:composition>, sauf tout le corps de la balise est inclus
dans un composant JSF qu’on peut utiliser. Pour l’utiliser il faut passer par l’attribut « bindings ».
9.5.9. Fragment
La balise <ui:fragment> est identique à la balise <ui:component> dans son fonctionnement, mais tout
comme la balise <ui:decorate>, les balises de la page appelante seront incluses dans la réponse finale.
9.5.10.
Balises JSTL et Fonctions
Facelets propose une implémentation des taglibs JSTL Core et des fonctions.
9.5.10.1. JSTL Core
Pour utiliser les balises JSTL Core,
« xmlns:c="http://java.sun.com/jstl/core" ».
il
faut
déclarer
le
namespace
suivant :
<c:if>
Attribut
Obligatoire
Description
test
Oui
Expression à évaluer. Si l’expression vaut true alors le corps de cette
balise est pris en compte sinon il est ignoré. Une expression null vaut
false.
var
non
Variable qui doit contenir le résultat du test de l’expression.
Exemple :
<c:if test="#{user.roles['admin']}">
</c:if>
<c:forEach>
Attribut
Description
items
Une expression qui pointe sur la Collection, la Map ou le tableau à parcourir.
var
Contient l’élément actuel qu’on parcourt
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
101
JSF - Framework Web
begin
Index à partir duquel il faut commencer l’itération.
end
Index à partir duquel il faut finir l’itération.
step
La valeur dont l’index augmente à chaque itération.
varStatus
Pointe sur un objet qui contient les propriétés suivantes :
•
boolean first,
•
boolean last,
•
int begin,
•
int end,
•
int index,
•
int step,
102 /
108
<c:set>
Attribut
Description
var
value
La variable qui va contenir la valeur de l’attribut « value ».
L’expression qui va déterminer la valeur de la variable. Cette expression sera réutilisée à
chaque fois que la variable est utilisée. C’est-à-dire qu’il n’y a pas copie de cette valeur
dans la variable désignée par l’attribut « var ».
9.5.10.2. Fonctions
Pour utiliser les fonctions il faut déclarer le namespace suivant :
« xmlns:fn="http://java.sun.com/jsp/jstl/functions" ».
9.6.
Templating de composants
9.6.1. Le problème
Malgré la simplicité de JSF, il existe de nombreux cas où l’on est obligé de répéter du code qui se
ressemble beaucoup. C’est le cas pour tout ce qui est présentation, comme nous l’avons vu lors du
chapitre « 9.4 Templating de vue », mais le problème peut aussi se poser pour tout ce qui est
composants personnels.
9.6.2. La solution avec Facelets
Grâce à son système de template, facelets va permettre de créer une balise que l’on va utiliser comme
un composant. Cette balise va se charger de générer tout le code des différents duplicata, la seule
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
102
JSF - Framework Web
103 /
108
chose qu’il faudra lui fournir est la liste des attributs qui peuvent changer entre plusieurs duplicata de
code.
CaseComponent.xhtml :
<!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"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<head>
<title></title>
</head>
<body>
<!-- Paramètres:
- columnName: Nom de la colonne
- sortMethod: Nom de la méthode du bean qui permet de trier la colonne
- bean: bean qui contient la méthode de tri
- caseValue: Valeur de la case
-->
<ui:composition>
<h:column>
<f:facet name="header">
<h:panelGroup>
<!-- Si la méthode est triable, le nom est un lien qui permet de la trier
-->
<c:if test="#{!empty sortMethod}">
<h:commandLink action="#{bean[sortMethod]}">
<h:outputText value="#{columnName}" />
</h:commandLink>
</c:if>
<!-- Sinon on affiche juste son nom -->
<c:if test="#{empty sortMethod}">
<h:outputText value="#{columnName}" />
</c:if>
</h:panelGroup>
</f:facet>
<h:outputText value="#{caseValue}" />
</h:column>
</ui:composition>
</body>
</html>
9.6.3. TagFile
Pour utiliser ce template de composant à l’aide d’une balise, il faut le déclarer dans fichier de
déclaration. Le fichier doit porter l’extension « .taglib.xml ».
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
103
JSF - Framework Web
104 /
108
labo-sun.taglib.xml :
<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"facelet-taglib_1_0.dtd">
<facelet-taglib>
<namespace>http://www.labo-sun.com/jsf</namespace>
<tag>
<tag-name>case</tag-name>
<source>CaseComponent.xhtml</source>
</tag>
</facelet-taglib>
Cette déclaration va permettre d’utiliser notre template avec une balise de type :
<case columnName="" sortMethod="" caseValue="" bean="" />
Les attributs de la balise sont déterminés à partir des variables qui sont utilisées dans la page de
template.
Pour que Facelets charge ce fichier, il faut ajouter la déclaration suivante dans le fichier web.xml.
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
/WEB-INF/facelets/tags/arcmind.taglib.xml
</param-value>
</context-param>
Déclaration
<managed-bean>
<managed-bean-name>beanTable</managed-bean-name>
<managed-bean-class>com.labosun.facelets.BeanTable</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
public class BeanTable {
private List<Person> persons;
private static Comparator<Person> personLastNameComparator =
new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return o1.getLastName().compareTo(o2.getLastName());
}
};
private static Comparator<Person> personFirstNameComparator =
new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return o1.getFirstName().compareTo(o2.getFirstName());
}
};
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
104
105 /
108
JSF - Framework Web
public BeanTable() {
persons = new ArrayList<Person>();
persons.add(new Person("Bob", "Gnoliac"));
persons.add(new Person("Thomas", "Anderson"));
persons.add(new Person("Raymond", "Smith"));
}
//Getter et setter
public void sortByFirstName() {
Collections.sort(getPersons(), personFirstNameComparator);
}
public void sortByLastName() {
Collections.sort(getPersons(), personLastNameComparator);
}
}
Voilà, notre balise est prête à être utilisée. La déclaration se fait à l’aide de namespace de la manière
suivante :
<?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"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:m="http://www.labo-sun.com/jsf">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Test column template</title>
</head>
<body>
<h:form>
<h:dataTable value="#{beanTable.persons}" var="person" border="1" rules="all">
<m:case columnName="Last name" sortMethod="sortByLastName"
caseValue="#{person.lastName}" bean="#{beanTable}" />
<m:case columnName="First name" sortMethod="sortByFirstName"
caseValue="#{person.firstName}" bean="#{beanTable}" />
</h:dataTable>
</h:form>
</body>
</html>
Voici le résultat final:
Tri par nom
Tri par prénom
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
105
JSF - Framework Web
9.7.
106 /
108
Paramètres
Paramètres
Description
facelets.LIBRARIES
Liste des chemins vers des librairies de tags Facelets séparées par
des « ; ». Les chemins sont relatifs à la racine de l’application.
Une librairie n’est chargée que lorsque la page qui l’utilise doit
être compilé.
Exemple :
/WEB-INF/facelets/my.taglib.xml;
/WEB-INF/facelets/car.taglib.xml;
facelets.DECORATORS
Une liste de classes (séparées par des ‘ ;’) du type
« com.sun.facelets.tag.TagDecorator » avec un constructeur par
défaut. Ces décorateurs seront chargés lorsque la première
requête atteindra la vue « FaceletViewHandler ».
Exemple :
com.sun.facelets.tag.jsf.html.HtmlDecorator
facelets.DEVELOPMENT
Si true alors des informations de debugging sont affichées sur la
page Web lorsqu’il y a une erreur.
La valeur par défaut est false.
facelets.BUFFER_SIZE
La taille du buffer utilisée par le ResponseWriter.
Attention, une taille trop petite de buffer ne permet pas d’afficher
toute une page.
Par défaut, la valeur de -1 permet de ne pas mettre de limite de
taille.
facelets.REFRESH_PERIOD
Permet de définir l’intervalle de temps minimum que doit
attendre le compilateur avant de vérifier si une page doit être
recompilée (s’il y a eu des changements).
La valeur de -1 permet d’empêcher le compilateur de vérifier s’il
y a eu des changements une fois que la page est compilée.
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
106
JSF - Framework Web
107 /
108
La valeur par défaut est 2.
facelets.RESOURCE_RESOLVER Permet de spécifier un ResourceResolver personnalisé.
La valeur par défaut est :
com.sun.facelets.impl.DefaultResourceResolver
facelets.VIEW_MAPPINGS
Une liste d’url (séparées par des ‘ ;’) qui seront gérées par
Facelets. Si rien n’est précisé, toutes les requêtes sont gérées par
Facelets. Dans le cas où une url, n’est pas gérée par Facelets,
c’est la vue du parent par défaut (JSP) qui est utilisée.
Attention si vous spécifiez des url, le mapping vers la Servlet
FacesServlet, doit être mappé pour plusieurs types de fichiers.
Ex : /faces/*;*.xhtml
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
107
JSF - Framework Web
108 /
108
10. Bibliographie
La documentation des balises JSF se trouve à l’adresse :
JSF 1.1 : http://java.sun.com/j2ee/javaserverfaces/1.1/docs/tlddocs/index.html
JSF 1.2 : http://java.sun.com/j2ee/javaserverfaces/1.2/docs/tlddocs/index.html
La javadoc de l’API JSF se trouve à l’adresse :
JSF 1.1 : http://java.sun.com/j2ee/javaserverfaces/1.1/docs/api/index.html
JSF 1.2 : http://java.sun.com/j2ee/javaserverfaces/1.2/docs/api/index.html
Le tutorial de SUN sur J2EE 1.4 et qui inclut un tutorial sur JSF 1.1 est à l’adresse :
http://java.sun.com/j2ee/1.4/docs/tutorial/doc/index.html
Le tutorial de SUN sur JEE 5 et qui inclut un tutorial sur JSF 1.2 est à l’adresse :
http://java.sun.com/javaee/5/docs/tutorial/doc/index.html
Le site de Facelets :
https://facelets.dev.java.net/
Le site de MyFaces :
http://myfaces.apache.org/index.html
Oracle ADF :
http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf/index.html
http://www.labo-sun.com
Ce document est la propriété de Supinfo et est soumis aux règles de droits d’auteurs
108
Téléchargement