JSF et Ajax (Zeina Zgheib)

Qu’est ce que JSF ?

JSF (JavaServer Faces) est un framework MVC basé sur les composants. Il est construit sur l'API Servlet et fournit des composants sous forme de bibliothèques de balises. Celles-ci peuvent être utilisées dans des pages JSP comme dans toute autre technologie de vue basée sur le Java, car le framework JSF ne limite pas le développeur à une technologie particulière pour la vue. 
Cependant, il existe une technologie relativement récente baptisée la Facelet, qui fait partie du standard et qu'il est recommandé d'utiliser dès lors que l'on travaille avec JSF, celle-ci étant bien plus adaptée que les pages JSP. Ces dernières sont d'ailleurs considérées comme une technologie de présentation dépréciée pour JSF depuis la sortie de Java EE 6 en 2009.


Framework MVC

MVC est une architecture pour le développement de logiciels, elle n'est pas récente mais elle est extrêmement populaire et proposée par la plupart des langages/frameworks actuels. 
MVC signifie Modèle, Vue, Contrôleur.
Il s'agit donc de diviser le logiciel en trois parties distinctes qui vont interagir entre elles selon un schéma précis :
- Le contrôleur gère les événements et supervise les deux autres parties. Il administre les communications entre le modèle et la vue.
- Le modèle fournit des fonctions pour gérer les données. Ce modèle peut utiliser un SGBD (MySQL par exemple), des fichiers XML, ou autre ; cela est complètement transparent pour le contrôleur.
- La vue gère l'interface et se charge de l'affichage. Elle est concrétisée par les templates et les modèles d’affichage qui sont le plus souvent des fichiers xhtml et qui n'attendent que les données finales pour être présentés à l'utilisateur.


Historique


JSF 1.0

Ce fut la version initiale en mars 2004. Elle était pleine de bugs à la fois au niveau des performances et du noyau. Les applications ne fonctionnaient pas toujours comme attendu.


JSF 1.1

