JSF 2 : les principales nouveautés

La JSR 314 spécifiant la version 2 de Java Server Faces (JSF), le framework de développement d’IHM web fourni par JEE, a été livrée en version finale le 12 mai dernier (cf. http://jcp.org/en/jsr/detail?id=314).

Cette version 2 de JSF cherche à améliorer la productivité des développements, l’intégration d’AJAX et la ré-utilisation. Nous allons parcourir ici les principales nouveautés.

Les principales nouveautés

L’intégration native de fonctionnalités AJAX

Avec JSF 1, il fallait utiliser une autre librairie (RichFaces, IceFaces…) pour faire de l’AJAX, conduisant à une complexification de la configuration (ajout d’un filtre, de dépendances) et obligeant le développeur à maîtriser plusieurs frameworks. JSF2 dispose désormais d’un tag nommé « f:ajax » offrant la possibilité de mettre à jour une partie de la page lors d’évènements. Pour fonctionner, on doit inclure dans la page une librairie JavaScript fournie par JSF2. Par exemple, on veut ici mettre à jour la div panierDiv lors d’un clic sur le lien  addPronostic :


<h:outputScript name="jsf.js" library="javax.faces" target="body"></h>
<h:form>
<h:commandLink id="addPronostic" value="#{match.cote1}" action="#{mesPronosBean.addPronoCote1}">
<f :ajax render=":panierDiv" />
</h:commandLink>
</h:form>
<div id="panierDiv">...</div>

De plus, JSF2 va traiter côté serveur uniquement la partie de la page nécessaire. C’est la notion de partial processing. Cela améliore grandement les performances car auparavant, toute la page était traitée.

Le remplacement de configuration XML par des annotations

JSF 1 centralisait la déclaration des managed bean, de la navigation et bien d’autres choses dans le fichier faces-config.xml. On peut désormais déclarer des managed beans avec des annotations (des frameworks comme Spring le permettaient déjà), économisant des dizaines de lignes de configuration dans le fichier faces-config.xml :

@ManagedBean()
@SessionScoped
public class UserBean {...}

JSF 2 fournit également l’injection de dépendances de managed beans.

De même, les pages de destination peuvent être déclarées directement dans la réponse d’une méthode d’action :

<h:commandButton id="loginButton" action="#{monBean.doAction}"/>

Si la méthode « doAction » renvoie « hello », alors JSF interprétera  l’action « hello » comme la page hello.xhtml , et la cherchera dans les répertoires disponibles. S’il existe plusieurs pages du même nom, on pourra évidemment déclarer la navigation dans le fichier faces-config.xml.
Cependant, JSF laisse la possibilité d’utiliser la déclaration XMLdans tous les cas. Cela peut être parfois plus pratique, par exemple pour centraliser les informations dans un projet assez complexe.

La simplification de la création de composant :

L’utilisation de composants est le grand avantage de JSF. Il doit permettre la ré-utilisation de composants développés en entreprise, ainsi que de composants offerts par des librairies du marché (open-sources ou non).
Malheureusement, développer des composants avec JSF 1 était complexe et nécessitait l’écriture de nombreuses classes Java implémentant différentes interfaces, et de fichiers de configuration (cf. http://blogs.steeplesoft.com/jsf-component-writing-check-list/). Plusieurs initiatives ont vu le jour pour simplifier ce développement, comme le Component Development Kit de RichFaces. Le framework Facelets permettait également de simplifier un peu ce développement. JSF 2 a intégré Facelets et permet de créer des composants de manière déclarative dans un seul fichier XHTML, ne nécessitant plus ni l’écriture d’une classe Java (sauf si besoin est), ni de XML de description. De plus, on peut désormais créer des composants composites, qui peuvent être réutilisés dans d’autres composants.

Par exemple, on va définir un composant affichant le nom et le prénom d’une personne :


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">
<!-- interface -->
<composite:interface>
<composite:attribute name="user"/>
</composite:interface>
<!-- implémentation -->
<composite:implementation>
<h:form>
<h:outputText value="Prénom : #{cc.attrs.user.forname} Nom :
#{cc.attrs.user.name}"/>
</h:form>
</composite:implementation>
</html>

Points-clés :

  • composite:interface, composite:attribute et composite:implementation structurent la déclaration du composant.
  • #{cc.attrs.user} est la formulation JSF 2 pour récupérer le paramètre «monimage» déclaré par la vue ou le composant qui utilisera ce composant. Cc.attrs sont des mots réservés en JSF 2.
  • Le nom du composant est directement déduit du nom du fichier XHTML, et son namespace est construit avec http://java.sun.com/jsf/composite suivi du chemin où se trouve le composant, depuis la racine du site. Il est possible de modifier le préfixe « java.sun.com/jsf/composite », mais on complexifiera le code.

Pour l’utiliser dans une page, si le fichier précédent se nomme par exemple « usercomp.xhtml » et se trouve dans le répertoire « components/util », on l’utilisera comme suit :

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:util="http://java.sun.com/jsf/composite/components/util">
<util:usercomp user="#{sessionBean.user}"/>
</html>

Ce composant est bien évidemment simpliste, et dès que l’on a du code plus complexe, on devra utliser une classe Java, etc.

Standardiser et simplifier le développement de composants est un point crucial pour l’avenir de JSF. Ces nouveautés vont donc dans la bonne direction. Il faudra encore que les outils de développements suivent pour que cela soit le plus efficace possible : intégration aux IDE, plug-ins et archetypes Maven…

Une gestion des ressources plus puissante

On peut désormais placer les ressources (images, CSS, JavaScript) dans un répertoire nommé « resources » en dehors du répertoire WEB-INF, ou même les inclure dans un JAR à déposer dans ce même répertoire. Cela permet un meilleur versioning des ressources. On accédera par exemple à une image appelée « monimage.jpg » et à la racine du répertoire resources de la façon suivante :

#{resource['images:monimage.jpg']}

Templating

En intégrant Facelets à la la spécification , JSF 2 intègre désormais nativement des fonctions de templating de vue dans JSF. Cela évite encore d’avoir à inclure un framework tiers.

Bilan

JSF2 n’apporte pas de nouveauté révolutionnaire, et pourrait ressembler plus à une amélioration de JSF 1.2 qu’à une nouvelle version majeure. Il améliore tout de même la productivité et la ré-utilisation en simplifiant les développements, et ce de façon non négligeable.
Désormais, les limitations de JSF viendront sans doute de ses principes fondamentaux :

  • la nécessité pour JSF de gérer une représentation de la vue entière côté serveur, qui induit une charge de travail importante côté serveur, des temps de réponses plus longs et empêche de réaliser des vraies architectures stateless
  • son orientation navigation web classique, entre différentes pages, alors que les applications RIA tendent plutôt vers des applications à une seule page, manipulant des petits fragments du DOM via JavaScript et n’ayant pas besoin d’une vue globale de la page côté serveur
  • le principe de génération de HTML avec des tags, qui nécessite à la fois de savoir développer en HTML + CSS et de connaître les composants JSF. Sur ce point JSF peut souffrir à la fois de la concurrence de frameworks comme Wicket ou JavaScript classiques, qui sont non intrusifs dans le HTML et peuvent être mieux adaptés pour un bon développeur web, et de celle de GWT, qui permet de ne développer qu’en Java et être mieux adapté pour un développeur Java (cf. « faut-il-maitriser-son-code-html »).

L’amélioration de la productivité du développement, grâce à l’utilisation de composants et aux outils, notamment le support par les IDE, sera la clef pour la réussite de JSF, si les fondamentaux du framework ne changent pas.

P.S: on remarquera l’absence des tests dans cet article. L’absence de nouveautés dans JSF 2 concernant ce point ne signifie pas pour autant qu’il est impossible de tester. Cela pourra faire l’objet d’un autre article.

Pour aller plus loin

Commencer à utiliser JSF

L’API et l’implémentation de référence de JSF 2 sont déjà disponibles ici : http://download.java.net/maven/2/com/sun/faces/ et presque finalisées. Bien que JSF 2 ne fera partie que de la version 6 de JEE, il tourne sur la plupart des serveurs JEE 5 du marché (Tomcat, JBoss, Glassfish…). Pensez- simplement à mettre à jour les librairies JSF fournies par le serveur sur JBoss et Glassfish…

JSF 2 au Paris JUG

Mon collègue Damien Gouyette et moi-même présenterons une session du Paris Java User Group consacrée à JSF 2 le 15 octobre prochain.

Pensez à réserver vos places!

Liens externes

9 commentaires pour “JSF 2 : les principales nouveautés”

  1. Bonjour, et merci beaucoup pour cette synthese tres interessante.
    Je trouve personnellement qu’on oublie souvent de mentionner qu’en entreprise, pour les projets importants, on part quand meme toujours de maquettes d’écran faites par des designers. Et ces maquettes sont en HTML/CSS. Mais on prend rarement comme critère d’evaluation d’un framework l’intégration des écrans dynamique avec les maquettes HTML.
    Ainsi pour moi, un bon framework de présentation doit etre le moins intrusif dans la maquette fournie.
    Ainsi les frameworks tels que GWT par exemple sont trop complexes à utiliser pour des projets avec maquette!
    Du coup je ne comprends pas qu’on puisse dire que c’est un point négatif pour un framework quand il faut savoir maitriser HTML/CSS…

  2. @Gilles S

    Bonjour et merci pour votre commentaire.
    La nécessité de maîtriser HTML et CSS pour développer en JSF exige plus de compétences des développeurs au niveau des langages, que GWT qui permet de tout faire en Java.
    En revanche, comme vous le montrez, cela présente l’avantage d’être plus proche d’une maquette faite en HTML/CSS que GWT, mais moins que Wicket cependant. Ce point avait été traité plus en profondeur dans http://blog.octo.com/faut-il-maitriser-son-code-html .

    Cordialement.

  3. Rebonjour,
    Je ne suis pas un expert en Wicket mais en lisant le premier chapitre d’un livre sur Wicket, j’ai quand meme l’impression que:
    - c’est très bien pour conserver les « états » de certaines données en cours
    - c’est quand meme assez lourd, vu qu’il faut à priori une classe java par composant graphique. Et qu’il faut apprendre un langage de tag différent de JSP!!
    Au niveau gestion de compétences en entreprise c’est difficile de former des gens à ce genre de langage, surtout si c’est du long terme. Je préfère investir du temps et des ressources pour la gestion des tests et la qualité logicielle plutot que d’apprendre de nouveaux langages…

  4. Bonjour,

    merci pour cette présentation.

    nous avons travaillé sur un comparatif des « nouveaux » frameworks pour remplacer nos applis Struts. Dans notre démarche, un désigner nous a fourni une maquette à implémenter. Le but était de comparer GWT, JSF 1.2 + RichFaces et Wicket.

    Sans revenir sur tous les avantages et inconvénients de chacun de ces frameworks, j’ai surtout retenu la rapidité d’implémentation de Wicket. Il n’a pas un langage en tant que tel, car il consiste à ajouter principalement un tag pour identifier les composants de la page et pour pouvoir mapper les données. La maquette était complétement respectée, le développement côté Java très simple, parfaite intégration avec Spring, gestion des annotations, bref un bonheur. Le gros avantage a quand même été le fait de ne développé qu’en Java.

    Pour GWT, cela a été plus compliqué car il fallait l’intégrer à un portail existant en respectant une navigation page à page…

    Quant à JSF+RichFaces, pas mal. Même si certains comportements de composants en Ajax n’ont pas pu être implémentés et buggaient. De plus, appliquer notre ergonomie a été relativement difficile. Ce qui m’inquiète le plus dans ce framework c’est quid de l’évolution lors de montée de version de JSF ou RichFaces… Nouveaux tags, compatibilité ascendante, application des css ? Entre JSF1.1 et 1.2, les versions de Richfaces, les imbrications sont fortes et j’ai peur de mettre en place un système figé qu’il sera difficile de faire évoluer.

    Je pense refaire ma « Proof of Concept » avec JSF1.2, en espérant revoir ma position mais pour l’instant, je classerai Wicket devant dans mes préconisations.

    Cordialement

  5. un aspect que l’on oublie souvent reste le couplage entre Build et Run…

    JSF impose certaines version de JSP et de Servlet (de mémoire JSF 1.2 impose JSP 2.1 et servlet 2.5, de mémoire….)
    du coup, les cycles de développements et les versions de serveurs d’app sont liés : migrer/upgrader les dev implique d’upgrader son serveur d’app et upgrader les serveurs d’app (pour des optim….) peut avoir des impacts sur les dev.
    C’est un moins vrai avec des solutions comme GWT. wicket, j’avoue ne pas savoir.

    dans certains cas (bcp de serveurs…), ce peut être couteux. dans d’autres, c’est acceptable…

  6. @Olivier Mallasi
    Concernant la version de JSP/Servlet à utiliser avec JSF, ce n’est pas tout à fait exact. En fait, c’est seulement dans le cas où l’on compte effectivement utiliser JSP pour le développement des pages en JSF.

    Aujourd’hui, la tendance est clairement à facelets (d’ailleurs présent en standard dans JSF 2) qui permet de s’affranchir de la version de JSP/Servlet.

  7. Bonjour Akram,

    il existait un problème de cycle de vie différent entre JSF 1.X et JSP(cf. notamment « Beginning Java EE6 … » d’Antonio Goncalves, http://apress.com/book/view/1430219548).
    En effet, avec JSF 2, les JSP sont en partie supportées mais il est recommandé d’utiliser Facelets à la place.
    Cela supprime bien la dépendance entre JSF et JSP, en revanche, il existe toujours une dépendance entre JSF 2 et Servlet, qui doit être au-moins en 2.5.
    Il existe donc toujours des contraintes par-rapport au serveur, surtout si ce sont des serveurs JEE qui embarquent leurs implémentations de JSF (il y aura plus de conflits de versions de librairies à résoudre avec Glassfish ou JBoss qu’avec Tomcat ou Jetty par exemple).

    Au plaisir d’en parler au café ;)

  8. Bonjour,

    concernant votre commentaire sur les limitations de JSF 2 :
    « son orientation navigation web classique, entre différentes pages, alors que les applications RIA tendent plutôt vers des applications à une seule page, manipulant des petits fragments du DOM via JavaScript et n’ayant pas besoin d’une vue globale de la page côté serveur »
    Tout à fait d’accord ; cette fonctionnalité d’application à une page avec des fragments est supportée par le framework Oracle ADF et ses « TaskFlows » (extension du NavigationHandler) depuis environ trois ans.
    Le tout dernier JDev 11.1.2 intègre également JSF 2.0.
    Cordialement,

  9. J’ajoute également que les partial refresh sont supportés depuis longtemps et ceci sans besoin de javascript.

    Cdlt,