Introduction aux frameworks JSF2, Primefaces et Primefaces mobile


précédentsommairesuivant

VII. Application exemple-03 : rdvmedecins-pf-ejb

Rappelons la structure de l'application exemple développée pour le serveur Glassfish :

Image non disponible

Nous ne changeons rien à cette architecture si ce n'est la couche web qui sera ici réalisée à l'aide de JSF et Primefaces.

Image non disponible

VII-A. Le projet Netbeans

Ci-dessus, les couches [métier] et [DAO] sont celles de l'exemple 01 JSF / EJB / Glassfish. Nous les réutilisons.

Image non disponible
  • [mv-rdvmedecins-ejb-dao-jpa] : projet EJB des couches [DAO] et [JPA] de l'exemple 01,
  • [mv-rdvmedecins-ejb-metier] : projet EJB de la couche [métier] de l'exemple 01,
  • [mv-rdvmedecins-pf] : projet de la couche [web] / Primefaces - nouveau,
  • [mv-rdvmedecins-app-ear] : projet d'entreprise pour déployer l'application sur le serveur Glassfish - nouveau.

VII-B. Le projet d'entreprise

Le projet d'entreprise ne sert qu'au déploiement des trois modules [mv-rdvmedecins-ejb-dao-jpa], [mv-rdvmedecins-ejb-metier], [mv-rdvmedecins-pf] sur le serveur Glassfish. Le projet Netbeans est le suivant :

Image non disponible

Le projet n'existe que pour ces trois dépendances [1] définies dans le fichier [pom.xml] de la façon suivante :

[pom.xml]
CacherSélectionnez
  • lignes 10-13 : l'artifact Maven du projet d'entreprise,
  • lignes 18-37 : les trois dépendances du projet. On notera bien le type de celles-ci (lignes 23, 29, 35).

Pour exécuter l'application web, il faudra exécuter ce projet d'entreprise.

VII-C. Le projet web Primefaces

Le projet web Primefaces est le suivant :

Image non disponible
  • en [1], les pages du projet. La page [index.xhtml] est l'unique page du projet. Elle comporte trois fragments [form1.xhtml], [form2.xhtml] et [erreur.xhtml]. Les autres pages ne sont là que pour la mise en forme.
  • en [2], les beans Java. Le bean [Application] de portée application, le bean [Form] de portée session. La classe [Erreur] encapsule une erreur. La classe [MyDataModel] sert de modèle à une balise <dataTable> de Primefaces,
  • en [3], les fichiers de messages pour l'internationalisation,
  • en [4], les dépendances. Le projet web a des dépendances sur le projet EJB de la couche [DAO], le projet EJB de la couche [métier] et Primefaces pour la couche [web].

VII-D. La configuration du projet

La configuration du projet est celle des projets Primefaces ou JSF que nous avons étudiés. Nous listons les fichiers de configuration sans les réexpliquer.

Image non disponible

[web.xml] : configure l'application web.

[web.xml]
CacherSélectionnez

On notera, ligne 30 que la page [index.xhtml] est la page d'accueil de l'application.

[faces-config.xml] : configure l'application JSF

[faces-config.xml]
CacherSélectionnez

[beans.xml] : vide mais nécessaire pour l'annotation @Named

[beans.xml]
CacherSélectionnez

[styles.css] : la feuille de style de l'application

[styles.css]
CacherSélectionnez

La bibliothèque Primefaces vient avec ses propres feuilles de style. La feuille de style ci-dessus n'est utilisée que pour la page à afficher en cas d'exception, une page non gérée par l'application. C'est la page [exception.xhtml] qui est alors affichée.

[messages_fr.properties] : le fichier des messages en français

[messages_fr.properties]
CacherSélectionnez

[messages_en.properties] : le fichier des messages en anglais

[messages_en.properties]
CacherSélectionnez

VII-E. Le modèle des pages [layout.xhtml]

Image non disponible

Le modèle [layout.xhtml] est le suivant :

[layout.xhtml]
CacherSélectionnez

L'unique partie variable de ce modèle est la zone des lignes 28-30. Cette zone se trouve dans la zone d'id :formulaire:contenu (ligne 27). On s'en souviendra. Les appels AJAX qui mettent à jour cette zone auront l'attribut update=":formulaire:contenu". Par ailleurs, le formulaire commence à la ligne 15. Donc le fragment inséré en lignes 28-30 s'insère dans ce formulaire.

