MVC coté client avec RESThub

Ces derniers temps, le modèle stateful prôné depuis 10 ans par Java EE rencontre de nombreuses critiques et l’arrivée des architectures REST nous amène à repenser l’organisation et la conception de nos développements. En mariant ces deux tendances de fond, RESTHub propose une alternative structurée et moderne aux modèles encore dominant aujourd’hui.

Introduction : Les serveurs d’application légers

On assiste à une recrudescence de l’intérêt pour les serveur dits léger avec, par exemple, Tomcat et Jetty que l’on retrouve de plus en plus en production.

Typiquement ces applications n’utilisent pas les normes telles que EJB, JMS, JTA qui requièrent un “véritable” serveur d’application comme Weblogic, JBoss ou Glassfish.

Cette envie de légèreté a été encore renforcée avec l’arrivée de deux tendances :

  1. Les services Cloud : La norme de fait est un accès de type services Web entre le client et le serveur.
  2. OSGI (Toutes les applications n’ont pas besoin de l’ensemble des fonctionnalités Java EE,  on ne charge que ce qui est nécessaire (Glassfish)).

Pour rappel, la norme Java EE impose de moins en moins l’utilisation d’un serveur d’application.

Par exemple un container EJB n’est plus indispensable depuis java EE 6 (en tout cas pour les EJB lite).

De même depuis Java EE 6, seul un container de servlet est nécessaire pour implémenter des services SOAP ou REST (JAX-RS, JAX-WS).

Peu de gens le savent mais un serveur HTTP très léger est intégré à Java SE 6, un peu de JAX-WS et vous avez un serveur de services web prêt à l’emploi. Évidemment l’usage est réservé aux tests unitaires, aux environnements de développement et non à la production (attention aux bugs et à la capacité a tenir la charge).

Certains frameworks de services Web comme Axis 2 intègrent un serveur léger qui peut convenir même en production dans certain cas.

Caractéristiques des applications Web utilisant des serveurs légers

Il s’agit de celles dont les caractéristiques sont les suivantes :

  • Client : navigateur
  • Serveurs Web sans états
  • Le serveur est en charge des données (base de données) et des services
  • Présentation coté client
  • Stockage des informations de session coté client

Postulat : le stateleful n’est pas naturel

Le fonctionnement actuel des serveurs d’application Java EE en mode stateful et surtout des applications web est une aberration, en effet HTTP est lui même stateless.

Au delà du besoin métier qui peut exiger l’utilisation de sessions (cas des sites marchands par exemple) certains frameworks sont obligatoirement stateful (JSF, Wicket).

Les services stateful entraînent bien souvent des problèmes de performance coté serveur car il faut maintenir la session tant que les opérations ne sont pas terminées.

De plus dans le cas d’un environnement répliqué, chaque serveur doit avoir connaissance de la session et il faut sans cesse synchroniser ces données.

D’où l’idée de promouvoir les applications sans état, avec éventuellement stockage des informations nécessaires coté client.

La fonctionnalité offerte par html5 Persistant Storage est une avancée importante pour ce genre de frameworks car avant il fallait utiliser des cookies, des champ cachés ou plus récemment google gears (lui même basé sur les cookies et abandonné depuis).

Le support des fonctionnalités Local Storage et Session Storage est d’ores et déjà très bon (Cf. litmus) et seules les versions anciennes des navigateurs poserons problème.

Présentation de RESThub

Prévu pour fonctionner avec HTML 5,RESThub se base sur les principes suivants :

  • Architecture REST
  • DRY (don’t repeat yourself)
  • KISS (keep it simple and stupid)

Deux architectures MVC sont possibles :

  1. Une solution classique coté serveur (implémentation MVC avec Tapestry 5.2)
  2. Une solution plus originale coté client (jQuery, Sammy, JavaScript) pour concevoir une solution RIA (Javascript/HTML5) – Rest.

La plus intéressante est évidemment la solution 2 qui propose une nouvelle vision de l’architecture Web tout en étant compatible avec les technologies actuelles.

Pour ceux qui maîtrise déjà ces technologies la courbe d’apprentissage est très courte.

RESThub est “simplement” un liant de briques existantes  :

  • JPA basé sur Hibernate 3.5.1/JPA 2
  • Architecture REST implémentée avec Jersey (JAX RS 1.1)
  • Spring 3
  • jQuery
  • Maven 3 pour le build

Philosophie de développement

  • Framework full stack,
  • Session côté client (Une session utilisateur stockée côté client via HTML5 Session Storage),
  • Simplicité de développement,
  • Architecture REST,
  • Capitaliser sur des frameworks comme jQuery ou jQuery UI pour développer son IHM.

Outils de développement nécessaires

  • Java 6
  • Mercurial (pas indispensable, permet de récupérer les sources)
  • Maven 3
  • NetBeans (il n’y a pas de plugin RESTHub mais un meilleur support Java 6)

Les autres librairies sont apportées par MAVEN

3 archétypes sont proposés :

  • resthub-js-webapp-archetype (HTML5 + REST)
  • resthub-tapestry5-webapp-archetype (application web Tapestry)
  • resthub-middle-archetype (création d’un module)

Sécurité

Elle est basée sur OAuth 2.0 et le profil Web (on parle de Spring security)

