Afin de rendre les mêmes vues côté serveur et côté client, nous avons ajouté Handlebars à notre boîte à outils, et nous l’utilisons même au sein de nos JSP existantes.

Pourquoi Handlebars ?

  1. Implémentation et évolution de Mustache, c’est un moteur de templating simple, connu, et éprouvé.
  2. Il est disponible dans beaucoup de langages, et notamment dans les deux qui nous intéressent : JavaScript et Java.
  3. Il est logic-less, c’est à dire qu’il sert à mettre des données dans des trous, et c’est tout. Il permet tout de même de rendre un même bloc pour une collections d’objets (#each) et de tester une valeur booléenne ou la présence d’un objet (#if). Mais il ne permet pas d’écrire de code dans les templates. Par exemple une condition #if pourra uniquement tester un booléen déjà calculé et présent dans les données. De cette manière, Handlebars nous évite de nous tirer une balle dans le pied.

Voici un exemple de template Handlebars :

Super, c’est beau comme des points-virgules alignés, il n’y a plus qu’à mettre tout ça en place ! La suite de ce billet est la recette de cuisine pour parvenir à nos fins. Allergiques au code s’abstenir.

Mise en place côté JavaScript

L’implémentation JS de Handlebars permet de compiler nos templates en des fonctions JavaScript dès la construction des fichiers que nous allons servir. Ainsi on ne dépend plus que de quelques fonctions de Handlebars au runtime, ce qui limite le code à charger côté client. C’est donc la voie que nous avons choisie.

Mieux, avec handlebars-loader et la configuration suivante, Webpack va faire cela automatiquement pour nous, pour tout code JS important un template Handlebars (extension .hbs par convention) :

Ainsi, le code suivant donnera ensuite un unique fichier JavaScript :

Côté client, check! À présent allons voir côté serveur.

Mise en place côté serveur

Handlebars.java est une implémentation Java de Handlebars (quelle surprise !), qui vient avec plein de bonnes choses comme les typesafe templates ou le support Markdown.
Et notamment, elle propose aussi une intégration optionnelle à Spring MVC. Il se trouve que nous utilisons Spring Boot, ça tombe bien ! Cette intégration fournit le ViewResolver qui va bien pour juste donner le nom d’un template Handlebars en sortie d’un Controller et laisser la magie opérer. Elle permet aussi de gérer simplement le localisation des vues en branchant le helper “message” sur nos MessageSource (voire ce qu’est un helper Handlerbars un peu plus bas).

Exemple de Controller rendant le template “hello” vu plus haut :

La configuration de l’engin est aisée : avec le module Spring MVC, il suffit d’ajouter HandlebarsViewResolver à la configuration Spring ! (Et sinon, voir plus bas.)

Bref, c’est tout bénef ! Enfin, si on veut écrire des vues Handlebars from scratch… Mais quid de nos JSP existantes ? Ne serait-il pas beau de pouvoir dès le début rendre des composants handlebars en plein milieu d’une JSP ? Ah ben ça tombe bien, c’est le titre suivant, juste là :

Utilisation au sein de JSP

On va respecter ici la manière “JSP”, et directement écrire le code Java qui va bien dedans. Non je plaisante, on va faire ça proprement et écrire une petite taglib nous permettant de compiler un template s’il ne l’est pas déjà, puis d’écrire dans la sortie le résultat de l’appel de ce template avec les arguments souhaités.

Exemple d’utilisation souhaitée :

Forcément il faut écrire des tags et un Tag Lib Descriptor et c’est un peu verbeux, mais ce n’est qu’un mauvais moment à passer. Aussi, pour que cela fonctionne, il faut reprendre la main sur le module Spring MVC et configurer une instance de Handlebars à notre sauce. Allez, je mets tout là pour être complet :

Et enfin le TLD et la config Spring, comme promis :

Et voilà, on y est !

Enfin presque, car il nous reste à traiter d’un dernier point.

Écriture et partage de helpers

Sans trahir le côté simple et logic-less de Handlebars, il est tout de même nécessaire ou très intéressant d’écrire des fonctions utilitaires pour quelques problématiques communes de rendu (des helpers). Sans cela il serait nécessaire de tout prémâcher et de donner à Handlebars des données contenant par exemple des dates déjà formatées.

Nous avons donc écrit une dizaine de ces helpers, pour formater des dates, sortir les bonnes traductions, rendre des textes écrit en pseudo Markdown, etc.

Problème, il faut à chaque fois écrire les helpers dans les deux langages cibles. Une bonne raison de limiter leur utilisation et de ne pas mettre trop de magie dans nos vues.

On aurait pu envisager de les écrire uniquement en JavaScript pour ensuite les appeler en Java avec Nashorn, mais cela n’est pas possible pour certaines API de la lib pas-si-standard JS, et peut-être même pas si souhaitable d’un point de vue performances. Enfin, nous n’aurions pas pu traiter le cas particulier de la localisation des textes de cette manière car il ne s’agit pas ici juste de coder un comportement deux fois. (Nous aborderons peut-être ce large sujet dans un prochain article dédié à l’internationalisation.)

Voici un exemple très simple d’un helper concaténant ses arguments, en JavaScript, et en Java :

Ouf, la conclusion !

Avec tout cela en place, nous pouvons à présent rendre des composants graphiques côté serveur — y-compris dans des vues JSP existant depuis longtemps — puis rafraîchir ces composants côté client avec le même template. Pour peu que le code client récupère ses données du serveur via des appels HTTP (RESTful ou non), nous pouvons également faire en sorte de ne pas dupliquer la logique produisant ces données.

Et puis… les templates Handlebars, c’est quand même plus plaisant à l’œil que les JSP 😛 Bon, c’est subjectif et pour être honnêtes nous n’allons pas arrêter d’écrire des JSP tout de suite. Les deux systèmes vont cohabiter, mais au moins il le feront en bonne entente !

Leave a Reply

Your email address will not be published. Required fields are marked *