mika-el
4/7/2018 - 9:47 AM

JSF

Avec JSF, le traitement d'une requête entrant sur le serveur est découpé en six étapes, que nous allons parcourir sommairement :

  1. La 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 (eh oui, rappelez-vous bien qu'avec JSF la vue conserve un état). Voilà pourquoi cette étape s'intitule "restauration de la vue" : 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 (c'est-à-dire l'ensemble des composants qui y interviennent, et donc son état) est sauvegardée dans l'objet FacesContext.

  1. L'application des valeurs contenues dans la requête

Arrivés à cette étape, les composants de la vue courante ont tout juste été récupérés ou créés depuis l'objet FacesContext. Chacun d'eux va maintenant récupérer la valeur qui lui est assignée depuis les paramètres de la requête, ou éventuellement depuis des cookies ou headers. Ces valeurs vont alors être converties. Ainsi, si un champ est lié à une propriété de type Integer, alors son contenu va être converti en Integer. Si cette conversion échoue, un message d'erreur va être placé dans le FacesContext, et sera utilisé lors du futur rendu de la réponse. À noter qu'à cette étape peut intervenir la "prise en charge immédiate des événements" : cela veut dire que si un composant est marqué comme tel, sa valeur va directement être convertie puis validée dans la foulée. Si aucun composant n'arbore cette propriété, alors les valeurs de tous les composants sont d'abord converties, puis intervient ensuite l'étape de validation sur l'ensemble des valeurs.

  1. La validation des données

Les valeurs tout juste 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.

  1. La mise à jour des valeurs du modèle

Les composants peuvent être directement liés, par l'intermédiaire des balises présentes dans la vue, à des propriétés de beans. Ces beans sont qualifiés de managed-beans ou backing-beans, car ils sont gérés par JSF et la vue s'appuie sur eux. Si de tels liens existent, alors les propriétés de ces beans sont mises à jour avec les nouvelles valeurs des composants correspondants, fraîchement validées. Puisque la validation a eu lieu en premier lieu, le développeur est certain que les données enregistrées dans le modèle sont valides, au sens format du champ du formulaire. Il n'est par contre pas exclu que les données ne soient pas valides d'un point de vue de ce qu'attend le code métier de l'application, mais c'est tout à fait normal, puisque cette étape est la suivante dans le processus...

  1. L'appel aux actions, le code métier de l'application

Les actions associées à la soumission du formulaire sont alors appelées par JSF. Il s'agit enfin de l'entrée en jeu du code métier : maintenant que les données ont été converties, validées et enregistrées dans le modèle, elles peuvent être utilisées par l'application. La fin de cette étape se concrétise par la redirection vers la vue correspondante, qui peut dépendre ou non du résultat produit par le code métier. Il s'agit donc de définir la navigation au sein des vues existantes, ce qui est réalisé directement depuis le bouton de validation dans la page, ou depuis un fichier de configuration XML externe nommé faces-config.xml.

  1. Le rendu de la réponse

La dernière et ultime étape est le rendu de la réponse. La vue définie dans la navigation est finalement affichée à l'utilisateur : tous les composants qui la composent effectuent alors leur propre rendu, dans leur état courant. La page HTML ainsi générée est finalement envoyée au client, mais ça, vous vous en doutiez ! Voilà comment se déroule le traitement d'une requête avec JSF. Comme vous pouvez le voir, ça change du mode de traitement linéaire que nous avions adopté dans nos exemples MVC faits maison, notamment au niveau de la possibilité de prise en charge immédiate d'un événement qui permet le court-circuitage du processus global pour un composant en particulier ! Si tout ceci est encore très flou dans votre tête, c'est normal : beaucoup de choses vous semblent encore bien abstraites. Ne vous découragez surtout pas, car comprendre le fonctionnement de JSF est l'effort le plus intense qu'il vous faudra fournir. Dès lors que vous aurez assimilé comment se goupille toute cette mécanique, vous aurez fait plus de la moitié du chemin vers l'adoption de JSF ! ;) Pour vous aider à bien comprendre, je vous propose de découvrir ce processus dans un exemple pratique très simple. Mais avant cela, je vous propose de vous détendre un peu en découvrant une petite astuce sous Eclipse, permettant de préparer rapidement votre espace de travail au développement de Facelets, les fameuses pages que nous allons créer à la place de nos pages JSP.

  • JSF est un framework MVC basé sur les composants. C'est un standard, car il fait partie intégrante de la plate-forme Java EE 6.
  • Avec JSF, une unique servlet joue entre autres le rôle d'aiguilleur géant : la FacesServlet.
  • Avec JSF, il n'est plus nécessaire d'écrire de servlets : seuls des Facelets et des backing-beans sont nécessaires.
  • Dans sa version actuelle, JSF tire partie des annotations Java pour simplifier grandement le développement et la configuration.
  • Une Facelet est une simple page XHTML, contenant des balises qui lient littéralement la vue aux composants JSF, et leur associe d'éventuelles valeurs via des expressions EL.
  • L'ensemble des balises d'une vue, qui peut être constituée d'une ou plusieurs Facelets, constitue l'arbre des composants associé à cette vue.
  • Avec JSF, le processus de traitement d'une requête rassemble les étapes de récupération, conversion, validation et sauvegarde des données.
  • Lors du développement d'une application JSF, il est possible d'activer un mode de debug pour faciliter le pistage des erreurs rencontrées.
  • Une Facelet porte en général une de ces trois extensions : .jsf, .xhtml ou .faces. Il n'existe pas une unique extension pour la simple raison qu'une Facelet n'est rien d'autre qu'un document XML.
  • Une Facelet est constituée de balises, dont la syntaxe est très similaire à celles des balises JSTL utilisées dans une page JSP.
  • Le framework JSF intègre nativement trois bibliothèques standard : HTML, Core et UI.
  • La documentation officielle du framework JSF: https://jcp.org/aboutJava/communityprocess/final/jsr245/index.html
  • Une Facelet est une page constituée d'une suite d'appels à des composants JSF (réalisés par l'intermédiaire de balises), et ceux-ci forment ce que l'on appelle un arbre de composants, ou component tree.
  • À la différence des JSP, les Facelets JSF conservent un état (on dit alors que la vue est stateful) : ce sont les composants autonomes appelés par l'intermédiaire des balises contenues dans les Facelets qui permettent de maintenir cet état.
  • Les composants JSF suivent le pattern de l'objet composite pour gérer un arbre de composants : en clair, cela signifie à la fois qu'un objet conteneur contient un composant, et qu'un objet conteneur est lui-même un composant.
  • Il existe deux principales implémentations de la spécification JSF:
    • 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.