Liste des librairies Java utilisées

  • Maven 3
  • Spring 3
  • Hibernate
  • Hades
  • H2 base de données embarquée

Liste des frameworks Javascript

  • jQuery
  • jQuery UI
  • Sammy JS
  • Dominoes
  • Maven YUI compressor

Dominoes permet de piloter le chargement de scripts Javascript et CSS et ainsi éviter de tout charger au premier démarrage de la page par exemple.

Maven YUI compressor permet de compacter les fichiers JavaScript afin de réduire le temps de transfert.

Sammy est un framework construit comme une extension de JQuery

RESThub  utilise la technologie SPI (single page interface) popularisé par les applications Ajax (une seule page dont les données sont rafraîchies/modifiées au fur et a mesure de la navigation.

L’un des défauts de ce genre d’application est qu’il est difficile de reconstituer le parcours précis des utilisateurs (en tout cas c’est plus difficile qu’avec le postulat une page = une fonctionnalité).

Sammy permet de gérer la navigation au sein de ce genre d’application (en définissant des routes) et ainsi permettre de gérer l’historique de navigation d’un utilisateur.

**Hades**est une librairie qui facilite l’écriture de DAO en s’appuyant sur Spring et JPA. En intégrant l’utilisation de génériques, on écrit moins de code.

D’ailleurs RESThub utilise massivement les génériques :

  • DAO génériques.
  • CRUD services.
  • Controleurs REST.
  • Classes de test.

Base embarquée H2

  • Écrit en Java
  • Modes embarqués et serveur
  • Base de données mémoire
  • Console Web d’administration
  • Seulement 1 Mo pour le jar

Impact de l’utilisation du framework coté serveur

Modèle

  1. Identifiant technique (il suffit d’hériter de la classe Resource).
  2. Clé fonctionnelle pour la recherche (cela parait logique).
  3. Stratégie pour l’héritage (pas de table pour la classe mère une table pour chaque classe fille ).

Gestion des entités et prise en compte

  1. Par configuration dans fichier de configuration Spring (par exemple <resthub:include-entities base-package=”net.myProject.**.model” />)
  2. Prise en compte automatique des entités par scan des entitées JPA2 réparties dans différents modules
  3. Annotations java 6 supportées
  4. un fichier Spring par module

La session est gérée grâce à la fonctionnalité HTML5 session storage.

RESThub console

La console RESThub est un widget jQuery qui permet de débugger la partie serveur d’une application RESThub.

  • Database console (basée sur la console H2)
  • WADL explorer : permet d’explorer le contrat WADL et de tester les services REST.
  • Affiche les détails d’un bean en utilisant Spring API

Conclusion

RESThub  apporte une approche nouvelle qui a le mérite d’être très peu impactante en réalité pour ceux qui ont l’habitude des frameworks utilisés.

Il apporte une simplification de l’architecture coté serveur bienvenue lors de forte sollicitations.

Il repositionne les rôles de chacun, le serveur offre des services, charge au client de gérer la présentation et le contexte (SOA semble renaître après sa mort annoncée).

Améliorations

RESThub est pour l’instant en version 1.0, beaucoup d’améliorations sont prévues :

  • Plus de documentations, de tutoriels (toutefois il faut se référer aux briques utilisées)
  • Support de la sécurité basé sur Spring Security
  • Support de beans validation
  • Finalisation de la stack Javascript
  • Support Web socket
  • Support CouchDB
  • Support de tous les profils OAuth

D’autres frameworks concurrents existent :  JavascriptMVC, Backbone.js

Principes RESThub

  1. TDD (Test Driven Development)
  2. Développement en couches : Modèle , DAO , Service (transactions, sécurité), Contrôleur (Rest , Web services)
  3. Développement des couches de persistance et de service selon le principe Interface/Implémentation.
  4. Utilisation du pattern IOC.
  5. Utiliser les projets multi-module Maven.
  6. Pragmatic SOA : créer des modules fonctionnels avec couplage lâche tout en utilisant les mécanismes tels que l’héritage, le polymorphisme, les génériques et le chargement tardif
  7. Définir une classe mère pour toutes les entités contenant les spécificités de la persistance (classe Resource).
  8. Utiliser la classe Spring *PropertyPlaceholderConfigurer *pour définir les propriétés du projet plutôt que Maven. Cela permet d’injecter les valeur au moment de l’exécution plutôt qu’au build et de les définir dans le WAR.
  9. Préferrer lorsque cela est possible l’utilisation de JAR à la place de modules WAR.
  10. Réserver l’utilisation de WAR pour le déploiement et la configuration.
  11. DRY (Don’t Repeat Yourself) : utilisation des génériques.
  12. KISS (Keep It Simple and Stupid) : éviter complexité inutile.
  13. Implémenter la sécurité dans les couches de services.
  14. Utiliser une classe mère abstraite (AbstractTest) qui se chargera de la configuration du contexte.
  15. Ne pas polluer les services métier avec des contraintes techniques telles que la sérialisation et l’implémentation (SOAP\REST), confier ce rôle au contrôleur.
  16. Utiliser les services RESTful et considérer la sérialisation comme un simple paramètre (XML, JSON …).
  17. Préférer les mécanismes de plugin à une configuration centralisée (un jar par module et un fichier Spring par jar).