L'aspect donné par ce modèle est le suivant :

Image non disponible

La partie dynamique de la page viendra s'insérer dans la zone encadrée ci-dessus.

VII-F. La page [index.xhtml]

Image non disponible

Le projet affiche toujours la même page, la page [index.xhtml] suivante :

[index.xhtml]
CacherSélectionnez
  • lignes 8-9 : ce fragment XHTML viendra s'insérer dans la zone dynamique du modèle [layout.xhtml],
  • la page comprend trois sous-fragments :
  • [form1.xhtml], lignes 10-12 ;
  • [form2.xhtml], lignes 13-15 ;
  • [erreur.xhtml], lignes 16-18.

La présence de ces fragments dans [index.xhtml] est contrôlée par des booléens du modèle [Form.java] associé à la page. Donc en jouant sur ceux-ci, la page rendue diffère.

Le fragment [form1.xhtml] a le rendu suivant :

Image non disponible

Le fragment [form2.xhtml] a le rendu suivant :

Image non disponible

Le fragment [erreur.xhtml] a le rendu suivant :

Image non disponible

VII-G. Les beans du projet

Image non disponible

La classe du paquetage [utils] a déjà été présentée : la classe [Messages] est une classe qui facilite l'internationalisation des messages d'une application. Elle a été étudiée au paragraphe , page .

VII-G-1. Le bean Application

Le bean [Application.java] est un bean de portée application. On se rappelle que ce type de bean sert à mémoriser des données en lecture seule et disponibles pour tous les utilisateurs de l'application. Ce bean est le suivant :

[Application.java]
CacherSélectionnez
  • ligne 8 : on donne au bean le nom application,
  • ligne 9 : il est de portée application,
  • lignes 13-14 : une référence sur l'interface locale de la couche [métier] lui sera injectée par le conteneur EJB du serveur d'application. Rappelons-nous l'architecture de l'application :
Image non disponible

L'application JSF et l'EJB [Metier] vont s'exécuter dans la même JVM (Java Virtual Machine). Donc la couche [JSF] va utiliser l'interface locale de l'EJB. C'est tout. Le bean [Application] ne contient rien d'autre. Pour avoir accès à la couche [métier], les autres beans iront la chercher dans ce bean.

VII-G-2. Le bean [Erreur]

La classe [Erreur] est la suivante :

[Erreur]
CacherSélectionnez
  • ligne 9, le nom d'une classe d'exception si une exception a été lancée,
  • ligne 10 : un message d'erreur.

VII-G-3. Le bean [Form]

Son code est le suivant :

[Form]
CacherSélectionnez
  • lignes 6-8 : la classe [Form] est un bean de nom form et de portée session. On rappelle qu'alors la classe doit être sérialisable,
  • lignes 14-15 : le bean form a une référence sur le bean application. Celle-ci sera injectée par le conteneur de servlets dans lequel s'exécute l'application (présence de l'annotation @Inject).
  • lignes 17-44 : le modèle des pages [form1.xhtml, form2.xhtml, erreur.xhtml]. L'affichage de ces pages est contrôlé par les booléens des lignes 27-29. On remarquera que par défaut, c'est la page [form1.xhtml] qui est rendue (ligne 27),
  • lignes 46-47 : la méthode init est exécutée juste après l'instanciation de la classe (présence de l'annotation @PostConstruct),
  • lignes 50-51 : on demande à la couche [métier], la liste des médecins et des clients,
  • lignes 59-65 : si tout s'est bien passé, les dictionnaires des médecins et des clients sont construits. Ils sont indexés par leur numéro. Ensuite, la page [form1.xhtml] sera affichée (ligne 27),
  • ligne 54 : en cas d'erreur, le modèle de la page [erreur.xhtml] est construit. Ce modèle est la liste d'erreurs de la ligne 36,
  • lignes 78-88 : la méthode [prepareVueErreur] construit la liste d'erreurs à afficher. La page [index.xhtml] affiche alors les fragments [form1.xhtml] et [erreur.xhtml] (ligne 87).

La page [erreur.xhtml] est la suivante :

[erreur.xhtml]
CacherSélectionnez

Elle utilise une balise <p:dataTable> (lignes 12-28) pour afficher la liste des erreurs. Cela donne une page d'erreur analogue à la suivante :

Image non disponible

