Traitement et navigation

publicité
12
Traitement et navigation
Au chapitre précédent, nous avons vu comment créer des pages web avec différentes
technologies (HTML, JSP, JSTL, etc.) en insistant sur le fait que JSF est la spécification conseillée pour écrire des applications web modernes avec Java EE. Cependant, créer des pages contenant des composants graphiques ne suffit pas : ces pages
doivent interagir avec un backend (un processus en arrière-plan), il faut pouvoir
naviguer entre les pages et valider et convertir les données. JSF est une spécification très riche : les beans gérés permettent d’invoquer la couche métier, de naviguer
dans votre application, et, grâce à un ensemble de classes, vous pouvez convertir les
valeurs des composants ou les valider pour qu’ils correspondent aux règles métiers.
Grâce aux annotations, le développement de convertisseurs et de validateurs personnalisés est désormais chose facile.
JSF 2.0 apporte la simplicité et la richesse aux interfaces utilisateurs dynamiques.
Il reconnaît nativement Ajax en fournissant une bibliothèque JavaScript permettant
d’effectuer des appels asynchrones vers le serveur et de rafraîchir une page par parties.
La création d’interfaces utilisateurs, le contrôle de la navigation dans l’application
et les appels synchrones ou asynchrones de la logique métier sont possibles parce
que JSF utilise le modèle de conception MVC (Modèle-Vue-Contrôleur). Chaque
partie est donc isolée des autres, ce qui permet de modifier l’interface utilisateur
sans conséquence sur la logique métier et vice versa.
Le modèle MVC
JSF et la plupart des frameworks web encouragent la séparation des problèmes en
utilisant des variantes du modèle MVC. Ce dernier est un modèle d’architecture
permettant d’isoler la logique métier de l’interface utilisateur car la première ne se
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
386
Java EE 6 et GlassFish 3  mélange pas bien avec la seconde : leur mélange produit des applications plus difficiles à maintenir et qui supportent moins bien la montée en charge. Dans la section
"JavaServer Pages" du chapitre précédent, nous avons vu une page JSP qui contenait
à la fois du code Java et des instructions SQL : bien que ce soit techniquement correct, imaginez la difficulté de maintenir une telle page... Elle mélange deux types de
développement différents (celui de concepteur graphique et celui de programmeur
métier) et pourrait finir par utiliser bien plus d’API encore (accès aux bases de données, appels d’EJB, etc.), par gérer les exceptions ou par effectuer des traitements
métiers complexes. Avec MVC, l’application utilise un couplage faible, ce qui facilite la modification de son aspect visuel ou des règles métiers sous-jacentes sans
pour autant affecter l’autre composante.
Comme le montre la Figure 12.1, la partie "modèle" de MVC représente les données
de l’application ; la "vue" correspond à l’interface utilisateur et le "contrôleur" gère
la communication entre les deux.
Figure 12.1
Client
Server
Requête HTTP
Le modèle
de conception MVC.
Navigateur
Contrôleur
(FacesServlet)
Réponse HTTP
crée et gère
manipule et redirige
Modèle
(backing bean)
accède
Vue
(pages XHTML)
Le modèle est représenté par le contenu, qui est souvent stocké dans une base de
données et affiché dans la vue ; il ne se soucie pas de l’aspect que verra l’utilisateur.
Avec JSF, il peut être formé de backing beans, d’appels EJB, d’entités JPA, etc.
La vue JSF est la véritable page XHTML (XHTML est réservé aux interfaces web,
mais il pourrait s’agir d’un autre type de vue, comme WML pour les dispositifs
mobiles). Comme au chapitre précédent, une vue fournit une représentation graphique d’un modèle et un modèle peut avoir plusieurs vues pour afficher un livre
sous forme de formulaire ou de liste, par exemple.
Lorsqu’un utilisateur manipule une vue, celle-ci informe un contrôleur des modifications souhaitées. Ce contrôleur se charge alors de rassembler, convertir et valider
les données, appelle la logique métier puis produit le contenu en XHTML. Avec JSF,
le contrôleur est un objet FacesServlet.
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
Chapitre 12
Traitement et navigation 387
FacesServlet
FacesServlet est une implémentation de javax.servlet.Servlet qui sert de contrô-
leur central par lequel passent toutes les requêtes. Comme le montre la Figure 12.2,
la survenue d’un élément (lorsque l’utilisateur clique sur un bouton, par exemple)
provoque l’envoi d’une notification au serveur via HTTP ; celle-ci est interceptée
par javax.faces.webapp.FacesServlet, qui examine la requête et exécute différentes actions sur le modèle à l’aide de beans gérés.
Figure 12.2
Cycle de vie
Interactions de
FacesServlet.
3. Traitement en 6 étapes
FacesContext
2. Passe le contrôle au cycle de vie
1. Crée un FaceContext
Bouton
Événement
FacesServlet
En coulisse, la FacesServlet prend les requêtes entrantes et donne le contrôle à
l’objet javax.faces.lifecycle.Lifecycle. À l’aide d’une méthode fabrique, elle
crée un objet javax.faces.context.FacesContext qui contient et traite les informations d’état de chaque requête. L’objet Lifecycle utilise ce FacesContext en six
étapes (décrites au chapitre précédent) avant de produire la réponse.
Les requêtes qui doivent être traitées par la FacesServlet sont redirigées à l’aide
d’une association de servlet dans le descripteur de déploiement. Les pages web, les
beans gérés, les convertisseurs, etc. doivent être assemblés avec le fichier web.xml
du Listing 12.1.
Listing 12.1 : Fichier web.xml définissant la FacesServlet
<?xml version=’1.0’ encoding=’UTF-8’?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
388
Java EE 6 et GlassFish 3  <url-pattern>*.faces</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
</web-app>
Ce fichier définit la javax.faces.webapp.FacesServlet en lui donnant un nom
(Faces Servlet, ici) et une association. Dans cet exemple, toutes les requêtes portant l’extension .faces sont associées pour être gérées par la servlet – toute requête
de la forme http://localhost:8080/ chapter10-1.0/newBook.faces sera donc
traitée par JSF.
Vous pouvez également configurer quelques paramètres spécifiques à JSF dans
l’élément <context-param> (voir Tableau 12.1).
Tableau 12.1 : Paramètres de configuration spécifiques à JSF
Paramètre
Description
javax.faces.CONFIG_FILES
Définit une liste de chemins de ressources liées au
contexte dans laquelle JSF recherchera les ressources.
javax.faces.DEFAULT_SUFFIX
Permet de définir une liste de suffixes possibles pour les
pages ayant du contenu JSF (.xhtml, par exemple).
javax.faces.LIFECYCLE_ID
Identifie l’instance LifeCycle utilisée pour traiter les
requêtes JSF.
javax.faces.STATE_SAVING_
METHOD
Définit l’emplacement de sauvegarde de l’état. Les
valeurs possibles sont server (valeur par défaut qui
indique que l’état sera généralement sauvegardé dans un
objet HttpSession) et client (l’état sera sauvegardé
dans un champ caché lors du prochain envoi de
formulaire).
javax.faces.PROJECT_STAGE
Décrit l’étape dans laquelle se trouve cette application
JSF dans le cycle de vie (Development, UnitTest,
SystemTest ou Production). Cette information peut être
utilisée par une implémentation de JSF pour améliorer les
performances lors de la phase de production en utilisant
un cache pour les ressources, par exemple.
javax.faces.DISABLE_FACELET_
JSF_VIEWHANDLER
Désactive Facelets comme langage de déclaration de
page (PDL).
javax.faces.LIBRARIES
Liste des chemins qui seront considérés comme une
bibliothèque de marqueurs Facelets.
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
Chapitre 12
Traitement et navigation 389
FacesContext
JSF définit la classe abstraite javax.faces.context.FacesContext pour représenter
les informations contextuelles associées au traitement d’une requête et à la production de la réponse correspondante. Cette classe permet d’interagir avec l’interface
utilisateur et le reste de l’environnement JSF.
Pour y accéder, vous devez soit utiliser l’objet implicite facesContext dans vos
pages (les objets implicites ont été présentés au chapitre précédent), soit obtenir
une référence dans vos beans gérés à l’aide de la méthode statique getCurrentInstance() : celle-ci renverra l’instance de FacesContext pour le thread courant et vous
pourrez alors invoquer les méthodes du Tableau 12.2.
Tableau 12.2 : Quelques méthodes de FacesContext
Méthode
Description
addMessage
Ajoute un message d’erreur.
getApplication
Renvoie l’instance Application associée à cette application
web.
getAttributes
Renvoie un objet Map représentant les attributs associés à
l’instance FacesContext.
getCurrentInstance
Renvoie l’instance FacesContext pour la requête traitée par le
thread courant.
getMaximumSeverity
Renvoie le niveau d’importance maximal pour tout
FacesMessage mis en file d’attente.
getMessages
Renvoie une collection de FacesMessage.
getViewRoot
Renvoie le composant racine associé à la requête.
release
Libère les ressources associées à cette instance de FacesContext.
renderResponse
Signale à l’implémentation JSF que le contrôle devra être
transmis à la phase Render response dès la fin de l’étape de
traitement courante de la requête, en ignorant les étapes qui n’ont
pas encore été exécutées.
responseComplete
Signale à l’implémentation JSF que la réponse HTTP de cette
requête a déjà été produite et que le cycle de vie du traitement de
la requête doit se terminer dès la fin de l’étape en cours.
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
390
Java EE 6 et GlassFish 3  Configuration de Faces
La FacesServlet est interne aux implémentations de JSF ; bien que vous n’ayez
pas accès à son code, vous pouvez la configurer avec des métadonnées. Vous savez
désormais qu’il existe deux moyens d’indiquer des métadonnées avec Java EE 6 :
les annotations et les descripteurs de déploiement XML (/WEB-INF/faces-config.
xml). Avant JSF 2.0, le seul choix possible était XML mais, désormais, les beans
gérés, les convertisseurs, les moteurs de rendu et les validateurs pouvant utiliser les
annotations, les fichiers de configuration XML sont devenus facultatifs.
Nous conseillons l’emploi des annotations mais, pour montrer à quoi ressemble
un fichier faces-config.xml, le Listing 12.2 définit une locale et un ensemble de
messages pour l’internationalisation et certaines règles de navigation. Nous verrons
ensuite comment naviguer avec et sans faces-config.xml.
Listing 12.2 : Extrait d’un fichier faces-config.xml
<?xml version=’1.0’ encoding=’UTF-8’?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<locale-config>
<default-locale>fr</default-locale>
</locale-config>
<resource-bundle>
<base-name>messages</base-name>
<var>msg</var>
</resource-bundle>
</application>
<navigation-rule>
<from-view-id>*</from-view-id>
<navigation-case>
<from-outcome>doCreateBook-success</from-outcome>
<to-view-id>/listBooks.htm</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
Beans gérés
Comme on l’a indiqué plus haut, le modèle MVC encourage la séparation entre le
modèle, la vue et le contrôleur. Avec Java EE, les pages JSF forment la vue et la
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
Chapitre 12
Traitement et navigation 391
est le contrôleur. Les beans gérés, quant à eux, sont une passerelle
vers le modèle.
Les beans gérés sont des classes Java annotées. Ils constituent le cœur des applications
web car ils exécutent la logique métier (ou la délèguent aux EJB, par exemple), gèrent
la navigation entre les pages et stockent les données. Une application JSF typique
contient un ou plusieurs beans gérés qui peuvent être partagés par plusieurs pages.
Les données sont stockées dans les attributs du bean géré, qui, en ce cas, est également appelé "backing bean". Un backing bean définit les données auxquelles est lié
un composant de l’interface utilisateur (la cible d’un formulaire, par exemple). Pour
établir cette liaison, on utilise EL, le langage d’expressions.
FacesServlet
Écriture d’un bean géré
Écrire un bean géré est aussi simple qu’écrire un EJB ou une entité JPA puisqu’il
s’agit simplement de créer une classe Java annotée par @ManagedBean (voir Listing 12.3) – il n’y a nul besoin de créer des entrées dans faces-config.xml, de créer
des classes utilitaires ou d’hériter d’une classe quelconque : JSF 2.0 utilisant également le mécanisme de configuration par exception, une seule annotation suffit pour
utiliser tous les comportements par défaut et pour déployer une application web
utilisant un bean géré.
Listing 12.3 : Bean géré simple
@ManagedBean
public class BookController {
private Book book = new Book();
public String doCreateBook() {
createBook(book);
return "listBooks.xhtml";
}
}
// Constructeurs, getters, setters
Le Listing 12.3 met en évidence le modèle de programmation d’un bean géré :
il stocke l’état (l’attribut book), définit les méthodes d’action (doCreateBook())
­utilisées par une page et gère la navigation (return "listBooks.xhtml").
Modèle d’un bean géré
Les beans gérés sont des classes Java prises en charge par la FacesServlet. Les composants de l’interface utilisateur sont liés aux propriétés du bean (backing bean) et
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
392
Java EE 6 et GlassFish 3  peuvent invoquer des méthodes d’action. Un bean géré doit respecter les contraintes
suivantes :
■■
La classe doit être annotée par @javax.faces.model.ManagedBean ou son équivalent dans le descripteur de déploiement XML faces-config.xml.
■■
La classe doit avoir une portée (qui vaut par défaut @RequestScoped).
■■
La classe doit être publique et non finale ni abstraite.
■■
La classe doit fournir un constructeur public sans paramètre qui sera utilisé par
le conteneur pour créer les instances.
■■
La classe ne doit pas définir de méthode finalize().
■■
Pour être liés à un composant, les attributs doivent avoir des getters et des setters
publics.
Bien qu’un bean géré puisse être un simple POJO annoté, sa configuration peut être
personnalisée grâce aux éléments de @ManagedBean et @ManagedProperty (ou leurs
équivalents XML).
@ManagedBean
La présence de l’annotation @javax.faces.model.ManagedBean sur une classe l’enregistre automatiquement comme un bean géré. La Figure 12.4 présente l’API de
cette annotation, dont tous les éléments sont facultatifs.
Listing 12.4 : API de l’annotation ManagedBean
@Target(TYPE)
@Retention(RUNTIME)
public @interface ManagedBean {
String name() default "";
boolean eager() default false;
}
L’élément name indique le nom du bean géré (par défaut, ce nom est celui de la
classe commençant par une minuscule). Si l’élément eager vaut true, le bean géré
est instancié dès le démarrage de l’application.
Les composants de l’interface utilisateur étant liés aux propriétés d’un bean géré,
changer son nom par défaut a des répercussions sur la façon d’appeler une propriété
ou une méthode. Le code du Listing 12.5, par exemple, renomme le bean géré Book–
Controller en myManagedBean.
© 2010 Pearson Education France – Java EE 6 et GlassFish 3 – Antonio Goncalves
Téléchargement