Aujourd’hui, malgré les versions qui se suivent avec un rythme effréné, parfois avec une totale discontinuité entre les versions, Angular est devenu LE framework MVVM à la mode et celui utilisé sur la vaste majorité des projets. Les esprits chagrins pourraient y voir l’emprise et la toute puissance de Google sur le monde des développeurs Web plus que les qualités intrinsèques du framework… Et constater que son principal challenger, React, est lui même porté par Facebook et ne fait que corroborer cette analyse. Le pouvoir est maintenant passé dans la main des évangélistes, eux mêmes bien souvent à la solde de grosses compagnies…
Pourtant, il existe des frameworks réellement alternatifs, comme Vue.js (voir les nombreux posts de blog récent sur ce support) et Ember, objet de cette série d’articles. Ces solutions apportent souvent une vision originale et efficace pour la construction d’applications Web évoluées.
En ce qui concerne Ember, le point qui est à mon sens le plus discriminant tient dans son extension Ember Data dont l’objectif est de rendre l’application totalement agnostique de sa couche de persistance et des services qui la composent. Il s’agit au final d’une espèce d’ORM JavaScript encapsulant de manière fort intelligente les appels au backoffice et offrant en prime un mécanisme de cache et une abstraction de leur format. Bien entendu, un peu à la manière d’Hibernate, la courbe d’apprentissage est importante, mais les bénéfices valent largement l’effort !
Cette série d’articles a pour objectif de mettre en valeur ce point fort du framework. Elle commencera donc par expliquer les principes sous-jacents d’Ember au travers de la construction progressive d’une application intégrant petit à petit les concepts-clés.
Les étapes envisagées sont les suivantes :
- Etape 1 – Application simple avec données ‘rack’ retournées directement par le modèle sous forme d’un tableau JSON. Cette étape sera complétée par l’utilisation d’addons Ember pour rendre l’application plus esthétique et ergonomique.
- Etape 2 – Passage sur un modèle géré par Ember Data. Etant donné qu’aucun backoffice ne sera déployé, nous introduirons le framework de mock Mirage pour intercepter les appels HTTP.
- Etape 3 – Introduction d’une relation rack —> bottle, et enrichissement des données mockées.
- Etape 4 – Construction d’un composant graphique permettant une représentation d’un rack et simplifiant les templates d’affichage.
- Etape 5 – Mise en place d’un backoffice construit à l’aide de JHipster. Nous profiterons des capacités de cet outil pour obtenir rapidement un modèle persisté en base, les services Rest permettant de l’administrer ainsi qu’une interface d’administration. Nous verrons au passage quelques problématiques liées à la sécurité.
- Etape 6 – Mise en place d’un backoffice sur services Liferay et packaging de l’application Ember au sein d’une portlet. Nous avons choisi un backoffice Liferay pour sa facilité à construire un modèle de persistance mais surtout pour bien démontrer l’utilisation potentielle des Adapters et des Serializers, même si un backoffice plus conforme aux standards REST n’en sera que plus aisé à utiliser.
Dans la mesure du possible, nous avons repris tout le code produit au sein du document. Néanmoins, celui-ci est disponible sur https://gitlab.ippon.fr/bpinel/EmberCellar.
Cas d’utilisation
L’application ‘fil rouge’ que nous utiliserons consiste en un gestionnaire de cave à vins. Dans l’immédiat, notre cave à vin sera donc composée d’étagères (‘Racks’) permettant de stocker des bouteilles (‘bottles’) selon une matrice colonnes / lignes. Bien entendu, ce modèle simpliste pourra être ultérieurement largement élargi pour intégrer les notions de Produit, Producteur, Appellation, Région, Pays, etc..
L’autre point important, c’est que la construction de cette application pourra s’appuyer sur un mode d’organisation bien particulier :
- Des développeurs Front, ayant de bonnes compétences sur la stack web HTML5 / CSS / Javascript mais pas forcément en Java,
- Un back-office serveur en Java, fournissant des services web JSON, pas forcément très REST…
Fini le besoin impérieux de développeurs fullstack maîtrisant toute la chaîne du système et tous les langages et frameworks qu’il emporte !
Reste que l’objectif principal de cet article est de démontrer le caractère agnostique de cette solution par rapport au backoffice fournissant les services Web. Ceux-ci n’auront en effet pas le besoin impérieux de respecter des règles REST précises, tant qu’ils permettent de mettre à disposition la donnée brute.
Opérations préalables et concepts clef d’Ember
Pour la suite de ce tutorial, nous partirons du principe qu’EmberCLI (et donc Node.js) est déjà installé (voir https://ember-cli.com/).
Avant toute chose, il convient donc :
- d’installer un client Git,
- d’installer Nodejs (via une distribution disponible sur https://nodejs.org/en/,
- d’installer npm en exécutant simplement la commande npm install npm@latest -g,
- d’installer l’environnement CLI en tapant npm install -g ember-cli,
- pour plus de facilité, d’installer le plugin Chrome pour Ember.js.
Nous vous conseillons également de consulter le site d’Ember (https://emberjs.com/) : la documentation et les tutoriaux sont d’excellentes factures. Ils existent également de très bonnes ressources sur le web et je conseille fortement le eBook (payant) de Balint Erdi, Rock and Roll with Ember.js (https://balinterdi.com/rock-and-roll-with-emberjs/). Ce document a la double qualité d’être très didactique et de subir des mises à jour régulières en fonction des nouveautés du projet.
Le schéma suivant rappelle brièvement les principaux concepts sous-jacents d’Ember :
- Le Router traduit une URL dans une série de templates imbriqués, alimentés par un modèle. Une URL de type http://host:post/racks/rack/1 passera donc successivement par les routes correspondant à ‘/’, ‘/racks’ et ‘/racks/rack’ pour s’alimenter en données.
- La Route est un objet qui indique au template quel est le modèle qu’il doit afficher. C’est elle qui traditionnellement interagit avec le ‘Store’.
- Le Controller permet de stocker des états applicatifs et d’implémenter des comportements propres au template auquel il est associé.
- Le Template décrit l’affichage de l’interface utilisateur. Il se met à jour automatiquement lors de tout changement effectué sur le modèle. C’est un fragment de HTML utilisant le langage de templating handlebars (http://handlebarsjs.com/)
- Le Composant permet de créer des affichages ou des comportements réutilisables et/ou simplifiant le Template,
- Le Store agit comme un mini-ORM et traduit les opérations CRUD en lecture du cache ou en appel au back-office de l’application. Il s’appuie sur des Adapter et des Serializer respectivement pour adapter les appels au back-office (en terme de signature et/ou de protocole) et le format des données transmis /reçus.
Le schéma suivant présente une vue synthétique des objets Javascript manipulés lorsque le navigateur demande la restitution de la page http://localhost:4200/racks pour un serveur ember démarré localement :
Une petite baguette magique est attachée aux objets Route et Controler pour le chemin ‘Racks’, tout simplement parce qu’il ne faut pas oublier qu’Ember va automatiquement créer ces objets s’ils n’existent pas explicitement.
Après cette introduction (un poil longue, je vous l’accorde), nous allons pouvoir passer au choses sérieuses et à la création de notre première version de l’application.
Mais ça, ce sera pour l’article suivant !