Nous allons maintenant définir les différentes phases de la vie de l'application. Pour chaque action de l'utilisateur, nous étudierons les vues concernées et les gestionnaires des événements.

VII-H. L'affichage de la page d'accueil

Si tout va bien, la première page affichée est [form1.xhtml]. Cela donne la vue suivante :

Image non disponible

La page [form1.xhtml] est la suivante :

[form1.xhtml]
CacherSélectionnez

La barre d'outils encadrée dans la copie d'écran est le composant Primefaces Toolbar. Celui-ci est défini aux lignes 8-14. Il contient deux groupes de composants chacun étant défini par une balise <toolbarGroup>, lignes 9-11 et 12-14. L'un des groupes est aligné à gauche de la barre d'outils (ligne 9), l'autre à droite (ligne 12).

Examinons certains composants du groupe de gauche :

 
CacherSélectionnez
  • lignes 4-7 : le combo des médecins auquel on a ajouté un effet (effect="fade"),
  • ligne 6 : un comportement AJAX. Lorsqu'il y aura un changement dans le combo, la méthode [Form].hideAgenda (listener="#{form.hideAgenda}") sera exécutée et la zone dynamique :formulaire:contenu (update=":formulaire:contenu") sera mise à jour,
  • ligne 8 : inclut un séparateur dans la barre d'outils,
  • lignes 10-12 : la zone de saisie de la date. On utilise ici le calendrier de Primefaces. La zone de saisie est en lecture seule (readOnlyInputText="true"),
  • ligne 11 : un comportement AJAX. Lorsqu'il y aura un changement de date, la méthode [Form].hideAgenda sera exécutée et la zone dynamique :formulaire:contenu mise à jour,
  • ligne 14 : un bouton. Un clic dessus fait exécuter un appel AJAX vers la méthode [Form].getAgenda (), le modèle sera alors modifié et la réponse du serveur sera utilisée pour mettre à jour la zone dynamique :formulaire:contenu,
  • ligne 15 : la balise <tooltip> permet d'associer une bulle d'aide à un composant. L'id de ce dernier est désigné par l'attribut for du tooltip. Ici (for="resa-agenda") désigne le bouton de la ligne 14 :
Image non disponible

Cette page est alimentée par le modèle suivant :

Form
CacherSélectionnez
  • le champ de la ligne 12 alimente en lecture et écriture la valeur de la liste de la ligne 4 de la page. A l'affichage initial de la page, elle fixe la valeur sélectionnée dans le combo. A l'affichage initial, idMedecin est égal à null, donc c'est le premier médecin qui sera sélectionné,
  • la méthode des lignes 16-18 génère les éléments du combo des médecins (ligne 5 de la page). Chaque option générée aura pour label (itemLabel) les titre, nom, prénom du médecin et pour valeur (itemValue), l'id du médecin,
  • le champ de la ligne 13 alimente en lecture / écriture le champ de saisie de la ligne 10 de la page. A l'affichage initial, c'est donc la date du jour qui est affichée,
  • lignes 26-28 : la méthode getAgenda gère le clic sur le bouton [Agenda] de la ligne 14 de la page. Elle est quasi identique à ce qu'elle était dans la version JSF :
 
CacherSélectionnez

Nous ne commenterons pas ce code. Cela a déjà été fait.

VII-I. Afficher l'agenda d'un médecin

VII-I-1. Vue d'ensemble de l'agenda

C'est le cas d'utilisation suivant :

Image non disponible
  • en [1], on sélectionne un médecin [1] et un jour [2] puis on demande [3] l'agenda du médecin pour le jour choisi,
  • en [4], celui-ci apparaît sous la barre d'outils.

Le code de la page [form2.xhtml] est le suivant :

[form2.xhtml]
CacherSélectionnez
  • lignes 16-26 : l'élément principal de la page est la table <dataTable> qui affiche l'agenda du médecin,
    Image non disponible
  • lignes 12-14 : nous utiliserons un menu contextuel pour ajouter / supprimer un rendez-vous :
    Image non disponible
  • lignes 29-32 : une boîte de confirmation sera affichée lorsque l'utilisateur voudra supprimer un rendez-vous :
    Image non disponible
  • lignes 35-37 : une boîte de dialogue sera utilisée pour signaler une erreur :
    Image non disponible
  • lignes 40-43 : nous aurons besoin d'introduire un peu de Javascript.

VII-I-2. Le tableau des rendez-vous

Nous abordons ici le modèle d'un tableau de données tel qu'étudié au paragraphe , page .

