Introduction aux frameworks JSF2, Primefaces et Primefaces mobile


précédentsommairesuivant

X. Application exemple 05 : rdvmedecins-pfm-ejb

Rappelons la structure de l'application exemple 01 JSF / EJB 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, Primefaces et Primefaces mobile. Le navigateur cible sera celui d'un mobile.

Image non disponible

Nous avons développé deux applications avec Glassfish :

  • l'application 01 utilisait JSF / EJB et avait une interface assez rustique,
  • l'application 03 utilisait PF / EJB et avait une interface riche.

Du fait du faible nombre de composants disponibles dans Primefaces mobile, nous allons revenir à l'interface rustique de l'application 01. Par ailleurs, les vues devront pouvoir s'adapter à la taille réduite des écrans de mobiles.

X-A. Les vues

Pour fixer les idées, nous donnons quelques vues de l'application exécutée dans le simulateur d'un iphone 4 :

Image non disponible
  • en [1], la page d'accueil. On notera qu'il a fallu cette fois donner le nom de la machine (on peut aussi donner son adresse IP), parce qu'avec la machine localhost, ça n'affichait rien,
  • en [2], le combo des médecins,
  • en [3], la date désirée pour le rendez-vous,
  • en [4], le bouton pour demander l'agenda du jour,
  • en [5], la nouvelle vue affiche les créneaux horaires du médecin,
  • en [6], une série de boutons pour naviguer dans le calendrier,
  • en [7], un message pour rappeler le médecin et le jour,
  • en [8], un créneau horaire pour réserver. On le fait,
    Image non disponible
  • en [9], la vue de choix du client,
  • en [10], un message rappelant le médecin, le jour et le créneau horaire concernés par le rendez-vous,
  • en [11], le combo des clients,
  • en [12], le bouton de validation,
  • en [13], la validation nous fait revenir sur l'agenda,
  • en [14], le créneau horaire occupé est désormais réservé. On va maintenant supprimer la réservation,
    Image non disponible
  • en [15], on reste sur la même vue,
  • mais en [16], le rendez-vous a été supprimé,

Il est possible dans la page d'accueil de changer de langue [17], [18], [19] :

Image non disponible

Enfin, on a prévu une vue d'erreurs :

Image non disponible

X-B. Le projet Netbeans

Le projet Netbeans est le suivant :

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-pfmobile] : projet de la couche [web] / Primefaces mobile - nouveau,
  • [mv-rdvmedecins-pfmobile-app-ear] : projet d'entreprise pour déployer l'application sur le serveur Glassfish - nouveau.

X-C. 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-pfmobile] 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 6-9 : l'artifact Maven du projet d'entreprise,
  • lignes 14-33 : les trois dépendances du projet. On notera bien le type de celles-ci (lignes 19, 25, 31).

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

X-D. Le projet web Primefaces mobile

Le projet web Primefaces mobile est le suivant :

Image non disponible
  • en [1], les pages du projet. La page [index.xhtml] est l'unique page du projet. Elle comporte cinq vues [vue1.xhtml], [vue2.xhtml], [vue3.xhtml], [vueErreurs.xhtml] et [config.xhtml],
  • 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,
  • 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 mobile pour la couche [web].

X-E. 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 26 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

[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

X-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
  • ligne 8 : la page est internationalisée (attribut locale),
  • ligne 10 : la page contient cinq vues : vue1 ligne 11, vue2 ligne 19, vue3 ligne 24, vueErreurs ligne 29, config ligne 34. A un moment donné seule l'une de ces vues est visible. Au démarrage de l'application, c'est la vue vue1 qui est affichée. Ici, on a rencontré la difficulté suivante : si l'initialisation de l'application s'est bien passée, on doit afficher [vue1.xhtml], sinon c'est [vueErreurs.xhtml] qui doit être affichée. On a réglé le problème en faisant en sorte que le contenu de la vue vue1 soit géré par le modèle qui donne des valeurs aux booléens [Form].form1rendered (ligne 12) et [Form].erreurInit (ligne 15) pour fixer le contenu de vue1 (ligne 11),

Dans un simulateur, la vue [vue1.xhtml] a le rendu [1], la vue [vue2.xhtml] le rendu [2], la vue [vue3.xhtml] le rendu [3] :

Image non disponible

la vue [vueErreurs.xhtml] le rendu [4], la vue [config.xhtml] le rendu [5] :

Image non disponible

X-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 .

X-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 PFM et l'EJB [Metier] vont s'exécuter dans la même JVM (Java Virtual Machine). Donc la couche [PFM] 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.

X-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.

X-G-3. Le bean [Form]

Son code est le suivant :

[Form]
CacherSélectionnez
  • lignes 5-7 : 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 12-13 : 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 24-27 : contrôlent l'affichage des vues vue1 (ligne 24), vue2 (ligne 25), vue3 (ligne 26), vueErreurs (ligne 27),
  • lignes 43-44 : la méthode init est exécutée juste après l'instanciation de la classe (présence de l'annotation @PostConstruct),
  • lignes 49-50 : gèrent le format des dates. Primefaces mobile n'offre pas de calendrier. Par ailleurs, les validateurs JSF ne sont pas utilisables dans une page PFM. Aussi devrons-nous gérer à la main la saisie de la date de l'agenda,
  • ligne 49 : fixe le format des dates. Ce format est pris dans les fichiers internationalisés :

