MVC coté client avec RESThub

Logo RESTHubCes 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).
Tweet about this on TwitterShare on FacebookGoogle+Share on LinkedIn

13 réflexions au sujet de « MVC coté client avec RESThub »

  1. Merci pour l’article (Je suis le lead dev de RESThub).

    Pour info, nous travaillons sur la version 1.1 de RESThub qui apportera des améliorations significatives sur la stack Javascript, basée sur les retours d’expérience des projets sur lesquels nous avons utilisé RESThub 1.0.

    L’objectif était d’avoir une stack JS encore plus légère, utilisable sur de “gros” projets.

    Différence significatives entre RESThub JS 1.0 et 1.1 :
    – Migration du système de templates de EJS vers jQuery Template (plus rapide, plus secure, mieux documenté et maintenu)
    – Utilisation de RequireJS pour le chargement des scripts prenant en compte les dépendances transitives entre scripts au lieu de dominoes
    – Suppression de Sammy, dont on utilisait uniquement un sous ensemble et qui n’était pas assez orienté MVC
    – Implémentation d’une gestion des routes à la Sammy from scratch
    – Implémentation d’un bus d’évènement basé sur les customs events jQuery
    – Refonte du plugin Class (on se base sur celui de Javascript MVC)
    – Le Controller ne se base plus sur les widgets de jQuery-UI mais hérite simplement de Class
    – Implémentation de Repository pour centraliser les échanges client-serveur
    – Documentation de référence complète : https://bitbucket.org/ilabs/resthub-js/src/tip/README.rst
    – Tests et exemples fournis

    Nous en avons profité pour séparer complètement la stack Java (https://bitbucket.org/ilabs/resthub/) du micro framework Javascript (https://bitbucket.org/ilabs/resthub-js) car ce dernier peut être utilisé potentiellement avec n’importe quelle solution serveur qui expose des webservices REST.

    On devrait également publier un “vrai” site sur http://resthub.org qui proposera la documentation et les exemples de manière plus claire que l’interface de bitbucket.

    Stay tuned !

  2. désolé, mais “la norme Java EE impose de moins en moins l’utilisation d’un serveur d’application” est très ambigu, voire une contre-vérité : il est important qu’un serveur d’application propose le support complet de Java EE (ou au moins de son profil web) pour que le développeur sache quelles APIs il peut utiliser. Pour ce qui est des EJB, je pense qu’il faut arrêter de raisonner en terme de conteneurs servlet vs. EJB vs. etc… Les EJB 3.1 lite sont intégrés dans le Web Profile, donc un développeur peut décider de miser sur ce profil web ou sur la plate-forme complète.

    “seul un container de servlet est nécessaire pour implémenter des services SOAP ou REST” : il faut quand même l’implémentation de ces API: Metro ou Jersey pour mentionner les implémentations de référence.

    Je ne comprends pas non plus les mentions faites de GlassFish: pour moi il est la preuve que l’on peut avoir un serveur d’applications complet et léger.

    Pour ce qui est de RESThub, je trouve l’intégration de jQuery intéressante, sinon on est proche d’un profil web Java EE 6.

    1. Tout d’abord une précision : par serveur d’application, j’entends un serveur java officiellement certifié pour la plateforme Java (et l’ensemble des normes). Et ici il est plus question de montrer une alternative de développement crédible à une pile java complète (JSF, EJB, CDI, JAAS, …).
      Ces normes ont bien évidemment un sens mais ne doivent pas être la solution universelle.

      Java EE 6 est sorti officiellement en décembre 2009. Plus de 15 mois après très peu de serveurs sont certifiés (GlassFish Enterprise Server v3, TMAX JEUS 7 en font parti).
      Rien du coté des « leaders » JBoss, Weblogic, Websphere qui n’implémentent que certaines parties de la norme et se déclarent « compatibles » Java EE 6.
      De même pour les outils de développements seul Netbeans est utilisable réellement sur un projet Java EE 6.

      Concernant Glassfish je l’ai cité exactement dans ce sens, en ne chargeant que les librairies strictement nécessaires (grâce à OSGI) on obtient effectivement un démarrage très rapide. Par contre il ne peut être à la fois complet et léger en toute circonstance.

      Christophe

      1. @Christophe: JBoss 6 affiche un certification du profile web Java EE 6, WebSphere est en beta, Caucho Resin est imminent (profil web) et WebLogic annonce un support complet de Java EE 6 d’ici fin 2011. C’est une adoption les plus rapides d’une version de J2EE/JavaEE.

        Quant à GlassFish il s’adapte aux besoins d’une application, et dynamiquement qui plus est. Par défaut c’est sur un périmètre Java EE 6 mais les extensions servlet 3.0 et CDI doivent permettre de proposer un équivalent à resthub sur une base web profile GlassFish, non? 😉

        1. Et Java 7 est annoncé en Juillet 2011 (et Java 8 fin 2012) !
          Les serveurs d’applications auront donc toujours un train de retard (au moins pendant les deux prochaines années) et les impatients seront toujours tentés par les nouveautés. Après tout ce n’est pas plus mal et cela laisse de la place pour tout le monde.

          Sinon je suis d’accord qu’avec GlassFish on peut arriver à un équivalent mais ce serait omettre qu’ici la partie la plus intéressante c’est le client.

        2. Je suis en phase avec la vision de Christophe sur ce point, pour moi le mode serveur J2EE classique où tout est fourni, même en se limitant au web profile, montre clairement ses limites actuellement même si Glassfish est vraiment excellent.

          Ca impose beaucoup de contraintes pour peu de bénéfices par rapport au fait de se baser sur un Tomcat/Jetty/Grizzly tout simple + une stack technologique gérée avec Maven.

          Les JSR sont importantes, synchroniser les différentes versions histoire de garantir la cohérence de la plateforme également, mais dépendre d’un bundle monolithique alors même que de nos jours tout le monde gère très bien ses dépendances et ses configurations avec Maven, je ne vois pas l’intérêt pour les développeurs, mis à part pour bénéficier d’un support (payant) global sur l’ensemble de la stack technologique utilisée.

          Pour info, lors de la mise au point de RESThub nous nous sommes posés les questions suivantes pour les choix technologiques :
          – Vanilla JEE6 versus Spring : même si JEE6 a fait de gros progrès, les incohérences de certains choix (http://www.germanescobar.net/2010/04/4-areas-of-possible-confusion-in-jee6.html) nous ont poussé à préférer Spring plus cohérent, qui de plus fonctionne en embeded un peu partout.
          – JAX-RS versus Spring MVC REST support : là pour le coup la faiblesse des arguments des développeurs de Spring MVC quand on leur demande pourquoi ils n’ont pas implémenté l’excellent standard qu’est JAX-RS, combinée à la qualité de Jersey, ont fait penché la balance du côté de ce dernier.

          Les conférences que j’ai vu cette année au Devoxx sur CDI (celle de Adam Bien et de Dan Allen) m’ont conforté dans ce choix. Quand on voit les trésors d’ingéniosité qu’il faut pour mettre en place des mécanismes qu’on via Spring ou Hades nztivement, ça fait froid dans le dos … Je préfère faire du Spring 3 “classique” en utilisant les annotations JEE6 plutôt que d’utiliser CDI + les extensions maisons JBoss inclues avec Weld + des développements spécifiques basés sur CDI.

          En tout cas, on est satisfait de l’équilibre trouvé, entre standards et flexibilité :
          – On peut changer de serveur (Jetty vers Tomcat ou l’inverse) tout en ne prenant pas le risque majeur de changer l’implémentation des standards utilisés.
          – On utilise Spring 3 en maximisant l’utilisation d’annotations JEE6, il ne reste que le @Transactional de Spring qu’on garde
          – Si à l’avenir on souhaite utiliser JPA 2.1 + JAX-RS 1.1, ou JPA 1 + JAX-RS 2.0, on pourra le faire sans attendre 3 ans que le standard global JEE soit tamponné + que notre implémentation de référence implémente toute la stack
          – En terme de testabilité et de gestion des configurations par environnement, ça déchire 😉

          Je suis persuadé qu’entre les serveurs d’applications JEE monolithique, et les solutions full stack qui refont tout de A à Z (Play par exemple), il existe un juste milieu.

          1. Je pense que le choix de Spring 3 est tout à fait respectable et qu’il n’est pas nécessaire de troller sur Java EE 6 pour le justifier.
            Les “incohérences” que tu cites sont dues au fait que Java EE 6 dispose de plusieurs technologies toutes optionnelles et qu’en l’absence de CDI par exemple, les autres doivent pouvoir fonctionner (JSF avoir des managed bean et EJB des singletons). Le blog d’origine que tu mets en lien ne parle pas d’incohérences mais de confusions possible. En clair quand on a compris pourquoi ces recouvrements existent, c’est cohérent et ça ne gêne pas le développement.

            CDI fonctionne parfaitement en mode embedded ou sur du Tomcat et du Jetty.

            Je te rassure sur les “trésors d’ingéniosité”, il s’agit juste d’une façon différente de voir les choses. Je viens de porter un petit dev Srping en CDI et ai réduit le nombre de lignes totales (y compris le xml) d’environ 30 %.

            Pour info, il n’y a pas d’extensions incluses avec Weld qui reste l’implémentation de référence de CDI. Les “extensions maisons de JBoss” que tu évoques s’appellent Seam 3 et leur cahier des charges stipule qu’elles doivent fonctionner sur toutes les implémentations CDI et donc tous les serveurs Java EE 6 . Donc pas si “maison” que ça.

            Après il est clair que l’éco système CDI ne propose pas encore la richesse de celui de Spring et que le choix de ce dernier est pour l’instant encore nettement plus raisonnable et plus sûr.
            Tout ça pour dire que quand on se sent plus à l’aise ou en confiance avec une techno, il n’est pas honteux de le dire sans se sentir obliger de dénigrer les technos non choisies avec des arguments discutables.

          2. Mon but n’est pas de justifier, mais d’expliquer un peu plus dans le détail les raisons de ce choix, même si quelques Trolls se sont glissés dans mon commentaire 😉

            Je connais les raisons des incohérences liées de JEE6, simplement je les regrette. A trop vouloir jouer sur tous les tableaux (CDI, EJB, DI), on a quelque chose sur lequel on arrive généralement à trouver ce dont on a besoin, mais ça pose de vrais problèmes à l’échelle d’un boite ou d’un gros projet en terme de cohérence technique.

            Le projet dont je parle est Solder, qui est un sous projet de Seam 3, très utile quand on commence à développer des fonctionnalités avancées sur base de CDI.

            On avait évoqué avec un collègue très calé en JEE6, puisque contributeur OpenEJB, la possibilité de se baser uniquement sur du vanilla JEE6 pour le coeur Java de RESThub. J’ai donc abordé les confs du Devoxx en me demandant si dans notre cas c’était une alternative valable. En, effet, certaines fonctionnalités de CDI comme les interseptors sont vraiment sympas.

            La partie “Component configuration with EJB 3.1, interceptors and CDI” de la conf d’Adam Bien et surtout la conférence “The roots of Java EE 6: JSR-299 (CDI) and Weld extensions” de Dan Allen m’ont plutôt convaincu du contraire …

          3. Sebastien,

            Sans troller (Spring vs Java EE est aussi un choix qui depend du contexte et qui de fait ne se discute pas), peux-tu etre plus explicite sur “ce qui fait froid dans le dos” ?

            Si on veux aller par la, deployer 10 applications sur 1 app server qui remontent chacune une stack Spring + dependances depuis Maven ca peut aussi faire froid dans le dos 🙂

            A+

          4. En gros ce qui était présenté par Dan Allen dans la conférence “The roots of Java EE 6: JSR-299 (CDI) and Weld extensions”. En utilisant CDI + Solder + des devs spécifiques, il ajoutait des comportements (puissants) pour arriver à certaines fonctionnalités qu’on utilise habituellement sur Spring.

            Mais le soucis c’est qu’il y avait tellement de tweaks qu’on se retrouvait, de mon perçu, avec une solution “moins standard” sur base de ces devs qu’avec du Spring, alors qu’on se fait habituellement chambrer pour cet aspect.

            CDI est très puissant, mais j’ai l’impression que sur certains aspects, il est surtout un outil destiné aux développeurs de frameworks.

            Dans notre cas, vu le gap sur les fonctionnalités qui nous intéresse, la conclusion était que ça n’était pas pour nous. On a pas envie de recoder un Spring, mais plutôt de combler certains manques sur les briques qu’on intègre (Scan d’entités dans différents module pour une même Persistence Unit ou de classes sérialisées par JAX-RS pour compenser les effets du type erasure par exemple).

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


*