Examinons l'élément principal de la page, le tableau qui affiche l'agenda :

 
CacherSélectionnez

Le rendu est le suivant :

Image non disponible

C'est un tableau à deux colonnes (lignes 4-6 et 8-10) alimenté par la source [Form].getMyDataModel() (value="#{form.myDataModel}"). Une seule ligne peut être sélectionnée à la fois (selectionMode="single"). A chaque POST, une référence de l'élément sélectionné est affectée à [Form].creneauChoisi (selection="#{form.creneauChoisi}").

On se rappelle que la méthode getAgenda a initialisé le champ suivant dans le modèle :

 
CacherSélectionnez

Le modèle du tableau est obtenu par appel de la méthode [Form].getMyDataModel (attribut value de la balise <dataTable>) suivante :

 
CacherSélectionnez

Examinons la classe [MyDataModel] qui sert de modèle à la balise <p:dataTable> :

[MyDataModel]
CacherSélectionnez
  • ligne 7 : la classe [MyDataModel] est le modèle de la balise <p:dataTable>. Cette classe a pour but de faire le lien entre l'élément rowkey qui est posté, avec l'élément associé à cette ligne,
  • ligne 7 : la classe implémente l'interface [SelectableDataModel] au travers de la classe [ArrayDataModel]. Cela signifie que le paramètre du constructeur est un tableau. C'est ce tableau qui alimente la balise <dataTable>. Ici chaque ligne du tableau sera associée à un élément de type [CreneauMedecinJour],
  • lignes 13-15 : le constructeur passe son paramètre à sa classe parent,
  • lignes 18-20 : chaque ligne du tableau correspond à un créneau horaire et sera identifiée par l'id du créneau horaire (ligne 19). C'est cet id qui sera posté au serveur,
  • ligne 23 : le code qui sera exécuté côté serveur lorsque l'id d'un créneau horaire sera posté. Le but de cette méthode est de rendre la référence de l'objet [CreneauMedecinJour] associé à cet id. Cette référence sera affectée à la cible de l'attribut selection de la balise <dataTable> :
 
CacherSélectionnez

Le champ [Form].creneauChoisi contiendra donc la référence de l'objet [CreneauMedecinJour] qu'on veut ajouter ou supprimer.

VII-I-3. La colonne des créneaux horaires

Image non disponible

La colonne des créneaux horaires est obtenue avec le code suivant :

 
CacherSélectionnez
  • lignes 5-7 : l'entête de la colonne,
  • lignes 8-15 : l'élément courant de la colonne. On notera ligne 9, l'utilisation de la balise <h:outputFormat> qui permet de formater des éléments à afficher. Le paramètre value indique la chaîne de caractères à afficher. La notation {i,type,format} désigne le paramètre n° i, le type de ce paramètre et son format. Il y a ici 4 paramètres numérotés de 0 à 3, le type de ceux-ci est numérique et il seront affichés avec deux chiffres,
  • lignes 10-13 : les quatre paramètres attendus par la balise <h:outputFormat>.

VII-I-4. La colonne des clients

Image non disponible

La colonne des clients est obtenue avec le code suivant :

 
CacherSélectionnez
  • lignes 8-10 : l'entête de la colonne,
  • lignes 11-13 : l'élément courant lorsqu'il y a un rendez-vous pour le créneau horaire. Dans ce cas, on affiche les titre, prénom et nom du client pour qui ce rendez-vous a été pris,
  • lignes 14-16 : un autre fragment sur lequel nous reviendrons.

VII-J. Suppression d'un rendez-vous

La suppression d'un rendez-vous correspond à la séquence suivante :

Image non disponible
Image non disponible

La vue concernée par cette action est la suivante :

 
CacherSélectionnez
  • lignes 2-5 : un menu contextuel lié au tableau de données (attribut for). Il a deux options [1] :
    Image non disponible
    21
  • ligne 4 : l'option [Supprimer] déclenche l'affichage de la boîte de dialogue [2] des lignes 13-20,
  • ligne 15 : le clic sur le [Oui] déclenche l'exécution de [Form.action] qui va supprimer le rendez-vous. Normalement, le menu contextuel ne devrait pas offrir l'option [Supprimer] si l'élément sélectionné n'a pas de rendez-vous, et pas l'option [Réserver] si l'élément sélectionné a un rendez-vous. Nous n'avons pas réussi à ce que le menu contextuel soit aussi subtil. On y arrive pour le premier élément sélectionné mais ensuite on constate que le menu contextuel garde la configuration acquise pour cette première sélection. Il devient alors incorrect. Donc on a gardé les deux options et on a décidé de fournir un retour à l'utilisateur s'il supprimait un élément sans rendez-vous,
  • ligne 16 : l'attribut oncomplete qui permet de définir du code Javascript à exécuter après exécution de l'appel AJAX. Ce code sera ici le suivant :
 