format.date=dd/MM/yyyy

format.date_detail=dd/MM/yyyy

  • ligne 50 : on indique qu'on ne doit pas être " laxiste " vis à vis des dates. Si on ne le fait pas, une saisie comme 32/12/2011 qui est une saisie incorrecte est considérée comme la date valide 01/01/2012,
  • ligne 54 : on récupère une référence sur la couche [métier] auprès du bean [Application],

La page [erreur.xhtml] est la suivante :

[erreur.xhtml]
CacherSélectionnez

Elle utilise une balise <p:dataList> (lignes 21-23) pour afficher la liste des erreurs. Le bouton de la ligne 13 permet de revenir sur la vue vue1.

Image non disponible
  • le bouton [1] est produit par la ligne 13. L'attribut icon fixe l'icône du bouton. Le bouton ramène à la vue vue1 (attribut href),
  • l'entête [2] est produit par les lignes 11-15,
  • le titre [3] est produit par la ligne 18,
  • le texte [4] est produit par le modèle #{erreur.classe} de la ligne 22,
  • le texte [5] est produit par le modèle #{erreur.message} de la ligne 22.

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 qui s'y produisent.

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

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

Image non disponible

Le code de la vue [vue1.xhtml] est le suivant :

[vue1.xhtml]
CacherSélectionnez
  • lignes 11-15 : produisent l'entête [1],
  • ligne 13 : produit le bouton [2]. Un clic sur celui-ci affiche la vue config (attribut href),
  • ligne 19 : produit le titre [3],
  • lignes 21-26 : produisent le combo des médecins [4],
  • lignes 27-34 : produisent la saisie de la date [5]. Cette saisie est faite avec une balise <p:inputText> sans validateur. La validation de la date sera faite côté serveur. Si la date est incorrecte, celui-ci positionnera un message d'erreur affiché par les lignes 30-34,
    Image non disponible
  • ligne 35 : le bouton qui valide le formulaire. Il met à jour trois zones : form1 (le formulaire dans vue1), vue2 et vueErreurs. En effet, si la date est invalide c'est form1 qui doit être mise à jour. Si la date est correcte c'est vue2 qui doit être mise à jour. Enfin s'il se produit une exception (connexion à la base cassée par exemple), c'est vueErreurs qui doit être affichée. On peut être tenté de mettre vue1 à la place de form1 (on met à jour toute la vue). Dans ce cas, l'application bogue.

Cette vue est adossée au modèle suivant :

 
CacherSélectionnez
  • le champ de la ligne 16 alimente en lecture et écriture la valeur de la liste de la ligne 23 de la page. A l'affichage initial de la page, elle fixe la valeur sélectionnée dans le combo,
  • la méthode des lignes 27-29 génère les éléments du combo des médecins (ligne 24 de la vue). 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 18 alimente en lecture / écriture le champ de saisie de la ligne 29 de la page,
  • lignes 32-34 : la méthode getAgenda gère le clic sur le bouton [Agenda] de la ligne 35 de la page. Son code est le suivant :
 
CacherSélectionnez
  • la méthode commence par vérifier la validité de la date saisie par l'utilisateur,
  • ligne 5 : la date est parsée selon le format de date initialisé par la méthode init à l'instanciation du modèle,
  • ligne 11 : s'il se produit une exception, une erreur est positionnée (ligne 13), un message d'erreur internationalisé est construit (ligne 14), la vue vue1 est préparée (ligne 16) et on affiche la vue vue1 (ligne 17),
  • ligne 10 : si la date est correcte, on exécute la méthode suivante :
 
