Spring - Hibernate - GWT: Bilan du premier mois
Par philippe voncken, jeudi 13 août 2009 à 11:14 :: Logiciels libres :: #127 :: rss
Voici quelques infos sur le projet que je suis actuellement en train de mener. Ce billet fait suite aux présentations que j'avais fait sur l'intégration de Spring, Hibernate et GWT dans le bilan de la première semaine et celui de la seconde semaine. Il est temps de faire le bilan du premier mois, et de donner mon retour sur la mise en place de ce socle technique et des impressions sur les premiers écrans produit avec celui-ci.
Le mois de juillet est passé très vite. La mise en place du socle a bien mis deux semaines, et les deux semaines suivantes ont été utilisées pour faire des réunions avec la MOA et comprendre leur besoin fonctionnel avant de s'attaquer à la mise en place de la gestion des écrans. L'abstraction des mécanismes redondants, la factorisation du code, la refactorisation à la fin de chaque grandes étapes de développement et me voilà déjà à la fin du mois.
La cinquième semaine, c'est la production des trois premiers "écrans" qui permettent de valider le bon fonctionnement générale des premiers mécanismes:
- La création d'une entité avec le passage en mode mise à jour,
- La consultation de ce type d'entité avec la gestion de la pagination
- Et la redirection vers un autre écran sur sélection de l'entité trouvée suite à la recherche en consultation.
Ces premiers écrans sont un succès. Le chargement d'un écran est rapide et une fois chargé, l'application est très rapide en exécution. L'expérience utilisateur en devient donc particulièrement agréable. Mais quels ont été les grands axes suivis du côté de Gwt pour atteindre un tel niveau de satisfaction ?
Explication des mécanismes de haut niveau
Définition: ce que j'appelle "écran" est l'affichage d'une suite d'éléments cohérents qui permettent de gérer une entité persistante ou un type d'entités.
L'architecture de GWT impose une partie serveur et une partie cliente.
- La partie serveur va être essentiellement l'implémentation de contrôleurs Rpc. Ils vont permettre de faire le lien entre la partie cliente et la couche de persistance.
- La partie cliente tant qu'à elle va regrouper tous les mécanismes de construction et de gestion de l'interface.
Parlons un peu des mécanismes côté client.
Mise en page
La page Html affichant l'application GWT définit plusieurs balises Html ayant des identifiants permettant de les manipuler directement dans GWT. Ainsi, en plus des traditionnels headers et footer, j'ai défini une div affichant le menu, une autre étant la partie affichage des messages utilisateurs, une autre permet d'afficher une image dynamique de chargement et une dernière permet d'afficher un "écran".
Les managers
J'ai utilisé un Singleton pour chaque mécanisme global de l'application. Chacun de ces Singletons porte le suffix Manager pour qu'on puisse les distinguer rapidement. Par exemple, pour la gestion du cache, j'ai un CacheManager. Tous mes managers se trouvent dans le même package, comme ça dès que j'ai besoin de retrouver un mécanisme global, je sais où chercher.
La particularité de Gwt est que la partie cliente Java est destinée, après compilation, à être transformée en Javascript. Il faut bien avoir cela en tête car les Singletons ne seront donc pas instanciés en mémoire du serveur (sauf s'ils sont utilisés côté serveur évidemment), mais ils seront instanciés en Javascript dans le navigateur Web.
Alors, de mémoire, voici quelques Managers dont j'ai eu besoin pour gérer mes écrans de manière performante:
Le CacheManager
Le cacheManager me permet de mettre en cache les objets de références. Tous les objets utilisés dans les listBox et autres champs. Pour récupérer mes objets j'ai défini un Dto par écran qui contient tous les objets dont j'ai besoin pour afficher l'écran. Lorsque je souhaite afficher un écran, je test si son Dto est null dans le CacheManager. Si oui, je lance un appel Rpc pour les récupérer. Sinon j'affiche directement l'écran. C'est seulement une fois que j'ai tous mes objets utiles que j'affiche l'écran.
Les Dto ici présentés permettent de regrouper les objets pour n'avoir qu'un appel Rpc. On aurait pu récupérer les objets un a un en faisant un appel spécifique pour chaque type d'objet mais les performances auraient été moins bonnes, au risque de surcharger le serveur.
Le LoaderManager
Le LoaderManager permet de rendre visible ou de cacher l'image de chargement. Lorsqu'on lance un appel Rpc on rend visible l'image qui montre à l'utilisateur que le navigateur est en attente du serveur. Lorsque le serveur à répondu on cache cette image. Ce manager manipule l'élément Html div ayant l'id "loader".
Le PanelManager
Le PanelManager me permet de gérer l'ensemble de mes écrans. Une méthode, utiliser pour le menu et l'historique (bouton précédent/suivant du navigateur), me permet d'instancier un écran en fonction d'un identifiant. Et il existe une méthode pour chaque écran appelé en interne de l'application. Ce manager manipule l'élément Html div ayant l'id "panels".
Le MenuManager
Le MenuManager permet de gérer le menu. Le menu est construit dynamiquement côté serveur en fonction des droits de l'utilisateur. Ainsi on envoie côté client le stricte minium des éléments auquel l'utilisateur à le droit d'accéder. Il s'agit d'un premier niveau de sécurité. Ce manager manipule l'élément Html div ayant l'id "menu".
Le MessagesManager
Le MessagesManager permet d'afficher des messages à l'utilisateur dans une partie spécifique de la page. Les messages ainsi affichés sont supprimés sur chaque action de l'utilisateur. Un système d'exceptions au niveau serveur permet de remonter dans la partie cliente les messages utilisateur liés aux validateurs Hibernate. L'exception qui remonte ces messages contient le nom de l'attribut qui a généré l'erreur, ainsi on peut lier l'erreur à un champ de l'écran et mettre en rouge le label du champ en question. Ce manager manipule l'élément Html div ayant l'id "messages".
Les écrans
Une fois les mécanismes communs factorisés dans des classes abstraites, les écrans se retrouvent articulés autour de trois classes. La première classe gère les commandes, ou les appels Rpc. La seconde classe défini l'ensemble des champs et boutons de l'écran. La dernière classe gère l'ensemble en plaçant les champs et boutons sur des Panels afin de les positionner pour les afficher et les connectent aux commandes.
Rpc ou appel asynchrone
On a vu précédemment, pour la gestion du cache, qu'un écran s'initialise en effectuant un appel Rpc. La spécificité des appels Rpc dans GWT est qu'ils fonctionnent en mode asynchrone. C'est à dire que lorsqu'on lance l'appel, on ne sait pas quand le serveur va répondre dans le temps. Ceci fait que plutôt que d'instancier l'écran et de l'afficher, on va plutôt l'instancier et le laisser s'afficher tout seul. C'est dans la méthode de retour de l'appel Rpc que l'écran va faire appelle au PanelsManager pour lui demander de s'afficher.
La gestion des champs
Pour gérer les erreurs relatives aux champs de saisie en fonction de leur mapping sur un objet persistant, il a fallut abstraire le concept de champs de saisie. J'ai donc construit un GenericInput qui se décline ensuite en tous les types de champs (ListBox, TextBox, DecimalBox...) dont nous avons besoin pour nos écrans. Un GenericInput possède un label et un champs. La classe principale d'un écran étend une classe abstraite qui possède une liste de GenericInput.
Lorsque l'utilisateur clique sur le bouton enregistrer de l'écran on va faire une boucle pour tester tous les GenericInputs au niveau client, pour savoir notamment si les champs obligatoires sont bien renseignés. Si tous les champs son Ok on effectue l'appel, sinon on marque en rouge le label du champ qui pose problème et on affiche un message clair à l'utilisateur.
Une fois l'appel effectué, si une exception a été lancée à cause d'un Hibernate Validator, on va retrouver le GenericInput qui correspond à l'exception en fonction de son identifiant et du nom de l'attribut qui pose problème. On va pouvoir afficher un message clair à l'utilisateur et marquer en rouge les labels des champs qui posent problème.
Conculsion
J'espère que cet aperçue des grands mécanismes mis en place pour la gestion d'une application de gestion via Spring - Hibernate - Gwt et Maven vous aura donné envie d'essayer ces technologies, qui sont pour moi ce qui se fait de mieux en ce moment.
Je rappelle que ce billet n'a pas pour but d'être exaustif sur chacun des sujets abordés. Le but est plutôt de donner des idées, sur les grands axes à suivre, pour ceux qui aimeraient essayer Gwt mais qui ne savent pas par où commencer.
Commentaires
Aucun commentaire pour le moment.
Ajouter un commentaire
Les commentaires pour ce billet sont fermés.