CacherSélectionnez
  • ligne 10 : le code Javascript regarde si le dictionnaire args a l'attribut erreur. Si oui, il fait afficher la boîte de dialogue de la ligne 2 (attribut widgetVar). Cette boîte affiche le modèle [Form].msgErreur.

Regardons le code exécuté pour gérer la suppression d'un rendez-vous :

 
CacherSélectionnez
  • ligne 2 : la méthode [Form].action va être exécutée,
  • ligne 4 : avant son exécution, le champ action aura reçu la valeur 'supprimer'.

La méthode [action] est la suivante :

 
CacherSélectionnez
  • ligne 4 : si l'action est 'supprimer', on exécute la méthode [supprimer],
  • ligne 12 : on récupère le rendez-vous du créneau sélectionné. On rappelle que [creneauChoisi] a été initialisé par la référence de l'élément [CreneauMedecinJour] sélectionné,
  • si ce rendez-vous existe, il est supprimé (ligne 19), l'agenda est régénéré (ligne 21) puis réaffiché (ligne 23),
  • si la suppression a échoué, on affiche la page d'erreurs (ligne 26),
  • si l'élément sélectionné n'a pas de rendez-vous (ligne 13) alors on est dans la situation où l'utilisateur a cliqué [Supprimer] sur un créneau qui n'a pas de rendez-vous. On signale cette erreur :
Image non disponible

La méthode [signalerActionIncorrecte] est la suivante :

 
CacherSélectionnez
  • ligne 4 : on enlève la sélection,
  • ligne 6 : on génère un message d'erreur internationalisé,
  • ligne 7 : on ajoute dans le dictionnaire args de l'appel AJAX l'attribut ('erreur', true).

Revenons au code XHTML du bouton [Oui] :

 
CacherSélectionnez
  • ligne 2 : après exécution de la méthode [Form].action, la méthode Javascript handleRequest est exécutée :
 
CacherSélectionnez
  • ligne 10 : on regarde si le dictionnaire args a l'attribut nommé 'erreur'. Si oui, la boîte de dialogue de la ligne 2 est affichée,
  • ligne 3 : elle fait afficher le message d'erreur construit par le modèle.

VII-K. Prise de rendez-vous

La prise de rendez-vous correspond à la séquence suivante :

Image non disponible

La vue impliquée par cette action est la suivante :

 
CacherSélectionnez
  • lignes 21-31 : affichent la chose suivante :
    Image non disponible
  • ligne 21 : l'affichage a lieu s'il n'y a pas de rendez-vous et qu'il y a bien eu sélection et que l'id du créneau choisi correspond à celui de l'élément courant du tableau. Si on ne met pas cette condition, le fragment est affiché pour tous les créneaux,
  • ligne 22 : la zone de saisie sera une zone de saisie assistée. On suppose ici qu'il peut y avoir beaucoup de clients,
  • lignes 24-26 : le lien [Valider],
  • lignes 28-30 : le lien [Annuler].

La zone de saisie assistée est générée par le code suivant :

 
Sélectionnez
1.
<p:autoComplete completeMethod="#{form.completeClients}" value="#{form.identiteClient}" size="30"/>

La méthode [Form].completeClients est chargée de faire des propositions à l'utilisateur à partir des caractères tapés dans la zone de saisie :

Image non disponible

Les propositions sont de la forme [Nom prénom titre]. Le code de la méthode [Form].completeClients est le suivant :

[Form]
CacherSélectionnez
  • ligne 2 : query est la chaîne de caractères tapée par l'utilisateur,
  • ligne 3 : la liste des propositions. Au départ une liste vide,
  • lignes 5-10 : on construit les identités [Nom prénom titre] des clients. Si une identité commence par query (ligne 7), elle est retenue dans la liste des propositions (ligne 8).

VII-L. Validation d'un rendez-vous

La validation d'un rendez-vous correspond à la séquence suivante :