CacherSélectionnez

On retrouve là un code déjà rencontré à diverses reprises. Ligne 9, un message internationalisé est construit pour la vue vue2 :

 
CacherSélectionnez

On notera que nous avons mis du XHTML dans le message. Il sera affiché de la façon suivante :

Image non disponible

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

L'agenda du médecin est affiché par la vue [vue2.xhtml] :

Image non disponible

Le code de la vue [vue2.xhtml] est le suivant :

[vue2.xhtml]
CacherSélectionnez
  • lignes 11 : produit l'entête [1],
  • ligne 15-20 : produit le groupe de boutons [2],
  • ligne 21 : produit le titre [3]. On notera la valeur de l'attribut escape. C'est ce qui permet d'interpréter le code XHTML que nous avons mis dans form2Titre,
  • ligne 24 : l'affichage des créneaux horaires est faite à l'aide d'un dataList,
  • lignes 28-33 : produisent l'intitulé du créneau horaire [4],
  • lignes 34-37 : affichent un fragment s'il y a un rendez-vous dans le créneau horaire,
  • ligne 36 : affiche l'identité du client ayant pris le rendez-vous,
  • lignes 41-45 : affichent le bouton [Supprimer] s'il y a un rendez-vous,
  • lignes 46-50 : affichent le bouton [Réserver] s'il n'y a pas de rendez-vous.

Cette vue est principalement alimentée par le modèle suivant :

 
Sélectionnez
1.
private AgendaMedecinJour agendaMedecinJour;

qui alimente le dataList de la ligne 24. Ce champ a été construit par la méthode getAgenda, lorsqu'on est passé de la vue vue1 à la vue vue2.

X-J. Suppression d'un rendez-vous

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

Image non disponible

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

 
CacherSélectionnez
  • ligne 2 : le bouton [Supprimer] est associé à la méthode [Form].action (attribut action),
  • ligne 3 : l'id du créneau sur lequel on est positionné sera envoyé au modèle [Form].idCreneauChoisi,
  • ligne 2 : l'appel AJAX mettra à jour les zones form2 (formulaire de vue2) et la vue vueErreurs. On a en effet deux cas : sii tout se passe bien la vue vue2 sera réaffichée sinon c'est la vue vueErreurs qui le sera.

La méthode [action] est la suivante :

 
CacherSélectionnez
  • lignes 3-12 : on recherche le créneau horaire dont on a reçu l'id (ligne 7),
  • si on le trouve pas, ce qui est anormal, on réaffiche vue2 (lignes 16-17),
  • ligne 19 : si on le trouve, on mémorise l'objet [CreneauMedecinJour] correspondant. C'est lui qui nous donne accès au rendez-vous à supprimer,
  • ligne 26 : on le supprime,
  • lignes 35-48 : la méthode supprimer renvoie la vue vue2 si la suppression s'est bien passée (lignes 42-43) ou la vue vueErreurs s'il y a eu un problème (lignes 46-47).

X-K. Prise de rendez-vous

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

Image non disponible

On passe de la vue vue2 à la vue vue3. Le code impliquée par cette action est le suivant :

 
CacherSélectionnez
  • ligne 2 : le bouton [Réserver] est associé à la méthode [Form].action (attribut action), donc la même que pour le bouton [Supprimer]. L'appel AJAX met à jour les vues vue3 et vueErreurs selon qu'il y a ou non des erreurs lors du traitement de l'appel.
  • ligne 3 : comme pour le bouton [Supprimer], l'id du créneau horaire est passé au modèle.

Le modèle qui traite cette action est le suivant :

 
CacherSélectionnez
  • lignes 2-10 : la méthode action va déterminer la référence creneauChoisi de l'objet [CreneauMedecinJour] qui fait l'objet d'une réservation puis appeler la méthode reserver,
  • ligne 16 : un message internationalisé est construit. C'est le suivant :
 
