Introduction à JSF 2.0 (Java Server Faces) Université de Nice - Sophia Antipolis Richard Grin Version 0.3.2 – 10/7/11 Adaptation / tri sélectif : Michel Buffa Plan (1) Présentation Cycle de vie Java EE 6 Une application Web Rappels sur HTTP Page JSF Fichiers de configuration Implémentations de JSF (librairies JSF) Code d’une page JSF 21/10/99 Richard Grin JSF - page 2 Plan (2) Langage EL Composants standards Navigation Portées (requête, session,…) Beans Utilisation des EJB Ajax 21/10/99 Richard Grin JSF - page 3 Remarque Ce support est une introduction à JSF 2.0 utilisé dans un cadre Java EE 6, avec un serveur d’applications du type de Glassfish, et CDI (Contexts and Dependency Injection) 21/10/99 Richard Grin JSF - page 4 Présentation 21/10/99 Richard Grin JSF - page 5 Utilité de JSF Créer des pages Web dynamiques Par exemple, une page Web qui est construite à partir de données enregistrées dans une base de données Une grande partie de la programmation liée à la validation des données saisies par l’utilisateur et de leur passage au code de l’application est automatisée ou grandement facilitée Ajax sans programmation 21/10/99 Richard Grin JSF - page 6 JSF Framework MVC qui reprend le modèle des interfaces utilisateurs locales (comme Swing) Le modèle est représenté par des classes Java, les Java beans, sur le serveur Les vues sont représentées par des composants Java sur le serveur, transformées en pages HTML sur le client Le contrôleur est un servlet qui intercepte les requêtes HTTP liées aux applications JSF et qui organise les traitements JSF (implicite) 21/10/99 Richard Grin JSF - page 7 Autres possibilités Java D’autres solutions que JSF peuvent être utilisées pour créer des pages Web dynamiques : JSPs (aujourd’hui officiellement plus conseillées) Utilisation de bibliothèques javascript / HTML5 / Servlets ou Web Services REST GWT (Google Web Tollkit) JRuby on rail Etc 21/10/99 Richard Grin JSF - page 8 Autres solutions hors Java PHP Ruby on Rails Python / Pyjama etc (ROR en Python) ASP (Microsoft) ColdFusion (Macromedia) Flash – Flex ??**?? (avenir très sombre ?) 21/10/99 Richard Grin JSF - page 9 Services rendus par JSF (1/2) Architecture MVC pour séparer l’interface utilisateur, la couche de persistance et les processus métier, utilisant la notion d’événement Conversion des données (tout est texte dans l’interface utilisateur) Validation des données (par exemple, des champs de formulaires requis) Automatisation de l’affichage des messages d’erreur en cas de problèmes de conversion ou de validation 21/10/99 Richard Grin JSF - page 10 Services rendus par JSF (2/2) Internationalisation Support d’Ajax sans programmation (communication en arrière-plan et mise à jour partielle de l’interface utilisateur) Fournit des composants standards simples pour l’interface utilisateur Possible d’ajouter ses propres composants Adaptable à d’autres langages de balise que HTML (WML par exemple pour les téléphones portables) 21/10/99 Richard Grin JSF - page 11 Standards JSF 2.0 est intégré dans Java EE 6 JSF 2.0 s’appuie sur les standards suivants : n n n n Servlet 2.5 -> JSF et les Servlets ça marche bien ! Java SE 5.0 Java EE 5.0 JSTL 1.1 -> ATTENTION PAS CONSEILLE !!! JSF 2.0 peut (c’est conseillé) utiliser CDI (Contexts and Dependency Injection) n 21/10/99 Annotations @EJB, @Inject etc. Richard Grin JSF - page 12 Le cycle de vie 21/10/99 Richard Grin JSF - page 13 Pour bien comprendre JSF il est indispensable de bien comprendre tout le processus qui se déroule entre le remplissage d’un formulaire par l’utilisateur et la réponse du serveur sous la forme de l’affichage d’une nouvelle page 21/10/99 Richard Grin JSF - page 14 21/10/99 Richard Grin JSF - page 15 21/10/99 Richard Grin JSF - page 16 Le servlet « Faces » Toutes les requêtes vers des pages « JSF » sont interceptées par un servlet défini dans le fichier web.xml de l’application Web <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class> javax.faces.webapp.FacesServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> 21/10/99 Richard Grin JSF - page 17 URL des pages JSF Les pages JSF sont traitées par le servlet parce que le fichier web.xml contient une configuration telle que celle-ci : <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> Le pattern est souvent aussi de la forme *.faces (les pages dont l’URL se termine par .faces sont considérées comme des pages JSF) 21/10/99 Richard Grin JSF - page 18 Codage - décodage Les pages HTML renvoyées par une application JSF sont représentées par un arbre de composants Java L’encodage est la génération d’une page HTML à partir de l’arbre des composants Le décodage est l’utilisation des valeurs renvoyées par un POST HTML pour donner des valeurs aux variables d’instance des composants Java, et le lancement des actions associées aux « UICommand » JSF (boutons ou liens) 21/10/99 Richard Grin JSF - page 19 Cycle de vie Le codage/décodage fait partie du cycle de vie des pages JSF Le cycle de vie est composé de 6 phases Ces phases sont gérées par le servlet « Faces » qui est activé lorsque qu’une requête demande une page JSF (correspond au pattern indiqué dans le fichier web.xml ; le plus souvent /faces/* ou *.faces) 21/10/99 Richard Grin JSF - page 20 21/10/99 Richard Grin JSF - page 21 Demande page HTML Etudions tout d’abord le cas simple d’une requête d’un client qui demande l’affichage d’une page JSF 21/10/99 Richard Grin JSF - page 22 La vue Cette requête HTTP correspond à une page JSF (par exemple *.faces) et est donc interceptée par le servlet Faces La page HTML correspondant à la page JSF doit être affichée à la suite de cette requête HTTP La page HTML qui sera affichée est représentée sur le serveur par une « vue » Cette vue va être construite sur le serveur et transformée sur le serveur en une page HTML qui sera envoyée au client 21/10/99 Richard Grin JSF - page 23 Contenu de la vue Cette vue est un arbre dont les éléments sont des composants JSF (composants Java) qui sont sur le serveur (des instances de classes qui héritent de UIComponent) Sa racine est de la classe UIViewRoot 21/10/99 Richard Grin JSF - page 24 Construction vue et page HTML Une vue formée des composants JSF est donc construite sur le serveur (ou restaurée si elle avait déjà été affichée) : phase « Restore View » Puisqu’il n’y a pas de données ou d’événements à traiter, la vue est immédiatement rendue : le code HTML est construit à partir des composants de la vue et envoyé au client : phase « Render Response » 21/10/99 Richard Grin JSF - page 25 Traitement d’un formulaire Nous allons cette fois-ci partir d’une requête HTTP générée à partir d’une page HTML qui contient un formulaire (page construite à partir d’une page JSF) L’utilisateur a saisi des valeurs dans ce formulaire Ces valeurs sont passées comme des paramètres de la requête HTTP ; par exemple, http://machine/page.xhtml?nom=bibi&prenom=bob si la requête est une requête GET, ou dans l’entité d’un POST 21/10/99 Richard Grin JSF - page 26 21/10/99 Richard Grin JSF - page 27 Phase de restauration de la vue La vue qui correspond à la page qui contient le formulaire est restaurée (phase « Restore View ») Tous les composants reçoivent la valeur qu’ils avaient avant les nouvelles saisies de l’utilisateur 21/10/99 Richard Grin JSF - page 28 21/10/99 Richard Grin JSF - page 29 Phase d’application des paramètres Tous les composants Java de l’arbre des composants reçoivent les valeurs qui les concernent dans les paramètres de la requête HTTP : phase « Apply Request Values » Par exemple, si le composant texte d’un formulaire contient un nom, le composant Java associé conserve ce nom dans une variable En fait, chaque composant de la vue récupère ses propres paramètres dans la requête HTTP 21/10/99 Richard Grin JSF - page 30 21/10/99 Richard Grin JSF - page 31 Phase de validation Toutes les validations des données traitées à l’étape précédentes sont exécutées Les données sont converties dans le bon type Java Si une validation échoue, la main est donnée à la phase de rendu de la réponse 21/10/99 Richard Grin JSF - page 32 Phase de validation Comment c’est fait : chaque composant valide et convertit les données qu’il contient Si un composant détecte une valeur non valable, il met sa propriété « valid » à false et il met un message d’erreur dans la file d’attente des messages (ils seront affichés lors de la phase de rendu « render response ») et les phases suivantes sont sautées 21/10/99 Richard Grin JSF - page 33 21/10/99 Richard Grin JSF - page 34 Phase de mise à jour du modèle Si les données ont été validées, elles sont mises dans les variables d’instance des Java beans associés aux composants de l’arbre des composants 21/10/99 Richard Grin JSF - page 35 21/10/99 Richard Grin JSF - page 36 Phase d’invocation de l’application Les actions associées aux boutons ou aux liens sont exécutées Le plus souvent le lancement des processus métier se fait par ces actions La valeur de retour de ces actions va déterminer la prochaine page à afficher (navigation) 21/10/99 Richard Grin JSF - page 37 21/10/99 Richard Grin JSF - page 38 Phase de rendu de la réponse La page déterminée par la navigation est encodée en HTML et envoyée vers le client HTTP 21/10/99 Richard Grin JSF - page 39 Sauter des phases Il est quelquefois indispensable de sauter des phases du cycle de vie Par exemple, si l’utilisateur clique sur un bouton d’annulation, on ne veut pas que la validation des champs de saisie soit effectuée, ni que les valeurs actuelles soient mises dans le modèle Autre exemple : si on génère un fichier PDF à renvoyer à l’utilisateur et qu’on l’envoie à l’utilisateur directement sur le flot de sortie de la réponse HTTP, on ne veut pas que la phase de rendu habituelle soit exécutée 21/10/99 Richard Grin JSF - page 40 immediate=true sur un UICommand Cet attribut peut être ajouté à un bouton ou à un lien (<h:commandButton>, <h:commandLink>, <h:button> et <h:link>) pour faire passer directement (immédiatement) de la phase « Apply request values » à la phase « Invoke Application » (en sautant donc les phases de validation et de mise à jour du modèle) Exemple : un bouton d’annulation d’un formulaire 21/10/99 Richard Grin JSF - page 41 immediate=true sur un EditableValueHolder Cet attribut peut être ajouté à un champ de saisie, une liste déroulante ou des boîte à cocher pour déclencher immédiatement la validation et la conversion de la valeur qu’il contient, avant la validation et la conversion des autres composants de la page Utile pour effectuer des modifications sur l’interface utilisateur sans valider toutes les valeurs du formulaire 21/10/99 Richard Grin JSF - page 42 Exemple Formulaire qui contient champ de saisie du code postal et un champ de saisie de la ville Lorsque le code postal est saisi, un ValueChangeListener met automatiquement à jour la ville : <h:inputText valueChangeListener="#{…}" ... onChange = "this.form.submit()" /> La soumission du formulaire déclenchée par la modification du code postal ne doit pas lancer la validation de tous les composants du formulaire qui ne sont peut-être pas encore saisis 21/10/99 Richard Grin JSF - page 43 Une application Web 21/10/99 Richard Grin JSF - page 44 21/10/99 Richard Grin JSF - page 45 Etapes du développement Ecrire le code des pages JSF et des backing beans (Tester en local en déployant sur un container Web) Déployer sur le container Web final Taper l’adresse de l’application pour tester 21/10/99 Richard Grin JSF - page 46 Structures des fichiers 21/10/99 Richard Grin JSF - page 47 Fichier de distribution L’application doit être distribuée sous la forme d’un fichier war (fichier de format jar) Elle peut être une partie d’un projet de type entreprise, dans ce cas l’application est encore un .war mais contenu dans le .ear du projet global (le .ear contient la partie web dans le .war, la partie EJB dans un ou plusieurs .jar) 21/10/99 Richard Grin JSF - page 48 Rappels sur HTTP 21/10/99 Richard Grin JSF - page 49 Requête HTTP Le protocole HTTP permet à un client HTTP d’envoyer plusieurs types de requêtes à un serveur Les 2 types de base principaux sont les types GET et POST GET permet au client de demander une page HTML POST permet au client de passer des données au serveur 21/10/99 Richard Grin JSF - page 50 Réponse du serveur HTTP En réponse à une requête d’un client HTTP, un serveur HTTP renvoie au client une réponse 21/10/99 Richard Grin JSF - page 51 Format d’une requête La première ligne contient le type de la requête (GET par exemple), suivi de l’URI qui désigne le destinataire de la requête, suivi du numéro de la version HTTP utilisée Ensuite peuvent venir des lignes facultatives (entêtes) pour indiquer la configuration du client ou des formats de documents acceptés en réponse En dernier la requête peut contenir une « entité » composée de données qui pourront être utilisées par le serveur (essentiellement réservé à la requête POST) ; ligne vide avant l’entité 21/10/99 Richard Grin JSF - page 52 Format d’une réponse Une première ligne d’état qui contient la version HTTP utilisée, le code d’état (nombre ; par exemple, 200 indique que tout s’est bien passé) et la description du code (« OK » pour 200) Viennent ensuite des lignes d’en-têtes (comme pour la requête du client) Finalement, le corps de la réponse est envoyé ; il peut s’agir du contenu d’un fichier HTML ou d’un contenu généré par un programme du serveur 21/10/99 Richard Grin JSF - page 53 GET La fonctionnalité de base de HTTP est de permettre à un navigateur (client HTTP) de récupérer et d’afficher une page Web Pour cela le client envoie une requête GET au serveur Cette requête contient l’URL de la page Web avec, éventuellement, des paramètres (couples clé-valeur) La réponse contient le plus souvent un corps qui est le code d’une page HTML 21/10/99 Richard Grin JSF - page 54 Exemple de requête GET GET page.html?nom=Toto&Prenom=Pierre HTTP/1.1 Accept: */* Host: www.unice.fr User-Agent: Generic 21/10/99 Richard Grin JSF - page 55 POST Certaines pages Web contiennent des questionnaires remplis par l’utilisateur du navigateur Lorsque l’utilisateur clique sur le bouton « Submit », les données qu’il a tapées sont envoyées au serveur par une requête POST Cette requête contient l’URI du code qui va traiter les données, ainsi que les données La réponse du serveur contient le code de la prochaine page à afficher par le navigateur 21/10/99 Richard Grin JSF - page 56 Exemple de POST POST /appl/client.xhtml HTTP/1.1 Accept: */* Host: www.unice.fr nom=Toto Prenom=Pierre 21/10/99 Richard Grin JSF - page 57 Formulaires HTML Une page HTML peut contenir un formulaire (<FORM>) Lorsque ce formulaire est soumis au serveur (bouton de type « submit »), les données entrées dans le formulaire sont transmises au serveur par une requête POST ou une requête GET Avec GET, les valeurs saisies sont intégrées à l’URI ; avec POST elles sont mises dans l’entité C’est l’attribut name des balises qui donne le nom des paramètres de la requête 21/10/99 Richard Grin JSF - page 58 Page JSF 21/10/99 Richard Grin JSF - page 59 Les pages JSF contiennent des balises qui décrivent les composants qui représenteront la page sur le serveur 21/10/99 Richard Grin JSF - page 60 Une page JSF Code XHTML Contient des parties en EL : #{…} Utilise souvent une (ou plusieurs) bibliothèque de composants JSF Sera traduite en XHTML « pur » pour être envoyée au client Web 21/10/99 Richard Grin JSF - page 61 Architecture des applications JSF 21/10/99 Richard Grin JSF - page 62 JSF, servlets et beans Dans l’architecture des applications qui utilisent JSF, on trouve aussi des servlets et des beans Les servlets et les beans s’occupent principalement des traitements métier et des accès aux données Les pages JSF sont utilisées pour l’interface avec l’utilisateur 21/10/99 Richard Grin JSF - page 63 Répartition des tâches Les pages JSF ne contiennent pas de traitements (pas de code Java ou autre code comme dans les pages JSP, « ancien langage » de JSF pour créer les pages affichées à l’utilisateur) Les traitements liés directement à l’interface utilisateur sont écrits dans les backing beans Ces backing beans font appels à des EJB ou des classes Java ordinaire pour effectuer les traitements qui ne sont pas liés directement à l’interface utilisateur Note : on peut très bien faire des pages JSF, du EL et des Servlets… mais c’est considéré « bas nioveau » Attention : pas de JSTL !!! 21/10/99 Richard Grin JSF - page 64 Répartition des tâches (2) Les EJB sont chargés de traitements métier et des accès aux bases de données Les accès aux bases de données utilisent JPA et des classes entités 21/10/99 Richard Grin JSF - page 65 Beans 2 types principaux de beans : n EJB (essentiellement des beans sessions) liés aux processus métier n « Backing beans » associés aux pages JSF et donc à l’interface utilisateur qui font la liaison entre les composants JSF de l’interface, les valeurs affichées ou saisies dans les pages JSF et le code Java qui effectue les traitements métier 21/10/99 Richard Grin JSF - page 66 Backing bean Souvent, mais pas obligatoirement, un backing bean par page JSF Voir support de cours sur les Backing Beans n n n n n 21/10/99 Variables pour les propriétés, Variable pour stocker des résultats de traitement, Des méthodes get/set pour les propriétés, Des méthodes de traitement (qu’on appelle « command handlers », Des écouteurs d’évènements… Richard Grin JSF - page 67 EJB Un backing bean fournit du code Java pour l’interface graphique Lorsqu’un processus métier doit être déclenché, le backing bean cède la main à un EJB Un EJB est totalement indépendant de l’interface graphique ; il exécute les processus métier ou s’occupe de la persistance des données Les entités JPA 2 sont utilisées par les EJB pour la persistance des données 21/10/99 Richard Grin JSF - page 68 Container pour les JSF Pour qu’il sache traiter les pages JSF, le serveur Web doit disposer d’un container pour ces pages On peut utiliser pour cela un serveur d’applications du type de Glassfish, JBoss, WebSphere, WebLogic, OAS.. Tomcat (projet Apache) est une solution plus légère pour traiter les pages JSF n n n 21/10/99 Mais attention, Tomcat n’est PAS un serveur d’applications, Pas d’applications distribuées, pas de transactions distribuées, etc Ne contient pas toutes les bibliothèques J2EE par défaut Richard Grin JSF - page 69 Paquetage et classes principales Les paquetages javax.servlet, javax.serlet.http, javax.servlet.jsp etc. ne sont pas fournis avec la distribution standard de Java (SDK) Ils sont dans la distribution « entreprise » (qui est installée avec la version de netbeans qu’on utilise. On peut aussi les récupérer à part pour les utiliser avec la distribution standard ; c'est le cas si on décide d’utiliser Tomcat. 21/10/99 Richard Grin JSF - page 70 Fichiers de configuration 21/10/99 Richard Grin JSF - page 71 Les différents fichiers WEB-INF/web.xml fichier global de configuration d’une application Web Java WEB-INF/faces-config.xml : configuration de la partie JSF de l’application, par exemple pour indiquer la navigation entre les pages ou pour déclarer les beans utilisés par les pages ; plus indispensable avec JSF 2.0 grâce aux annotations Java 21/10/99 Richard Grin JSF - page 72 Annotations et fichier faces-config.xml JSF 2.0 a développé l’emploi des annotations des classes pour configurer son fonctionnement Le fichier XML l’emporte sur les annotations, ce qui permet de changer la configuration même si on n’a pas le code source (ou d’éviter de recompiler si on a le code source) 21/10/99 Richard Grin JSF - page 73 Les différents fichiers (2) Fichier WEB-INF/beans.xml, indispensable si CDI est utilisé ; il semble qu’un fichier beans.xml vide suffise à déclencher l’utilisation de CDI (attention, si ce fichier n’existe pas, CDI n’est pas utilisé, sans aucun message d’avertissement, et donc les @Inject ne fonctionnent pas) Fichiers de description des balises (tags) personnalisées dans le cas où des balises personnalisée sont utilisées (voir la section sur les composants personnalisés) n 21/10/99 Ex : vous faites vos composants, un lecteur vidéo par exemple. Richard Grin JSF - page 74 Implémentations de JSF – librairies JSF 21/10/99 Richard Grin JSF - page 75 Implémentations Implémentation de référence de JSF Librairies de composants 21/10/99 Richard Grin JSF - page 76 Implémentation de référence Projet Mojarra Fournit les composants de base et avec des fonctionnalités minimales De nombreuses librairies fournissent d’autres composants ou enrichissent les fonctionnalités des composants de l’implémentation de référence 21/10/99 Richard Grin JSF - page 77 Librairies de composants L’idéal serait que toutes les librairies de composants soient compatibles entre elles, ce qui permettrait de choisir ses composants dans plusieurs librairies Dans la réalité ça n’est pas toujours le cas et il vaut mieux bien choisir la librairie et s’y tenir Principales librairies : PrimeFaces, RichFaces, OpenFaces, Icefaces, ADF Faces 21/10/99 Richard Grin JSF - page 78 Code d’une page JSF 21/10/99 Richard Grin JSF - page 79 Structure globale d’une page Fichier xhtml tag html qui précise les namespaces utilisés En-tête de la page (h:header) qui permet d’indiquer les css, les include javascript, etc Le corps de la page (du XHTML et des tags JSF) Voir aussi les templates dans la une autre partie de ce cours. 21/10/99 Richard Grin JSF - page 80 Commentaires (1/2) Par défaut les commentaires HTML (<!-- -->) ne fonctionnent pas pour JSF Une solution est de configurer l’application pour que ces commentaires soient pris en compte par Facelets en ajoutant ceci dans web.xml : <context-param> <param-name>facelets.SKIP_COMMENTS </param-name> <param-value>true</param-value> </context-param> 21/10/99 Richard Grin JSF - page 81 Commentaires (2/2) Cependant, dans certains cas, des information mises dans des commentaires HTML peuvent être utilisés par l’application Le plus sûr est donc d’entourer ce que l’on veut commenter par le tag <ui:remove> On peut mettre ce tag dans tous les emplacements où on pourrait mettre un composant JSF 21/10/99 Richard Grin JSF - page 82 Langage EL (Expression Language) 21/10/99 Richard Grin JSF - page 83 Utilité Sert à relier des propriétés ou des méthodes de beans avec des valeurs de pages JSF Une expression EL est entourée par #{…} Exemple : <h:inputText value="#{utilisateur.nom}"/> lie la valeur du champ de saisie de texte avec la propriété « nom » du bean « utilisateur » 21/10/99 Richard Grin JSF - page 84 Composants standards 21/10/99 Richard Grin JSF - page 85 Librairies de balises Plusieurs librairies de balises peuvent être utilisées dans une page JSF (avec Facelets) : n n n n n n JSF Facelets, de préfixe ui JSF HTML, de préfixe h JSF core tag, de préfixe f JSTL core tag (version 1.1), de préfixe c JSTL functions tag (version 1.1), de préfixe fn Eviter JSTL ! Ces préfixes correspondent à des espaces de noms XML (URL à voir dans la documentation) 21/10/99 Richard Grin JSF - page 86 Il est impossible dans cette introduction de passer en revue toutes les balises standards offertes par Facelets De nombreux sites Web en donnent des exemples Documentation pour ces balises : http://download.oracle.com/javaee/6/javaserverfa ces/2.0/docs/pdldocs/facelets/ Dans cette section nous donnerons quelques conseils pour débuter 21/10/99 Richard Grin JSF - page 87 Quelques références Le tutoriel Java EE 6 d’Oracle est un bon site pour débuter : http://download.oracle.com/javaee/6/tutorial/doc/b narf.html 21/10/99 Richard Grin JSF - page 88 Types de composants 4 grands types : n Ceux qui contiennent une valeur (ValueHolder ou EditableValueHolder) ; un label ou un champ de saisie par exemple n Ceux qui proposent un choix à l’utilisateur (liste déroulante, boîtes à cocher, boutons radio,…) n Ceux qui lancent une action (ActionSource2) ; un bouton par exemple n Ceux qui correspondent à une structure itérative ; une datatable par exemple 21/10/99 Richard Grin JSF - page 89 Nous allons étudier un exemple de chaque type pour en illustrer les particularités Reportez-vous à la documentation de JSF ou de la librairie de composants que vous utilisez pour en savoir plus 21/10/99 Richard Grin JSF - page 90 Composants pour du texte Champ texte avec <h:inputText> (1 ligne) Saisie des mots de passe avec <h:inputSecret> Zone de texte de plusieurs lignes avec <h:inputTextarea> Image tutoriel Java EE 6 d’Oracle 21/10/99 Richard Grin JSF - page 91 Les listes Il y a plusieurs composants JSF standards qui permettent de proposer un choix (ou plusieurs) parmi une liste de valeurs Tous les composants sont bâtis sur des classes Java communes mais se présentent différemment à l’utilisateur 21/10/99 Richard Grin JSF - page 92 Listes à choix unique Boutons radios avec <h:selectOneRadio> Liste déroulante avec <h:selectOneMenu> Liste non déroulante avec <h:selectOneListbox> Image tutoriel Java EE 6 d’Oracle 21/10/99 Richard Grin JSF - page 93 Listes à choix multiple Boîtes à cocher avec <h:selectManyCheckbox> Liste déroulante avec <h:selectManyMenu> Liste non déroulante avec <h:selectManyListbox> Image tutoriel Java EE 6 d’Oracle 21/10/99 Richard Grin JSF - page 94 Les listes - Exemple <h:selectOneListbox value="#{bean.choix}"> <f:selectItem itemLabel="choix" itemValue="#{bean.option}" /> <f:selectItem itemLabel="autre choix" itemValue="false" /> <f:selectItems value="#{bean.options}"/> </h:selectOneListbox> Ce qui est désigné par f:selectItem et f:selectItems sera affiché dans la liste. Le choix fait par l’utilisateur parmi toutes ces valeurs, est rangé dans bean.choix (attribut value de selectOneListBox) Les entrées de la liste qui correspondent à l’attribut value sont présélectionnées dans la liste 21/10/99 Richard Grin JSF - page 95 Classe SelecItem Paquetage javax.faces.model Donne un label, une valeur et d’autres propriétés d’une liste de GUI Utilisée pour la valeur (attribut value) des tags <f:selectItem> et <f:selectItems> 21/10/99 Richard Grin JSF - page 96 <f:selecItems> Son attribut value peut désigner un tableau, une collection ou une map Le plus souvent, on part d’une liste d’éléments et on la transforme en tableau ou collection de SelectItem Le transparent suivant donne un schéma de code pour une telle transformation (souvent fourni sous la forme d’une méthode static utilitaire) 21/10/99 Richard Grin JSF - page 97 Schéma de code pour <f:selecItems> public static SelectItem[] getSelectItems(List<?> entities) { SelectItem[] items = new SelectItem[size]; for (Object x : entities) { items[i++] = new SelectItem(x, x.toString()); } return items; } 21/10/99 Richard Grin JSF - page 98 Autre façon de faire Pour éviter la complication de la transformation en SelectItem, on peut utiliser les attributs var, itemValue et itemLabel Exemple : <f:selectItems value="#{ecoleController.personnes}" var="personne" itemValue="#{personne.id}" itemLabel="#{personne.nom}"/> La variable « personne » contient un élément de la liste désignée par value 21/10/99 Richard Grin JSF - page 99 Chausse-trappes avec les listes Quelques chausse-trappes que l’on peut rencontrer avec les listes déroulantes sont exposées dans les transparents suivants En particulier avec les convertisseurs et les validateurs qui seront étudiés en détails dans la 2ème partie de ce cours sur JSF 21/10/99 Richard Grin JSF - page 100 Conversion pour les listes déroulantes Comment se fait la conversion entre les éléments d’une liste et ce qui est affiché ? Par exemple, une liste d’écoles et ce qui est affiché ? Il faut bien comprendre que le composant JSF va être transformé en élément(s) HTML et que toutes les valeurs vont être transformées en String ; en retour, une valeur choisie par l’utilisateur sera une String qu’il faudra éventuellement convertir en un autre type 21/10/99 Richard Grin JSF - page 101 Convertisseur Si le type T des éléments à choisir n’est pas String (ça peut, par exemple, être des pays de la classe Pays), il faut un convertisseur pour passer du type T à String (pour le passage en HTML) et vis-versa (pour le rangement du choix sous la forme d’une instance du type T) On aura un message d’erreur si on veut mettre une 1ère entrée du type « Choisissez un pays » car cette première entrée n’est pas du type T n 21/10/99 Solution : ne pas mettre cette première ligne ! Richard Grin JSF - page 102 Validation d’un choix dans une liste JSF vérifie que le choix qui est envoyé au serveur est bien un des choix proposés à l’utilisateur Ça implique que les choix proposés soient connus par JSF au moment de la validation Si les choix dépendent d’une propriété d’un backing bean (par exemple, un pays pour une liste de villes d’un certain pays), il faut donner la bonne portée au bean pour que les choix puissent être calculés correctement au moment de la validation (View ou Session par exemple) 21/10/99 Richard Grin JSF - page 103 <h:datatable> Très utilisé pour représenter les données d’une base de données : chaque ligne de la table correspond à une ligne d’une table Sera affiché comme une table HTML 21/10/99 Richard Grin JSF - page 104 Modèle de données Les données affichées sont représentées par un model : javax.faces.model.DataModel Souvent on n’utilise pas directement le modèle ; on fournit un tableau, une liste ou un ResultSet à l’attribut value de <h:datatable> ; en interne une classe fille de DataModel enveloppera les données fournies Quelquefois il faut expliciter l’utilisation de DataModel dans le backing bean de la page pour avoir plus de facilités de manipulation des données 21/10/99 Richard Grin JSF - page 105 DataModel Contient des méthodes pour récupérer les numéros des lignes, la valeur de la ligne « en cours » (un Object), gérer les écouteurs de la table 21/10/99 Richard Grin JSF - page 106 Exemple <h:datatable value="#{clientBean.all}" var="client"> <h:column> <f:facet name=header>Nom</f:facet> #{client.nom} </h:column> ... </datatable> 21/10/99 Richard Grin JSF - page 107 <ui:repeat> Permet de répéter un affichage sur une liste d’objets Exemple : <ul> <ui:repeat value="#{bean.clients}" var="item"> <li>#{item.nom}</li> </ui:repeat> </ul> 21/10/99 Richard Grin JSF - page 108 Navigation 21/10/99 Richard Grin JSF - page 109 Handler de navigation La navigation entre les pages indique quelle page est affichée quand l’utilisateur clique sur un bouton pour soumettre un formulaire ou quand il clique sur un lien Cette navigation est déléguée au « handler de navigation » La navigation peut être définie par des règles dans le fichier de configuration faces-config.xml ou par des valeurs écrites dans le code Java n 21/10/99 En général on s’en passe mais si on veut faire une navigation «logique » on peut utiliser les wizards de netbeans Richard Grin JSF - page 110 Navigation statique et dynamique La navigation peut être statique : définie « en dur » au moment de l’écriture de l’application La navigation peut aussi être dynamique : définie au moment de l’exécution par l’état de l’application (en fait par la valeur retournée par une méthode) 21/10/99 Richard Grin JSF - page 111 Dans les pages JSF Dans les pages JSF on indique la valeur ou la méthode associée à un bouton qui déterminera la navigation Avec une valeur : <h:commandButton value="Texte du bouton" action="valeur"/> Ou avec une méthode (qui retourne une valeur) : <h:commandButton value="Texte du bouton" action="#{nomBean.nomMethode}"/> 21/10/99 Richard Grin JSF - page 112 Modèle de navigation JSF, Le modèle GET - PRG 21/10/99 Richard Grin JSF - page 113 Par défaut, JSF travaille avec des requêtes POST Depuis JSF 2.0 il est plus simple de travailler avec des requêtes GET, ce qui facilite l’utilisation de l’historique et marque-pages (bookmarks) des navigateurs et évite des doubles validations de formulaire non voulues par l’utilisateur 21/10/99 Richard Grin JSF - page 114 Utiliser GET 2 composants de JSF 2.0 permettent de générer des requêtes GET : <h:button> et <h:link> 21/10/99 Richard Grin JSF - page 115 Le problème avec POST Avec une requête POST envoyée pour soumettre un formulaire n le refresh de la page affichée (ou un retour en arrière) après un POST soumet à nouveau le formulaire ; le navigateur prévient l’utilisateur en affichant une fenêtre popup inquiétante et difficile à comprendre pour l’utilisateur n l’adresse de la page affichée après le POST est la même que celle du formulaire (donc pas possible de faire réafficher cette page en utilisant l’historique du navigateur) 21/10/99 Richard Grin JSF - page 116 La raison du problème C’est le servlet qui intercepte les requêtes attachées aux pages JSF qui redirige vers la page désignée par le modèle de navigation JSF Le navigateur n’a pas connaissance de cette direction et pense être toujours dans la page qui contient le formulaire qui a été soumis On avait déjà le problème l’année dernière avec les HTTP forwarder dans les Servlets, mais cela ne vous a pas troublé outre mesure ;-) 21/10/99 Richard Grin JSF - page 117 Les conséquences du problème Le navigateur est en retard d’une page pour afficher l’URL de la page en cours Il ne garde donc pas la bonne adresse URL si l’utilisateur veut garder un marque-page Le navigateur pense être toujours dans la page qui contient le formulaire après un retour en arrière ou un refresh et il essaie de le soumettre à nouveau (il demande malgré tout une confirmation lors de la soumission multiple d’un formulaire) 21/10/99 Richard Grin JSF - page 118 La solution : POST, REDIRECT, GET (PRG) Le modèle POST– REDIRECT– GET préconise de n Ne jamais montrer une page en réponse à un POST n Charger les pages uniquement avec des GET n Utiliser la redirection pour passer de POST à GET 21/10/99 Richard Grin JSF - page 119 Sans PRG Cette image et la suivante viennent de Wikipedia 21/10/99 Richard Grin JSF - page 120 Avec PRG 21/10/99 Richard Grin JSF - page 121 Problème de PRG PRG peut poser un problème lorsque la page vers laquelle l’utilisateur est redirigée (le GET), doit afficher des données manipulées par le formulaire C’est le cas, par exemple, lorsque cette page est une page qui confirme l’enregistrement dans une base de données des informations saisies par l’utilisateur dans le formulaire En effet, les informations conservées dans la portée de la requête du POST ne sont plus disponibles 21/10/99 Richard Grin JSF - page 122 Solutions Une des solutions est de ranger les informations dans la session plutôt que dans la requête Cependant cette solution peut conduire à une session trop encombrée Une autre solution est de passer les informations d’une requête à l’autre JSF 2.0 offre 2 nouvelles possibilités qui facilitent la tâche du développeur : n la mémoire flash n les paramètres de vue 21/10/99 Richard Grin JSF - page 123 Paramètres de vue Les paramètres d’une vue sont définis par des balises <f:viewParam> incluses dans une balise <f:metadata> (à placer au début, avant les <h:head> et <h:body>) : <f:metadata> <f:viewParam name="n1" value="#{bean1.p1}" /> <f:viewParam name="n2" value="#{bean2.p2}" /> <f:metadata> 21/10/99 Richard Grin JSF - page 124 <f:viewParam> L’attribut name désigne le nom d’un paramètre de requête GET L’attribut value désigne (par une expression du langage EL) le nom d’une propriété d’un bean dans laquelle la valeur du paramètre est rangée Important : il est possible d’indiquer une conversion ou une validation à faire sur les paramètres, comme sur les valeurs des composants saisis par l’utilisateur 21/10/99 Richard Grin JSF - page 125 Un lien vers une page qui contient des balises <f:viewParam> contiendra tous les paramètres indiqués par les <f:viewParam> s’il contient « includeViewParams=true » Exemple : <h:commandButton value=… action="page2?faces-redirect=true &amp;includeViewParams=true" 21/10/99 Richard Grin JSF - page 126 Fonctionnement de includeViewParams La page de départ a un URL qui a le paramètre includeViewParams 2. Elle va chercher les <f:viewParam> de la page de destination. Pour chacun, elle ajoute un paramètre à la requête GET en allant chercher la valeur qui est indiquée par l’attribut value du <f:viewParam> 1. 3. A l’arrivée dans la page cible, la valeur du paramètre est mise dans la propriété du bean indiquée par l’attribut value 21/10/99 Richard Grin JSF - page 127 Fonctionnement de includeViewParams Ca revient à faire passer une valeur d’une page à l’autre Si la portée du bean est la requête et qu’il y a eu redirection, ça revient plus précisément à faire passer la valeur d’une propriété d’un bean dans un autre bean (de la même classe) 21/10/99 Richard Grin JSF - page 128 Donner une valeur à un paramètre Il y a plusieurs façons de donner une valeur à un paramètre de requête GET ; les voici dans l’ordre de priorité inverse (la dernière façon l’emporte) n n n 21/10/99 Dans la valeur du outcome <h:link outcome="page?p=4&amp;p2=‘bibi’ " …> <h:link outcome="page?p=#{bean.prop + 2} " …> Avec les paramètres de vue <h:link outcome="page" includeViewParams="true" …> Avec un <f:param> <h:link outcome="page" includeViewParams="true" …> <f:param name=p value=…/> </h:link> Richard Grin JSF - page 129 Exemple ; page2.xhtml <!DOCTYPE …> <html xmlns="http://www.w3.org/1999/xhtml" xmlns=...> <f:metadata> <f:viewParam name="param1" value="#{bean.prop1}"/> <f:viewParam name="param2" value="#{…}"/> </f:metadata> <h:head>…</h:head> <h:body> Valeur : #{bean.prop1} 21/10/99 Richard Grin JSF - page 130 Fonctionnement Si page2 est appelé par la requête GET suivante page2.xhtml?param1=v1&param2=v2 la méthode setProp1 du bean est appelée avec l’argument v1 (idem pour param2 et v2) Si un paramètre n’apparait pas dans le GET, la valeur du paramètre de requête est null et le setter n’est pas appelé (la propriété du bean n’est donc pas mise à null) 21/10/99 Richard Grin JSF - page 131 Conserver des adresses utiles Outre le fait qu’un refresh ne provoque plus de soumission du formulaire, le modèle PRG permet aussi de permettre de conserver un URL utile dans un marque-page ou dans l’historique En effet, l’URL contient les paramètres qui permettront de réafficher les mêmes données à un autre moment Sans PRG, les données utiles sont conservées dans l’entité de la requête et pas dans l’URL 21/10/99 Richard Grin JSF - page 132 preRenderView Listener (1) Une situation courante : il est possible de ne mettre en paramètre qu’un identificateur des données qui ont été traitées Par exemple, que la clé primaire des données enregistrées dans la base de données Avec les procédés précédents on peut faire passer cet identificateur dans la page qui va afficher les données 21/10/99 Richard Grin JSF - page 133 preRenderView Listener (2) Mais ça ne suffit pas ; il faut utiliser une autre nouveauté de JSF 2.0, les listeners « preRenderView » qui permet d’exécuter une action avant l’affichage de la vue On peut ainsi aller rechercher (par exemple dans une base de données) les informations identifiées par l’identificateur 21/10/99 Richard Grin JSF - page 134 Exemple de preRenderView <f:metadata> <f:viewParam name="id" value="#{bean.IdClient}"/> <f:event type="preRenderView" listener="#{bean.chargeClient}"/> </f:metadata> ... Nom : #{bean.client.nom} ... 21/10/99 Richard Grin JSF - page 135 Portées 21/10/99 Richard Grin JSF - page 136 Les différentes portées (scope) Application Session Requête Conversation Vue Personnalisée (custom) 21/10/99 Richard Grin JSF - page 137 Les différentes portée peuvent conserver des objets dans des maps 21/10/99 Richard Grin JSF - page 138 Lorsqu’une valeur est référencée dans une page Web, la valeur est d’abord recherchée dans le scope le plus « proche » : requête, vue, session, application, etc 21/10/99 Richard Grin JSF - page 139 Mettre une valeur dans une portée Cours à venir… voir support de cours sur les backing beans (à venir lui aussi) 21/10/99 Richard Grin JSF - page 140 Mémoire flash Il est bon de limiter la taille des informations entreposées dans la session Cependant la portée « request » peut ne pas convenir, en particulier s’il y a redirection de la requête (par exemple pour appliquer le modèle POST – REDIRECT – GET) La mémoire « flash » peut alors convenir : un objet mis dans la mémoire flash est encore disponible dans la prochaine requête issue de la même session ; il est ensuite effacé automatiquement de la mémoire flash 21/10/99 Richard Grin JSF - page 141 Utiliser la mémoire flash (page Web) Dans une page Web, avec le langage EL (flash est un objet implicite du langage) : #{flash.objet} 21/10/99 Richard Grin JSF - page 142 Utiliser la mémoire flash (en Java) Dans le backing bean par ex : il faut récupérer le contexte externe : ExternalContext ec = FacesContext.getCurrentInstance() .getExternalContext().getFlash(); qui renvoie un objet de la classe Flash (de javax.faces.context) qui se manipule comme une session (comme une map) dont la clé est une String et la valeur est un Object Par exemple, ec.getFlash().put("nom", nom); 21/10/99 Richard Grin JSF - page 143 Exemple <h:form> <h:inputText value="#{flash.nom}" .../> ... <h:commandButton value="Enregistrer" action="confirm?faces-redirect=true" /> </form> Page confirm.xhtml : <h:form> <h:outputText value="#{flash.nom}" .../> ... 21/10/99 Richard Grin JSF - page 144 keep Il est possible de garder l’objet pour une requête de plus grâce à la méthode keep de la classe Flash #{flash.keep.objet} renvoie l’objet qui a la clé « objet » et garde l’objet pour encore une requête de plus Dans le code Java, il faut le faire en 2 étapes : récupérer la valeur et remettre dans le flash pour la prochaine requête en appelant la méthode keep qui ne renvoie rien (void comme type retour). 21/10/99 Richard Grin JSF - page 145 Backing beans 21/10/99 Richard Grin JSF - page 146 Dans la section « Architecture des applications JSF » on a vu que les pages JSF sont épaulées par des backing beans qui apportent la puissance du langage Java pour coder des interactions sophistiquées avec l’utilisateur Les possibilités sont infinies Dans cette section nous allons voir quelques exemples caractéristiques de l’utilisation des backing beans 21/10/99 Richard Grin JSF - page 147 Plus de code dans les pages JSF Pour ceux qui ont travaillé avec JSP, il faut oublier la mauvaise habitude d’inclure de la programmation dans les pages JSF Tout le code (non « métier ») doit maintenant se trouver dans les backing beans (le code métier doit se trouver dans les EJB ou classes Java liées) 21/10/99 Richard Grin JSF - page 148 EJB 21/10/99 Richard Grin JSF - page 149 Pour plus de détails, se référer au cours sur les EJB Nous allons voir ici quelques utilisations caractéristiques des EJB par le code des backing beans 21/10/99 Richard Grin JSF - page 150 Ajax 21/10/99 Richard Grin JSF - page 151 Ajax Asynchronous Javascript and XML Permet des échanges entre le client et le serveur Web sans affichage d’une page entière Les requêtes envoyées par le client sont lancées « en arrière-plan » ; l’utilisateur peut continuer à travailler avec la page en cours La réponse du serveur à la requête peut ne modifier qu’une partie de la page en cours 21/10/99 Richard Grin JSF - page 152 <f:ajax> Pemet d’ajouter des fonctionnalités « Ajax » au composant JSF dans lequel il est inclus Par exemple, un bouton de soumission de formulaire peut envoyer une requête et la réponse du serveur mettra à jour une partie de la page sur laquelle l’utilisateur a continué à travailler 21/10/99 Richard Grin JSF - page 153 <f:ajax> - les attributs event : événement déclencheur de la requête execute : composants pris en compte pour l’envoi de la requête (espace séparateur) render : composants mis à jour au moment de la réponse du serveur (espace séparateur) 21/10/99 Richard Grin JSF - page 154 Exemple 1 <h:form> <h:input value= /> <h:commandButton> <f:ajax event="click" execute="@form" listener="#{bean.ajaxListener} " render="out1 out2" /> </h:commandButton> <h:input id="out1" …/> <h:input id="out2" …/> </h:form> 21/10/99 Richard Grin JSF - page 155 Exemple 2 <h:form> <h:input value="#{bean.***" /> <h:selectOneMenu value="#{bean.selected}"> <f:selectItems value="#{bean.items}" /> <f:ajax event="change" execute="@form" listener="#{bean.ajaxListener}" render="@form" /> </h:selectOneMenu> ... </h:form> 21/10/99 Richard Grin JSF - page 156 Compléments sur les attributs Chaque type de composant a un type d’événement par défaut Par exemple, valueChange pour les <h:inputText> ou action pour les <h:commandButton> 21/10/99 Richard Grin JSF - page 157 Compléments sur les attributs execute et render doivent indiquer un ou plusieurs identificateurs de composants Quelques valeurs particulières : @all, @this (le composant qui englobe <f:ajax> ; défaut pour execute), @form (tous les composants du formulaire), @none (défaut pour render) ; on peut aussi donner une expression EL qui fournit une collection de String (qui désignent des identificateurs) ; expression évaluée durant le rendu de la page 21/10/99 Richard Grin JSF - page 158 Composants inclus dans <f:ajax> <f:ajax> peut aussi encadrer plusieurs composants JSF qui lanceront alors des appels Ajax sur les événements indiqués : <f:ajax …> <h:panelGrid …> <h:inputText …/> <h:commandButton …/> </panelGrid ….> </ajax> 21/10/99 Richard Grin JSF - page 159 Conversion 21/10/99 Richard Grin JSF - page 160 Utilité des converters Quand le serveur reçoit une requête POST, les valeurs saisies par l’utilisateur arrivent sous la forme de chaînes de caractères Ces chaînes doivent souvent être traduites en objets Java Par exemple, si un candidat à une formation a indiqué sa nationalité par une liste déroulante, ce choix doit être traduit en un objet Pays qui sera associé à l’objet Candidat qui représente l’utilisateur 21/10/99 Richard Grin JSF - page 161 Désigner un convertisseur Lorsqu’un composant a besoin d’un convertisseur, on peut le désigner n par une sous-balise <f:converter> en donnant l’identificateur du convertisseur : <f:converter converterId=xxx> n par l’attribut converter du composant <h:outputText value=xxx converter=yyy/> n Par une sous-balise spéciale pour les convertisseurs standards 21/10/99 Richard Grin JSF - page 162 Convertisseur par défaut On verra qu’il est aussi possible d’associer un convertisseur par défaut pour un type Ce convertisseur par défaut sera utilisé si aucun convertisseur n’est explicitement désigné Une erreur est lancée si aucun convertisseur n’est donnée par son identificateur et qu’aucun convertisseur par défaut n’existe pour le type 21/10/99 Richard Grin JSF - page 163 Convertisseurs standards JSF fournit des convertisseurs pour les types primitifs, pour les dates et pour les classes BigInteger et BigDecimal Des balises spéciales sont fournies par JSF pour les convertisseurs standards mais on peut aussi utiliser la balise <f:convert> en donnant l’identificateur du convertisseur standard Par exemple, <f:convertDateTime/> est équivalent à <f:convert convertId="javax.faces.DateTime"/> 21/10/99 Richard Grin JSF - page 164 Exemples <inputText value="#{employe.salaire}"> <f:convertNumber type="currency"/> </inputText> <outputText value="#{employe.salaire}"> <f:convertNumber type="currency"/> </outputText> <inputText value="#{employe.dateNaissance}"> <f:convertDateTime pattern="dd/MM/yyyy"/> </inputText> 21/10/99 Richard Grin JSF - page 165 Convertisseur personnalisé Le développeur doit écrire les convertisseurs associés aux types qui ne sont pas pris en charge par les convertisseurs standards de JSF (custom converter) Il faut n écrire la classe Java du convertisseur n indiquer quand utiliser le convertisseur 21/10/99 Richard Grin JSF - page 166 Écrire un convertisseur Classe Java qui implémente l’interface Converter (paquetage javax.faces.convert) Cette interface contient les 2 méthodes n Object getAsObject(FacesContext, UIComponent, String) qui transforme une chaîne de caractères en objet n String getAsString(FacesContext, UIComponent, Object) qui transforme un objet en chaîne de caractères 21/10/99 Richard Grin JSF - page 167 Comme pour un validateur, il n’est pas possible d’utiliser @Inject dans un convertisseur Mais on peut écrire ce type de code pour utiliser un EJB ou une ressource : try { ic = new InitialContext(); myejb= (MyEJB) ic .lookup("java:global/xxxx/MyEJB"); } catch (NamingException e) { … } 21/10/99 Richard Grin JSF - page 168 Désigner un convertisseur Lorsqu’un composant doit utiliser un convertisseur, si aucun convertisseur particulier n’est désigné par son identificateur c’est le convertisseur par défaut du type qui est utilisé Pour désigner un convertisseur particulier ou un convertisseur par défaut d’un type, le développeur peut utiliser une annotation ou écrire une configuration dans le fichier faces-config.xml 21/10/99 Richard Grin JSF - page 169 Annotation @FacesConverter L’attribut par défaut donne un identificateur : @FacesConverter("fr.unice.Pays") L’attribut forClass indique que le convertisseur est le convertisseur par défaut d’une classe : @FacesConverter(forClass=fr.unice.Pays.class) 21/10/99 Richard Grin JSF - page 170 Fichier faces-config.xml Donne un identificateur à la classe du convertisseur : <converter> <converter-id>fr.unice.Pays</converter-id> <converter-class>fr.unice.PaysConverter</converter-class> </converter> Indique la classe du convertisseur par défaut d’un type : <converter> <converter-for-class>fr.unice.Pays</converter-for-class> <converter-class>fr.unice.Pays</converter-class> </converter> 21/10/99 Richard Grin JSF - page 171 Balise personnalisée pour convertisseur Il est possible de créer de nouvelles balises pour avoir des convertisseurs qui ont des attributs comme, par exemple, l’attribut pattern de la balise <f:convertDateTime> Pour cela, comme pour toutes les balises personnalisées, il faut écrire un fichier de description de balises (voir section sur les balises et composants personnalisés) ou créer un fichier jar à part 21/10/99 Richard Grin JSF - page 172 Bibliographie Core JSF, 3ème édition mise à jour pour JSF 2.0. David Geary et Cay Horstmann. Prentice Hall. Le meilleur livre pour débuter. The Complete Reference JSF 2.0. Ed Burns et Chris Schalk. Quelques compléments intéressants par rapport au livre Core JSF. JSF 2.0 Cookbook. Anghel Leonard. Packt Publishing. Descriptions détaillées de quelques recettes pour résoudre des points précis. 21/10/99 Richard Grin JSF - page 173