Image non disponible

Le code du lien [Valider] est le suivant :

 
CacherSélectionnez

C'est donc la méthode [Form].action() qui va gérer cet évènement. Entre-temps, le modèle [Form].action aura reçu la chaîne 'valider'. Le code est le suivant :

[Form]
CacherSélectionnez
  • lignes 33-35 : à cause du valeur du champ action, la méthode [validerResa] va être exécutée,
  • ligne 43 : on vérifie d'abord que le client existe. En effet, dans la zone de saisie assistée, l'utilisateur a pu faire une saisie en dur sans s'aider des propositions qui lui ont été faites. La saisie assistée est associée au modèle [Form].identiteClient. On regarde donc si cette identité existe dans le dictionnaire identitesClients construit à l'instanciation du modèle (ligne 20). Celui-ci associe à une identité client de type [Nom prénom titre], le client lui-même (ligne 25),
  • ligne 44 : si le client n'existe pas, on renvoie une erreur au navigateur,
  • ligne 45 : un message d'erreur internationalisé,
  • ligne 46 : on ajoute l'attribut ('erreur',true) au dictionnaire args de l'appel AJAX. L'appel AJAX a été défini de la façon suivante :
 
CacherSélectionnez

Ligne 3 ci-dessus, on voit que le lien [Valider] a un attribut oncomplete. C'est cet attribut qui va faire afficher le message d'erreur selon une technique déjà rencontrée.

  • ligne 50 : on demande à la couche [métier] d'ajouter un rendez-vous pour le jour choisi (jour), le créneau horaire choisi (creneauChoisi.getCreneau()) et le client choisi (hIdentitesClients.get(identiteClient)),
  • ligne 52 : on demande à la couche [métier] de rafraîchir l'agenda du médecin. On verra le rendez-vous ajouté plus toutes les modifications que d'autres utilisateurs de l'application ont pu faire,
  • ligne 54 : on réaffiche l'agenda [form2.xhtml],
  • ligne 57 : on affiche la page d'erreur si une erreur se produit.

VII-M. Annulation d'une prise de rendez-vous

Cela correspond à la séquence suivante :

Image non disponible

Le bouton [Annuler] dans la page [form2.xhtml] est le suivant :

[form2.xhtml]
CacherSélectionnez

La méthode [Form].action est donc appelée :

[Form]
CacherSélectionnez

VII-N. Navigation dans le calendrier

La barre d'outils permet de naviguer dans le calendrier :

Image non disponible
Image non disponible
Image non disponible

Non montré sur les copies d'écran ci-dessus, l'agenda est mis à jour avec les rendez-vous du nouveau jour choisi.

Les balises des trois boutons concernés sont les suivantes dans [form1.xhtml] :

 
CacherSélectionnez

Les méthode [Form].getPreviousAgenda, [Form].getNextAgenda, [Form].today sont les suivantes :

[Form]
CacherSélectionnez
  • ligne 1 : le jour d'affichage de l'agenda,
  • ligne 5 : on utilise un calendrier,
  • ligne 6 : qu'on initialise au jour actuel de l'agenda,
  • ligne 7 : on retire un jour au calendrier,
  • ligne 8 : et on rénitialise avec, le jour d'affichage de l'agenda,
  • ligne 11 : on réaffiche l'agenda si celui-ci est affiché. En effet, l'utilisateur peut utiliser la barre d'outils sans que l'agenda soit affiché.

Les autres méthodes sont analogues.

VII-O. Changement de langue d'affichage

Le changement de langue est géré par le bouton menu de la barre d'outils :

Image non disponible
Image non disponible

Les balises du bouton menu sont les suivantes :

 
CacherSélectionnez

Les méthodes exécutées dans le modèle sont les suivantes :

 
CacherSélectionnez

Les méthodes des lignes 3 et 9 se contentent d'initialiser le champ locale de la ligne 1 puis redirigent le navigateur client vers la même page. Une redirection est une réponse dans laquelle le serveur demande au navigateur de charger une autre page. Le navigateur fait alors un GET vers cette nouvelle page.

  • ligne 17 : [ExternalContext] est une classe JSF qui permet d'accéder à la servlet en cours d'exécution,
  • ligne 19 : on fait la redirection. Le paramètre de la méthode redirect est l'URL de la page vers laquelle le navigateur client doit se rediriger. Ici nous voulons nous rediriger vers [/mv-rdvmedecins-pf] qui est le nom de notre application :