Sélectionnez
1.
2.
form3.titre={0} {1} {2}<br/>{3}<br/>{4,number,#00}h:{5,number,#00}-{6,number,#00}h:{7,number,#00}
form3.titre_detail={0} {1} {2}<br/>{3}<br/>{4,number,#00}h:{5,number,#00}-{6,number,#00}h:{7,number,#00}

Ce sera le titre de la vue vue3. Comme pour la vue vue2, ce titre comporte du XML. Il comporte également des paramètres formatés pour afficher les horaires du créneau,

Image non disponible
  • lignes 19-20 : le vue vue3 est affichée,
  • lignes 23-24 : la vue vueErreurs est affichée si on a rencontré des problèmes.

X-L. Validation d'un rendez-vous

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

Image non disponible

En [1], la vue vue3 et en [2], la vue vue2 après ajout d'un rendez-vous.

Le code [vue3.xhtml] de vue3 est le suivant :

[vue3.xhtml]
CacherSélectionnez
  • ligne 16 : produit le titre de la vue [3]. On notera la valeur de l'attribut escape qui permet l'interprétation des caractères XHTML dans le titre,
  • lignes 18-23 : produisent le combo des clients [4],
  • ligne 25 : produit le bouton [Valider] [5]. La méthode [Form].validerRv est associée à ce bouton :
 
CacherSélectionnez

Ce code a déjà été rencontré dans la version 01. On notera simplement l'affichage des vues :

  • la vue vue2 (lignes 11-12) si tout s'est bien passé,
  • la vue vueErreurs (lignes 15-16) sinon.

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

Cela correspond à la séquence suivante :

Image non disponible

Le bouton [1] dans la vue [vue3.xhtml] est le suivant :

 
Sélectionnez
1.
<p:commandButton inline="true" value=" " icon="back" action="#{form.showVue2}" update=":vue2"/>

La méthode [Form].showVue2 est donc appelée. Elle se contente d'afficher vue2 :

 
CacherSélectionnez

X-N. Navigation dans le calendrier

Dans vue2, des boutons permettent de naviguer dans le calendrier :

Jour précédent :

Image non disponible

Jour suivant :

Image non disponible

Aujourd'hui :

Image non disponible

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

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

 
CacherSélectionnez

Les méthode [Form].getPreviousAgenda, [Form].getNextAgenda, [Form].today ont été étudiées dans l'exemple 03.

X-O. Changement de langue d'affichage

Le changement de langue est géré par un bouton de la page d'accueil :

Image non disponible

Le code du bouton est le suivant :

 
Sélectionnez
1.
<p:button icon="gear" value=" "  href="#config" />

Il fait donc passer à la vue config [2]. La vue [config.xhtml] est la suivante :

 
CacherSélectionnez
  • ligne 11 : fait afficher [3],
  • ligne 13 : fait afficher le bouton [4]. Ce bouton permet de revenir à la vue vue1,
  • ligne 17 : le formulaire de la vue,
  • ligne 19 : fait afficher le titre de la vue [5],
  • lignes 21-27 : font afficher les boutons radio. La valeur (itemValue) du bouton radio sélectionné sera postée au modèle [Form].locale (attribut value de la ligne 23),
  • ligne 28 : fait afficher le bouton [Valider]. L'appel AJAX met à jour la vue vue1 (attribut update). La méthode appelée est [Form].configurer :
[Form]
CacherSélectionnez

La méthode configurer (ligne 1) se contente de rediriger le navigateur du mobile vers l'URL de l'application. C'est donc la page [index.xhtml] qui va être chargée :

 
CacherSélectionnez
  • ligne 8 : la vue va utiliser la langue qui vient d'être changée (attribut locale) et va afficher vue1 (ligne 11).

X-P. Conclusion

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

Image non disponible

Le passage à une interface pour mobiles a nécessité la réécriture des pages XHTML. Le modèle en revanche a lui peu bougé. Les couches basses [métier], [DAO], [JPA] n'ont, elles, pas bougé du tout.

X-Q. Tests Eclipse

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

Image non disponible
  • [mv-rdvmedecins-ejb-dao-jpa] : les couches [DAO] et [JPA],
  • [mv-rdvmedecins-ejb-metier] : la couche [métier],
  • [mv-rdvmedecins-pfmobile] : la couche [web] implémentée par Primefaces mobile,
  • [mv-rdvmedecins-pfmobile-app] : le parent du projet d'entreprise [mv-rdvmedecins-pfmobile-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-pfmobile-app-ear],
    Image non disponible
  • 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-pfmobile/] dans un navigateur ou un simulateur de mobile [5] :
Image non disponible

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.