Cet article fait partie d’une série d’article sur les technologies incluses dans Java EE 6. Vous pouvez également lire l’article d’introduction de cette série : Java EE 6 ici et maintenant.
Le meilleur outil pour parler technologies ?
Il est certaines technologies qui déclenchent les passions. Elles recèlent en elles le potentiel de polariser les opinions et laissent peu de gens modérés ou indifférents à leur sujet. Elles vont parfois jusqu’à déclencher des guerres de religion (on a les combats que l’on peut) dans lesquelles s’embarquent quelques consultants IT.
JSF fait assurément partie de ce petit groupe d’outils ou de frameworks voués aux gémonies par les uns ou portés aux nues par les autres.
Autant l’avouer tout de suite, je suis plutôt pro-JSF, tout en essayant de garder une certaine objectivité à son endroit. Bien que cette technologie m’ait fait beaucoup souffrir lorsque j’ai commencé à l’utiliser en 2005, elle m’a aussi bien des fois agréablement surpris ou jeté dans des abîmes de frustration à d’autres. Autant dire que j’ai entretenu des rapports oscillant entre l’amour et la haine avec JSF.
Cependant, j’ai récemment commencé un projet avec JSF 2 et je dois admettre que, au risque d’écorner l’équanimité dont j’aime à faire preuve : “JSF 2 ça déchire grave”.
Vis ma vie avec JSF – un retour d’expérience
J’ai commencé à m’intéresser à JSF en 2004. Faisant exclusivement des développements web, ma stack d’alors était composée de Spring 1.0.1, de Struts 1.2 et d’iBatis 2. Struts me plaisait bien mais je trouvais qu’il me manquait quelque chose pour enrichir mes interfaces utilisateur. Bien sûr, j’utilisais les Jakarta taglibs d’Apache pour avoir des bibliothèques de tag JSP un peu plus étoffées et en développait moi même, mais ça restait globalement anémique. J’ai donc commencé à explorer JSF pendant la deuxième moitié de 2004 en parallèle de mes projets et ai eu l’opportunité de mettre ce savoir faire en pratique dès 2005 avec JSF 1.1 sur un beau projet. Autant l’avouer, le passage de la théorie à la pratique s’avéra être une douche froide : la technologie telle quelle, sortie de la boîte, était quasiment inutilisable pour un vrai développement d’interface avec du HTML. Et en même temps, certains aspects de la technologie étaient assez magiques comme les listeners qui permettaient de réagir à des événements sur l’interface ou tout le système de conversion et de validation qui bien qu’un peu lourd était bien conçu.
Ce premier projet fut pour moi une leçon de frustration ponctué de : “ça marche presque” ou de “dommage, ça avait l’air puissant mais, c’est inutilisable”. J’arrive tout de même à livrer mon appli (je me serais clairement planté si j’avais dû composer avec des graphistes et des webdesigners) et mon client, satisfait, m’en commande une seconde reprenant et étendant certaines fonctionnalités de la première. Là, j’ai un gros doute : est-ce que je repars de 0 avec quelque chose de plus classique ? Ou est-ce que je m’entête en essayant de trouver comment combler les 5% de fonctionnalités manquantes à la techno pour qu’elle soit productive ? Ayant des délais assez large, je prends le parti d’explorer la deuxième piste en me disant que si je ne trouve rien, j’aurais toujours le temps de repartir de zéro. C’est à ce moment là, que je découvre (grâce à tous les développeurs ayant souffert avant moi) le projet Facelets qui constitue la première lueur d’espoir dans ce désert de frustration qu’était JSF. Facelets en levant le frein du templating, rend la technologie utilisable sans camisole de force et capitonnage des murs. Je livre donc ce second projet beaucoup plus sereinement que le premier, même si tout n’est pas parfait.
A cette époque (début 2007), la version 1.2 de JSF est sortie et fait officiellement partie de Java EE 5, je croise de nombreux petits projets, mais n’ayant pas eu une expérience sans reproche avec JSF, je laisse la techno de côté, jusqu’à ce que je tombe dans JBoss Seam. Et là, je trouve le sésame. Seam débloque enfin JSF et le rend élégant et productif en comblant ses lacunes et corrigeant ses défauts. Après pas mal de petits projets et surtout deux gros menés avec ce framework, je peux affirmer que c’est l’un des mélanges les plus productif de l’éco système Java.
Bilan pré JSF 2 : JSF c’est génial quand y ajoute la techno de templating Facelets et le framework Seam sans oublier une bonne bibliothèque de composants comme Richfaces, Primefaces ou Icefaces. Ca fait beaucoup de choses à apprendre et maitriser pour une simple techno d’IHM. Et puis, que dire d’une technologie standard devant s’appuyer sur des solutions, certes Open Source, mais propriétaires pour être utilisable ?
Mais il semblerait que d’autres pensaient comme moi, car comme par magie, tous ces défauts ont été gommé avec la version 2 de JSF. Facelets fait désormais partie intégrante de la spécification et les apports de Seam pour JSF ont été intégrés. Mais j’y reviendrai plus loin.
Pourquoi tant de haine ?
Une perception de JSF assez juste à l'époque mais qui perdure injustement
Je pense avoir déjà donné un début de réponse à cette question dans le paragraphe précédent. Au delà d’un ressenti empirique et personnel, il me parait intéressant de synthétiser les anathèmes un peu primaires de tous les “Hate Boys” qui ont alimentés les rubriques “JSF sucks” que l’on retrouve dans la quasi totalité des sites liés à Java (je ne mets pas de lien sur ces sites histoire de ne pas contribuer à leur pagerank). Certains de ces reproches étaient bien fondés, d’autre un peu plus une question d’appréciation personnelle ou de mauvaise foi.
Mauvais paris sur l’évolution du Web
Gardons à l’esprit que les débuts de la conception de JSF remontent à 2001 et qu’à cette époque là, il était assez difficile d’imaginer le Web tel qu’il est aujourd’hui. Il s’agit d’une époque où l’applet java est toujours une solution client viable et où javascript n’est qu’une technologie de seconde zone à qui on délègue au mieux la vérification des champs des formulaires.
Les gens travaillant sur la première spécification de JSF, ont donc clairement raté les évolutions REST et Ajax du Web, obsédés qu’ils étaient de faire un Swing pour internet. Cela conduit à deux gros défaut
L’utilisation d’un technologie de templating ignorant HTML
Là, rien à dire. C’est une erreur grossière qui a coûté beaucoup à la réputation de JSF. La technologie de templating par défaut de JSF 1.X est basée sur JSP et n’accepte que des tags JSF (le tag f:verbatim permet royalement d’intégrer du HTML au sein de JSF, mais rien pour intégrer des composants JSF dans du HTML). L’arrivée de Facelets et la possibilité de modifier la technologie de templating dans JSF a corrigé cette énorme lacune. Mais le côté un peu amateur du projet Facelets et le manque de soutien officiel de l’Expert Group JSF ont fait que Facelets est resté pendant longtemps confidentiel ou source d’interrogation sur la pérennité du mélange.
L’activation du cycle de vie JSF seulement à partir d’un POST HTTP.
Autre grossière erreur de conception : considérer que seul le POST HTTP peut être le point de départ d’un traitement complet côté serveur. Je reviens un peu plus loin sur le cycle de vie JSF, mais en gros, celui-ci a besoin d’être activé pour que la partie serveur soit sollicitée. Cette limitation en plus de complexifier inutilement les développements a eu des effets secondaires désastreux pour la réputation du framework. Il en découlait l’impossibilité d’avoir des URL bookmarkables par exemple ou l’impossibilité de réagir de manière élégante à la sollicitation d’une url sécurisée (la jonction entre une éventuelle partie servlet/jsp et une partie JSF entrainait de grosses coutures dans les applis avec obligation d’avoir recours à des mauvaises pratiques).
De nombreuses solution tierces (Seam en tête) ont apporté une solution à cette grosse lacune. Là encore, la polyvalence de JSF a permis d’apporter ces corrections de manière élégante et en greffant naturellement des extensions aux points prévus dans la spécification. Néanmoins, avoir recours à l’une de ces solutions consistait souvent à retomber sur une technologie propriétaire qui n’était pas toujours compatible avec des extensions ou bibliothèque de composants d’autres tiers.
Le cas AJAX
L'accolyte d'Ajax
Entre 2001 et 2004, période de conception de JSF, le concept de communication asynchrone entre le browser et le serveur est encore une excentricité que personne (à part Google) ne considère vraiment sérieusement. C’est l’âge d’or de Corba et IIOP et peu de gens envisagent que le web devienne une plateforme applicative riche. On ne peut donc pas trop blâmer l’Expert Group JSF de ne pas avoir anticiper ce besoin en limitant la spécification aux seules commandes POST et un peu GET pour dialoguer entre client et serveur.
Néanmoins, ce manque a dû être comblé par des tiers de manières très variées rendant les diverses bibliothèques de composants faisant de l’Ajax totalement incompatibles les unes avec les autres.
L’écosystème de la frustration
Très tôt de nombreux éditeurs se sont emparé de JSF pour proposer des bibliothèques de composants. Il suffit d’aller jeter un coup d’oeil sur JSF matrix pour se rendre compte , que cette technologie a inspiré beaucoup de monde. Cet aspect aurait pu jouer en faveur de JSF, mais malheureusement les limitations ou lacunes évoquées ci-dessus ont gravement morcelé l’eco-système : chaque éditeur apportant ses propres solutions pour combler ces manquements, les différentes bibliothèques de composants sont devenues très rapidement incompatibles entres elles. Ainsi, la spécification JSF a donné lieu à un morcellement et à la création de Framework de composants parallèle comme ADF Faces ou Ice Faces ou dans une moindre mesure Rich Faces. L’intérêt de la technologie devenant dès lors,très secondaire, puisqu’il était possible de monter un véritable écosystème.
Le cycle de vie JSF
Pour finir sur des notes positives, j’aimerai revenir sur des reproches nettement plus injustifiés rencontrés chez les détracteurs de JSF. Au centre de ces critiques, le cycle de vie JSF. Ces critiques qu’on pourrait globalement intituler : “je n’aime pas JSF, parce qu’il ne fait ce que je veux”, sont assez voisines de celles que l’on croise concernant une autre technologie bâtie autour d’un cycle de vie : Maven. J’en conclus que la plupart des développeurs préfèrent adapter une technologie à ce qu’ils savent plutôt que de l’apprendre et de voir si leur fonctionnement standard convient à leurs besoins.
En effet, le cycle de vie de JSF est central dans la technologie et l’ignorer c’est clairement aller au devant de beaucoup de problèmes rédhibitoires. JSF ne propose pas de bidouillages ou raccourcis genre scriplet permettant de faire l’économie de l’apprentissage de la technologie. Toutefois, si le cycle de vie est incontournable, il propose de nombreux points d’extension. C’est d’ailleurs grâce à cette extensibilité que JSF a pu être sauvé : les développement des différentes solutions palliatives ont su tirer parti de cet extensibilité pour proposer des add-ons élégants à JSF 1.
Un beau cycle de vie qui rachète beaucoup de choses
Les performances
JSF a souvent été critiqué pour ses “mauvaises” performances. Sans aller jusqu’à dire que c’est un foudre de guerre, je pense que beaucoup de choses fausses ont été écrites sur le sujet et que les problèmes de lenteur de JSF sont souvent due à une mauvaise connaissance du framework (cycle de vie et fonctionnement de certains composants). Débattre sur ces questions n’est pas l’objet de cet articles, néanmoins, je vous renvoie vers cet article très intéressant de Dan Allen sur l’optimisation de datatable dans une appui JSF / Seam qui montre qu’en se penchant sur le sujet, on peut diviser les temps de réponse par 10.
JSF malgré tout
Après ce réquisitoire aux allures définitives, vous êtes en droit de vous demander pourquoi je n’ai pas mis JSF à la poubelle comme beaucoup l’ont fait depuis longtemps. Au delà d’un simple entêtement, j’ai de bonnes raisons d’avoir persévéré dans cette technologie.
La communauté
La taille de la communauté autour de JSF est tout simplement énorme. C’est assez difficile de s’en rendre compte parce qu’en France, cette technologie est plutôt marginalisée au profit de Struts et de Spring MVC avec JSP ce qui fait qu’un adepte de JSF se sent parfois aussi esseulé qu’un fan de Daniel Guichard égaré dans un concert de Rammstein.
Néanmoins, il suffit d’aller sur Internet pour voir que les sites spécialisés et blogs sur JSF pullulent. On peut citer rapidement JSF central ou JSF Tutorials ou encore tous les site d’éditeurs de bibliothèque de composants que vous retrouverez sur JSF Matrix. Cette communauté est plutôt enthousiaste et constructive. Elle s’organise également beaucoup autour des grandes bibliothèques de composants JSF comme ICEfaces (l’une des première solution d’IHM pour Java full Ajax, sortie en 2005), RichFaces ou le plus récent mais très efficace PrimeFaces. Jusqu’à l’arrivée de JSF 2.0 ces communauté étaient assez étanches puisque choisir une bibliothèque rendait quasiment impossible d’utiliser les composants d’une autre. Depuis un an ces communautés s’ouvrent les unes aux autres, enrichissant encore plus l’éco-système.
L’or sous la boue
La lecture du début de cet article pourrait laisser penser que JSF est une technologie définitivement handicapée à la naissance. En fait ce qui a sauvé cette technologie tient au fait que son noyau est extrêmement bien pensé et hyper paramètrable. Ce noyau permet de changer la technologie de rendu, d’intervenir dans le cycle de vie des requêtes ou de changer de technologie pour le binding des objets côté serveur. Ce qui a plombé JSF, c’est que les choix par défaut de configuration de la techno étaient mauvais ou nettement incomplets. Les solutions tierces autour de JSF sont la meilleure démonstration de cette qualité intrinsèque de la spécification : elles se greffent toutes de manière naturelle à la technologie pour la compléter ou palier à des parties déficientes. ICEFaces qui s’approprie totalement le cycle de vie de JSF ou Seam 2.X qui l’enrichit pour gommer tous ses défauts illustrent parfaitement cette ouverture dans la technologie.
Bien sûr, celui qui passe rapidement à côté de la techno ou qui la subi sans chercher à comprendre ne retiendra que la couche boueuse, mais il suffisait de creuser pour voir l’or à l’intérieur.
La solution composants / événement “standard”
Oui je sais : “on ne doit pas choisir une technologie parce qu’elle est standard”, je connais le refrain souvent rabâché par certains développeurs qui ne veulent pas bousculer leurs habitudes. Je suis globalement d’accord avec ce constat, mais je pense qu’il faut aussi ne pas refuser par principe une technologie parce qu’elle est standard. JSF est désormais un bon standard et même si cette technologie n’est pas adaptée à tous les besoins, je pense qu’il est fortement souhaitable que tous développeur d’applications web java la connaisse ne serait-ce que pour avoir un point de comparaison avec la technologie retenue sur leur développement.
Pour JSF (comme pour beaucoup de technologies Java EE) l’intérêt premier d’être un standard et d’avoir une spécification, c’est de disposer de plusieurs implémentations. JSF dispose de deux implémentations : celle de référence par Oracle : Mojarra et celle d’Apache : MyFaces. Ces deux implémentations sont de très bonne qualité et permettent aux développeurs de choisir le moteur le plus performant pour leur projet. L’émulation qui nait de l’existence de ces deux projets est bénéfique pour tout le monde et si votre implémentation contient un bug qui vous gêne, vous pouvez toujours basculer sur l’autre (c’est du vécu).
Seam, le framework aux belles coutures
Seam
Je parle beaucoup de Seam, mais ce framework a apporté beaucoup à Java EE. En proposant une approche plus moderne de l’injection de dépendance et en palliant à quasiment tous les défauts de JSF 1.X, ce framework joue le rôle de chaînon manquant dans l’histoire de Java EE.
Pour plus d’information sur le sujet vous pouvez toujours lire Les rendez-vous manqués de Spring qui revient sur ce point. Quoiqu’il en soit, les créateurs de Seam ont décidé de contribuer la majeure partie du framework à Java EE et d’en faire une spécification (CDI) et des améliorations pour JSF. Ces améliorations, plus celles d’autres vendeurs membres de l’expert group JSF 2.0, font de cette nouvelle spécification une vraie réussite.
JSF 2.0 : un nouveau départ
Je ne vais pas faire une revue détaillée des nouveautés et évolutions de JSF 2.0. D’autres l’ont fait bien mieux que moi (et j’ai déjà perdu 80 % de mes lecteurs avec la longueur de mon post), je vous recommande donc la série d’articles écrits par les membres de l’Expert Group JSF 2.0 sur Java Lobby. Je reviendrais juste sur les aspects principaux de ces évolutions.
Standardisation de Facelets
J’ouvre le bal avec une non-nouveauté. Le Facelets de JSF 2 est peu ou prou celui que l’on utilisait avec JSF 1.X. L’énorme nouveauté, c’est qu’il s’agit désormais du langage de templating par défaut de JSF. Parler des bienfaits de Facelets sur la conception et le découpage d’une interface ainsi que le partage des rôles entre monteurs HTML et développeurs pourrait nous embarquer encore quelques dizaines de paragraphes que je réserve a un autre post. Toujours est-il que cette standardisation, stabilise JSF et constitue la reconnaissance officielle de l’Expert Group du ratage du templating dans JSF 1.0
Le vrai support du get et ses conséquences
Bon, ok : “support du get”, vous pouvez ricaner (mais pas trop). Là encore, ce gros trou dans la raquette JSF était comblé depuis longtemps par des solutions tierces (je vous ai parlé de Seam ?), mais là ça y ‘est vous pouvez écrire un truc du genre :
<f:metadata> <f:viewParam name="orderid" value="#{commandHandler.orderId}" required="true" requiredMessage="You should provide an order id" /> <f:event type="preRenderView" listener="#{commandHandler.initOrder}" /> </f:metadata>
ainsi les paramètres de l’URL peuvent maintenant être récupérés à l’ouverture de la page et un traitement peut être lancé dans la foulée. Traitement pouvant le cas échéant rediriger vers une page d’erreur en cas d’échec.
Ajax
Ajax fait enfin partie intégrante de JSF, il s’intégre au cycle de vie nativement et il est possible de l’invoquer soit par appel javascript soit par un tag JSF. Le rafraichissement partiel des vues JSF est supporté et le support de technologies évoluée comme Atmosphere est inclus dans MyFaces et devrait l’être bientôt dans Moraja.
Les composants Facelets
Le développement de composants JSF était une tâche assez fastidieuse dans JSF 1. Elle devient plus aisée dans JSF 2 grace à la sauvegarde d’état partiels mais surtout grâce à Facelets qui permet de créer un type de composants assez simple : les composites. Il s’agit en fait de morceaux de vues (pages) JSF très paramétrable et ré-utilisables. Ce concept permettra par exemple de créer un tag jsf pour inclure une applet flash ou un effet jQuery qui doit se répèter (bulle d’aide).
Intuitive et versatile, cette approche qui existait déjà dans les versions antérieures de facelets donne une souplesse appréciable dans la conception d’interfaces et fait de JSF une vraie technologie “Légo” modulaire.
Un monde de composants interopérables
Amélioration de interactions avec le cycle de vie JSF
Le cycle de vie JSF n’a pas fondamentalement évolué depuis JSF 1. Ce qui change beaucoup, ce sont les outils pour interagir avec lui. le tag <f:event> permet de réagir à un événement survenant dans une phase donnée (comme dans l’exemple de récupération de paramètre donné ci-dessus). Ces événement peuvent également déclencher des appels javascript ou du code Java de manière beaucoup plus naturelle qu’auparavant. Le cycle de vie devient donc plus facile à adapter à des besoins particuliers ce qui rend le framework encore plus polyvalent.
De plus la gestion des exceptions est enfin intégrée (Seam again), et il est possible d’aiguiller automatiquement vers une page d’erreur JSF ou JSP en cas de soucis dans un traitement.
Une navigation améliorée et simplifiée
Amélioration en provenance de Seam à nouveau. Les règles de navigation conditionnelles permettent de rendre plus souple la navigation dans les vues JSF et les actions dans les tags JSF peuvent désormais être soit des vues de destination soit des outcomes qui seront traités par le processus de navigation sans avoir besoin de passer par l’invocation du code.
Conclusion : JSF 2 le mélange équilibré de l’IHM Web ?
Pour conclusion, j’évoquerai les approches antagonistes actuelles entre les frameworks qui prônent le do it yourself concernant la partie IHM (Ruby on Rails, Play!, Spring MVC) et ceux qui livrent des approches de composants riches laissant peu de contrôle sur le code produit (GWT ou Vaadin par exemple). Ces deux perceptions ont leurs avantages et inconvénients et je me garderai bien de trancher sur le sujet.
Simplement, je remarque que JSF 2.0 est une solution qui permet de jouer sur les deux tableaux, en permettant de développer soit même des composants réutilisables de manière très simple et/ou d’avoir recours à des bibliothèques très riches de composants haut niveau qui vont produire des interfaces riches sans que l’on ai à maitriser HTML 5, CSS3 ou Javascript.
Pour ceux qui se demandent encore pourquoi JSF est la technologie standard d’IHM web de Java EE 6, je pense que la réponse se trouve beaucoup dans cette souplesse et que, même si JSF a encore des progrès à faire, il a le mérite de proposer la bonne péréquation entre la conception d’interfaces simples et la création de client Web riches. Une synthèse presque parfaite des frameworks web Java en quelque sorte.