En mai 2004 il s'agissait ici d'une mise à jour destinée à corriger les bugs de la version initiale... Et les performances n'étaient toujours pas au rendez-vous. En outre, énorme inconvénient : il était impossible d'insérer du HTML dans une page JSF sans défauts! Il fallait entourer chaque portion de code HTML par une balise JSF (<f:verbatim>) pour qu'elle soit incluse correctement dans l'arbre des composants (l'enchaînement des balises JSF) et rendue proprement.


JSF 1.2

En mai 2006 ce fut la première version préparée par la nouvelle équipe de développement de JSF. L'équipe a fourni un travail énorme, et les spécifications ont beaucoup évolué. L'amélioration de la gestion de la vue a été le principal axe de changement. Elle n'a pas seulement rendu la vue JSF indépendante des JSP, mais elle a également permis aux développeurs d'insérer du HTML dans une page JSF sans avoir à dupliquer sans cesse ces balises <f:verbatim>nécessaires dans les versions précédentes. Un autre centre d'intérêt de l'équipe à l'époque fut l'amélioration des performances. Presque chaque version corrective mineure était alors accompagnée d'améliorations notables des performances globales du framework. 
Le seul réel inconvénient commun à toutes les versions JSF 1.x (1.2 inclus) était l'absence d'une portée se plaçant entre la requête et la session (celle qui est souvent nommée "scope de conversation"). Cela forçait les développeurs à jouer avec des champs de formulaires cachés, des requêtes sur la BDD non nécessaires et/ou à abuser des sessions à chaque fois que quelqu'un voulait retenir le modèle de données initial pour les requêtes suivantes afin de procéder aux validations/conversions/mises à jour du modèle et aux invocations d'actions dans des applications web plus complexes. En somme, le développeur devait faire comme nous lorsque nous travaillons à la main sans framework. Il n'avait aucun moyen standard pour donner un état à une vue en particulier. Ce problème pouvait à l'époque être partiellement évité en utilisant une bibliothèque tierce qui sauvegardait l'état des données nécessaires pour les requêtes suivantes, notamment la balise <t:saveState> de la bibliothèque MyFaces Tomahawk, ou encore le framework de conversation MyFaces Orchestra. 
Un autre point très pénalisant pour les webdesigners était le fait que JSF utilisait le caractère : en tant que séparateur d'identifiant afin d'assurer l'unicité des id des éléments HTML générés lors du rendu des balises, notamment lorsqu'un composant était utilisé plus d'une fois dans la vue (création de templates, boucles sur les composants, etc.). Ce caractère n'est pas autorisé dans les identifiants CSS, et les webdesigners devaient alors utiliser le caractère \ pour échapper les : dans les sélecteurs CSS qu'ils mettaient en place, ce qui produisait des sélecteurs étranges et sales tels que #formulaireId\:champId { ... } dans les feuilles CSS.
En outre, JSF 1.x n'était livré avec aucune fonctionnalité Ajax prête à l'emploi. Ce n'était pas vraiment un inconvénient technique, mais l'explosion du web 2.0 en a fait un inconvénient fonctionnel. Exadel introduisait alors rapidement la bibliothèque Ajax4jsf, qui a été activement développée durant les années suivantes puis intégrée au noyau de la bibliothèque de composants JBoss RichFaces. D'autres bibliothèques offrent depuis des composants ajaxisés, IceFaces étant probablement la plus connue. 
Quand JSF 1.2 a atteint la moitié de sa vie, une nouvelle technologie pour la vue basée sur le XML a été introduite : les Facelets. Cela a offert d'énormes avantages sur les JSP, particulièrement pour la création de templates et pour les performances.


JSF 2.0

En juin 2009 ce fut la seconde version majeure. Il y eut énormément de changements à la fois techniques et fonctionnels. La technologie JSP a été remplacée par les Facelets en tant que technologie de vue, et aux Facelets ont été greffées des fonctionnalités permettant la création de composants purement XML (appelés composants composites). Ajax a été introduit notamment, via un composant qui montre des similarités avec Ajax4jsf.
Dans cette version, des annotations et améliorations ont été introduites pour éliminer les volumineux fichiers de configuration autant que possible.
Cependant, bien que la plupart des inconvénients de JSF 1.x ont disparu avec cette version, il subsiste des bugs spécifiques à JSF 2.0 qui peuvent être un facteur bloquant dans le développement d'une application. Mais ils concernent une utilisation avancée du framework, et la plupart de ces bugs sont contournables.
Enfin c'est avec JSF 2.0 que sont apparues de nouvelles bibliothèques de composants plus graphiques comme PrimeFaces et OpenFaces.



Qu'est-ce que la création de templates ?

Il s'agit de la possibilité de découper une page en plusieurs composants indépendants, assemblés ensuite pour former une page finale. 

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
  <title><ui:insert name="title">JSF Example</ui:insert></title>
</head>
<body>
<div id="header">
    <ui:insert name="header">
    	<ui:include src="header.xhtml"/>
    </ui:insert>
</div>
<div id="content">
  <ui:insert name="content">
  </ui:insert>
</div>
<div id="footer">
  <ui:insert name="footer">
    	<ui:include src="footer.xhtml"/>
  </ui:insert>
</div>
</body>
</html>
BasicTemplate.xhtml


<html xmlns="http://www.w3.org/1999/xhtml">
<body>
      <div style="width:100%;font-size:36px;line-height:48px;background-color:navy;color:white">My Facelet Application</div>
</body>
</html>
header.xhtml


<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</head>
<body>
     <div style="background-color:navy;width:100%;color:white"></div>
</body>
</html>
footer.xhtml


Structure d'une application JSF

Comment se construit une application basée sur JSF:

  • la vue est généralement assurée par des pages XHTML (on parle alors de Facelets) ;
  • le modèle est assuré par des entités ou des JavaBeans ;
  • le contrôleur est décomposé en deux éléments:
    • une unique servlet mère servant de point d'entrée à toute requête, la FacesServlet.
    • un JavaBean particulier, déclaré via une annotation et désigné par le terme managed-bean.
  • le tout est mis en musique par des fichiers de configuration : le classique web.xml, mais également un nouveau fichier nommé faces-config.xml.



Facelets et composants

Avec JSF, de simples pages XHTML sont utilisées pour la création de vues dans une application Java EE, ces pages sont nommées des Facelets. 
Une Facelet est un fichier XML pur qui ne peut contenir que des balises, et il est impossible d'y inclure des scriptlets : le Java est donc définitivement banni de la vue avec cette technologie. D’ou la différence entre facelets et pages JSP.
Au niveau du format et du rendu, c'est le langage XHTML qui est le plus utilisé pour créer des Facelets (XHTML étant une version de la syntaxe HTML conforme au standard XML). Le framework JSF est markup-agnostique : cela signifie qu'il peut s'adapter à n'importe quel langage, à partir du moment où ce langage respecte la structure décrite par le standard XML. Ainsi, il est également possible de construire une Facelet avec du langage XML pur, par exemple pour créer un flux RSS.
Au niveau de l'aspect extérieur du fichier, une Facelet porte en général une de ces trois extensions : .jsf, .xhtml ou .faces. Dans l'absolu, c'est par défaut l'extension .xml qui pourrait être utilisée.
Exemple d’un facelet :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Premier exemple JSF 2.0</title>
    </h:head>
    <h:body>
        <h1>Premier exemple JSF 2.0 - bonjour.xhtml</h1>
        <h:form>
           <h:inputText value="#{bonjourBean.nom}" />
           <h:commandButton value="Souhaiter la bienvenue" action="bienvenue" />
        </h:form>
    </h:body>
</html>


La Servlet

Toutes les requêtes vers des pages « JSF » sont interceptées par une unique servlet, la FacesServlet, définie dans le fichierweb.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>

Elle est chargée d'aiguiller l'intégralité des requêtes entrantes vers les bons composants, et ce pour l'application tout entière. Donc pas d’écriture du code responsable du regroupement des saisies utilisateurs (paramètres de requêtes HTTP), de leur conversion & validation, de la mise à jour des données du modèle, de l'invocation d'actions métiers et de la génération de la réponse. 


Les Managed-Beans

Les managed beans font l’interface entre les pages JSF et le reste de l’application. Un managed-bean fournit du code Java pour l’interface graphique. Il peut effectuer les traitements liés directement à l’interface utilisateur ; il fait appels à des EJB ou des classes Java ordinaires pour effectuer les autres traitements.

Le bean contient deux annotations spécifiques à JSF :

  • @ManagedBean : permet de préciser au serveur que ce bean est géré par JSF. Cela signifie simplement que JSF va utiliser ce bean en tant que modèle associé à une ou plusieurs vues. Par défaut, le nom du bean correspond au nom de la classe, la majuscule en moins. Si on veut désigner ce bean par un autre nom, par exemple direBonjour, alors il faut annoter le bean en précisant le nom souhaité, via @ManagedBean(name="direBonjour") ;
  • L’une des portées suivantes :
    • @RequestScoped
      • On crée une nouvelle instance du bean pour chaque requête.
      • Puisque les beans sont aussi utilisés pour initialiser des valeurs de formulaire, ceci signifie qu’ils sont donc généralement instanciés deux fois (une première fois à l’affichage du formulaire, une seconde lors de la soumission)
    • @SessionScoped
      • On crée une instance du bean et elle durera le temps de la session. Le bean doit être Sérialisable.
      • Utile par exemple pour gérer le statut « connecté/non connecté » d’un formulaire login/password.
      • On utilisera les attributs « render » des éléments de UI pour afficher telle ou telle partie des pages selon les valeurs des variables de session.
    • @ApplicationScoped
      • Met le bean dans « l’application », l’instance sera partagée par tous les utilisateurs de toutes les sessions.
      • Pour des méthodes utilitaires ou pour mettre en cache des informations qui ne doivent pas varier (liste des pays par exemple).
    • @ViewScoped
      • La même instance est utilisée aussi souvent que le même utilisateur reste sur la même page, même s’il fait un refresh (reload) de la page !
      • Le bean doit être sérialisable,
      • Convient bien pour les pages JSF faisant des appels Ajax (une requête ajax = une requête HTTP=> une instance si on est en RequestScoped !)



Cycle de Vie

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.
Voici les étapes côté serveur lors d'une requête :

Restauration de la vue :

La requête entrante est redirigée vers l'unique servlet jouant le rôle de super-contrôleur, la FacesServlet. Celle-ci examine son contenu, en extrait le nom de la page ciblée et détermine s'il existe déjà une vue associée à cette page. Il s'agit en réalité de restaurer les éventuels composants déjà chargés si l'utilisateur a déjà accédé à la page par le passé. La FacesServlet va donc chercher les composants utilisés par la vue courante. Si la vue n'existe pas déjà, elle va la créer. Si elle existe déjà, elle la réutilise. La vue contient tous les composants de l'interface utilisateur intervenant dans la page. La vue est sauvegardée dans l'objet FacesContext.

Conversion:

Dans cette étape, les valeurs des données sont extraites de la requête HTTP pour chaque composant et sont stockées dans leur composant respectif dans le FaceContext. Durant cette phase des opérations de conversions sont réalisées pour permettre de transformer les valeurs stockées sous forme de chaîne de caractères dans la requête http en un type utilisé pour le stockage des données. Ainsi, si un champ est lié à une propriété de type Integer, alors son contenu va être converti en Integer.

Validation :

Les valeurs converties vont ensuite être validées, en suivant les règles de validation définies par le développeur. Si la validation d'une valeur échoue, un message d'erreur est ajouté au FacesContext, et le composant concerné est marqué comme "invalide" par JSF. La prochaine étape est alors directement le rendu de la réponse, il n'y aura aucune autre étape intermédiaire. Si les valeurs sont correctes vis-à-vis des règles de validation en place, alors la prochaine étape est la mise à jour des valeurs du modèle.

Mises à jour des valeurs du modèle :

Cette étape permet de stocker dans les composants du FaceContext leur valeur locale validée respective.

Invocations des métiers et navigation :

Dans cette étape, le ou les événements émis dans la page sont traités. Cette phase doit permettre de déterminer quelle sera la page résultat qui sera renvoyée dans la réponse en utilisant les règles de navigation définie dans l'application. L'arborescence des composants de cette page est créée.

Création de la réponse :

Cette étape se charge de créer le rendue de la page de la réponse. La page HTML ainsi générée est finalement envoyée au client.


Quelques balises utilisées en JSF


Avec Quoi Developper

  • Avec une des IDE bien connus:
    • Eclipse
    • NetBeans
    • Oracle Jdeveloper
  • Un serveur d’application: Glassfish, Tomcat …
  • JDK (Java Development Kit)
  • En ce qui concerne JSF, il existe deux principales implémentations :
    • Oracle Mojarra, l'implémentation de référence, utilisée par défaut par GlassFish ;
    • Apache MyFaces, l'implémentation éditée par Apache.
Comments