Image non disponible

la méthode [getRequestContextPath] permet d'avoir ce nom. Il va donc y avoir chargement de la page d'accueil [index.xhtml] de notre application. Cette page est associée au modèle [Form] de portée session. Ce modèle gère trois booléens qui commandent l'apparence de la page [index.xhtml] :

 
CacherSélectionnez

Comme le modèle est de portée session, ces trois booléens ont conservé leurs valeurs. La page [index.xhtml] va donc apparaître dans l'état où elle était avant la redirection. Cette page est mise en forme avec le template facelet [layout.xhtml] suivant :

 
CacherSélectionnez

La balise de la ligne 9 fixe la langue d'affichage de la page avec son attribut locale. La page va donc passer en français ou en anglais selon les cas. Maintenant pourquoi une redirection ? Revenons aux balises des options de changement de langues :

 
CacherSélectionnez

Elles avaient été écrites initialement pour mettre à jour par un appel AJAX la zone d'id formulaire (attribut update des lignes 7 et 8). Mais aux tests, le changement de langue ne fonctionnait pas à tout coup. D'où la redirection pour résoudre ce problème. On aurait peut-être pu également mettre l'attribut ajax='false' aux balises pour provoquer un rechargement de page. Cela aurait alors évité la redirection.

VII-P. Rafraîchissement des listes

Cela correspond à l'action suivante :

Image non disponible

La balise associée à l'option [Rafraîchir] est la suivante :

 
Sélectionnez
1.
<p:menuitem id="menuitem-rafraichir" value="#{msg['form1.rafraichir']}" actionListener="#{form.refresh}" update=":formulaire:contenu"/>

La méthode [Form].refresh est la suivante :

 
CacherSélectionnez

La méthode init est la méthode exécutée juste après la construction du bean [Form]. Elle a pour objet de mettre en cache des données de la base de données dans le modèle :

 
CacherSélectionnez

La méthode init construit les listes et dictionnaires des lignes 5-9. L'inconvénient de cette technique est que ces éléments ne prennent plus en compte les changements en base de données (ajout d'un client, d'un médecin…). La méthode refresh force la reconstruction de ces listes et dictionnaires. Aussi l'utilisera-t-on à chaque fois qu'un changement en base est fait, l'ajout d'un nouveau client par exemple.

VII-Q. Conclusion

Rappelons l'architecture de l'application que nous venons de construire :

Image non disponible

Nous nous sommes largement appuyés sur la version JSF2 déjà construite :

  • les couches [métier], [DAO], [JPA] ont été conservées,
  • les beans [Application] et [Form] de la couche web ont été conservés mais de nouvelles fonctionnalités leur ont été ajoutées à cause de l'enrichissement de l'interface utilisateur,
  • l'interface utilisateur a été profondément modifiée. Elle est notamment plus riche en fonctionnalités et plus conviviale.

Le passage de JSF à Primefaces pour construire l'interface web nécessite une certaine expérience car au départ on est un peu noyés devant le grand nombre de composants utilisables et finalement on ne sait trop lesquels utiliser. Il faut alors se pencher sur l'ergonomie souhaitée pour l'interface.

VII-R. Tests Eclipse

Comme nous l'avons fait pour les précédentes versions de l'application exemple, nous montrons comment tester cette version 03 avec Eclipse. Tout d'abord, nous importons dans Eclipse les projets Maven de l'exemple 03 [1] :

Image non disponible
  • [mv-rdvmedecins-ejb-dao-jpa] : les couches [DAO] et [JPA],
  • [mv-rdvmedecins-ejb-metier] : la couche [métier],
  • [mv-rdvmedecins-pf] : la couche [web] implémentée avec JSF et Primefaces,
  • [mv-rdvmedecins-app] : le parent du projet d'entreprise [mv-rdvmedecins-app-ear]. Lorsqu'on importe le projet parent, le projet fils est automatiquement importé,
  • en [2], on exécute le projet d'entreprise [mv-rdvmedecins-app-ear],
    Image non disponible
    34
  • en [3], on choisit le serveur Glassfish,
  • en [4], dans l'onglet [Servers], l'application a été déployée. Elle ne s'exécute pas d'elle-même. Il faut demander son URL [http://localhost:8080/mv-rdvmedecins-pf/] dans un navigateur [5] :
Image non disponible
5

précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2012 Serge Tahé. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.