Présentation de Grails

Introduction

Nous présentons ici le framework Grails: un framework web haute productivité, permettant de développer des applications web à déployer dans un conteneur d’applications JAVA.

Grails est un framework web visant la haute productivité, se basant sur le langage Groovy, offrant une architecture MVC et incluant un ORM. L’acronyme Grails, dont le premier nom était Groovy on Rails, reflète bien cet objectif. De plus, Grails met en place la philosophie « Convention over Configuration »: des valeurs par défaut raisonnables pour les différentes options.

Grails permet de développer un site web dynamique de manière rapide. On peut s’en servir pour faire des prototypes, comme des applications complètes. C’est un framework complet, permettant de faire de vraies applications d’Entreprise. On peut le voir comme du Spring à la sauce Rails: 100% de la puissance Spring et la productivité de Rails. Grails s’intègre de manière transparente à l’univers Java, et permet de réutiliser toutes ses briques: librairies, serveurs d’applications, etc. Grails, dont la première version date de 2003, est devenu un framework fiable et mature. Finalement, la base groovy, un langage non type pour la JVM, permet de se concentrer uniquement sur le code métier, et permet donc de générer moins de bugs, tout en augmentant la lisibilité et diminuant le temps de développement.

Pré-requis

Le framework Grails repose sur les fondamentaux suivants:

  • Java : On suppose que le lecteur est familier avec le langage Java. Les notions de classe, de création d’objet, d’appel de méthode, etc. sont nécessaires.
  • JSP : La connaissance de la spécification JavaEE JSP est optionnelle. Le langage de templates de pages web sera repris avec un nouveau nom: GSP.
  • Modèle MVC : le découpage d’une application en Modèle – Vue – Contrôleur est un des piliers des applications grails.
  • Groovy : La connaissance du langage Groovy est optionnelle. Indifféremment, le code grails peut être écrit en Groovy ou en Java.
  • SPRING : La connaissance du framework SPRING est optionnelle. Spring est utilisé comme la base de Grails, mais sa configuration en est grandement facilité.

Développer en grails

Entrons dans le vif du sujet, les bases du développement en Grails: l’installation, un mini-projet, MVC, les services, puis GORM.

Installation

Pour installer grails, il suffit de décompresser l’archive du framework, de créer la variable d’environnement GRAILS_HOME, puis d’ajouter au Path $GRAILS_HOME/bin. Une console d’exécution, ‘grails’, permet de simplifier la gestion d’un projet: création du projet, de classes, exécution de tests et du site web, génération d’un WAR. Les commandes disponibles sont listées dans la documentation en ligne, dans la colonne de droite, « Quick Reference / Command Line ».

Démarrer un projet

Pour créer un projet:

Le paradigme MVC impléménté par Grails est visible dans la hiérarchie du projet:

  • grails-app/controller
  • grails-app/domain
  • grails-app/views
  • grails-app/services

Pour explorer les fonctionnalités de Grails, nous allons créer un mini système de réservation de voyages, avec une persistance en base:

Rajoutons des champs à notre objet persisté en base (dans le fichier grails-app/domain/Trajet.Groovy)

On déclare implicitement toutes les méthodes du contrôleur (dans le fichier grails-app/controllers/TrajetController.Groovy), ainsi que les vues associées:

On peut déjà s’émerveiller:

Un site web est alors disponible sur le port 8080 (on peut changer le port pour la commande précédente via l’option –Dserver.port=9090). La webapp exposée offre déjà accès aux fonctions d’un éditeur de trajets (CRUD – Create/Read/Update/Delete, additionné de la fonctionnalité Liste). Le scaffolding, qui permet de générer automatiquement les opérations sur le domain, offre une très grande rapidité de développement.

De nombreuses améliorations sont possibles!

Personnaliser le contrôleur

Le contrôleur répond à des appels HTTP, en recevant plusieurs paramètres, et décide de la réponse à donner.

Ceci définit un verbe spécifique, ‘tutu’, qui permet de voir du texte simple (utile pour de l’AJAX ou pour déboguer) à l’adresse

Si l’on souhaite recevoir des paramètres, on peut les spécifier comme arguments:

Dans les méthodes du contrôleur, les paramètres sont accessibles dans le dictionnaire _params_, donc ici params.x==5 et params.y==3.

On a aussi exposé les opérations CRUD via l’instruction scaffold (sans cette instruction, ces opérations retournent un code HTTP 404).  Les actions du scaffold sont

On pourra surcharger ces méthodes (comme on a défini ‘tutu’), ou s’inspirer du code générique:

Personnaliser la vue

Dans grails, la construction de la vue HTML est déléguée à un patron au format GSP (Groovy Servlet Pages).  La syntaxe HTML est reprise, et augmentée de balises spécifiques, reposant sur le même  principe que les JSP (Java Servlet Pages).

Nous allons créer une vue spécifique pour l’appel ‘toto’ dans le contrôleur :

Il faut alors déclarer une page GSP (dans le fichier grails-app/views/toto.gsp):

On voit ici que les objets passés dans le dictionnaire en dernière instruction du contrôleur sont accessibles via le raccourci ${}. En fait, ce raccourci correspond à l’interprétation de code Groovy dans la page HTML. Cela est illustré par le calcul du coût du voyage (à 14 centimes le kilomètre). On devrait éviter de mettre des aspects ‘business’ (calcul du coût) dans la vue; cet exemple a pour but d’illustrer l’inclusion de code Groovy dans les GSP.

De très nombreuses balises sont disponibles, telles , , et simplifient grandement
la génération de pages HTML. On regardera la section « Quick Reference / Tags » dans la colonne de droite de la documentation en ligne.

L’instruction du header concernant le layout (4ème ligne) va chercher le fichier layout/main.gsp, et l’utilise  pour construire la page (sitemesh est un système de composition de patrons de page,  reposant sur le patron décorateur, une introduction se trouve ici).

Si comme pour le contrôleur, on souhaite réutiliser le code générique utilisé par grails via
l’instruction ‘scaffold’, la commande suivante générera les fichiers GSP correspondant au CRUD:

Lorsque les fichiers GSP deviennent trop volumineux, on peut utiliser un système de patrons pour découper les pages. On définira un patron (template) dans un fichier séparé,
que l’on pourra alors invoquer, avec des paramètres, en une seule ligne. Par exemple, si on
considère que l’affichage du coût est trop verbeux, on peut faire la séparation suivante:

Dans toto.gsp:

Dans _cout.gsp (remarquer le caractère souligné, qui indique que c’est un patron):

Services

Le rôle du contrôleur doit se réduire à la lecture des paramètres d’entrée, puis à la délégation à la vue.  On s’efforce d’isoler la logique métier dans des classes dédiées, les Services. On y rassemblera les appels aux bases de données, la couche décisionnelle (conditionnelle), etc.

Lors de l’exécution de la webapp, le service sera instancié automatiquement par le framework, sous forme de singleton.  Ses méthodes sont par défaut transactionnelles: si une exception est générée dans une méthode, tous les appels à la base de données de la méthode avant l’exception subiront un rollback.

Un service en grails est simplement une classe dans le répertoire grails-app/services. On peut générer un service via l’instruction

Cela va créer un service grails-app/services/TrajetService, que l’on peut compléter ainsi avec la méthode parisBrest:

Pour utiliser un service, il suffit de le déclarer pour qu’il soit injecté:

GORM

GORM signifie Grails Object Relational Mapping. C’est la couche qui se charge d’abstraire la base de données, en offrant une API orientée objet. Le DTO, appelé « classe domaine », classe qui représente une donnée (par exemple une ligne d’une table de base), est décrit en tant qu’objet dans la partie modèle du projet (on l’a déjà fait dans la classe grails-app/model/Trajet.Groovy). Le DAO, en charge de réaliser les appels à la source de données (par exemple via jdbc), est ajouté à la classe par le biais de méthodes statiques.

Configurer l’accès aux données

La base de données, créée initialement, est une base HSQLDB, c’est-à-dire une base en mémoire. Permettant d’accélérer les développements, ce type de base ne doit cependant jamais être utilisé production. Pour configurer la base, ouvrir le fichier de conf grails-app/conf/DataSource.Groovy:

Au démarrage de l’application via ‘grails run-app’, la base HSQLDB est démarrée, et les tables sont vidées. On pourra choisir de mettre en place une source de données plus pérenne, par exemple une base de données MySQL.

Validation

Jusqu’à maintenant, aucune validation n’était appliquée aux données persistées. Cependant nous souhaitons n’autoriser en base qu’un sous-ensemble de valeurs possibles, sous-ensemble plausible. Prenons la nouvelle définition suivante de notre classe de domaine (dans le fichier grails-app/domain/Trajet.Groovy)

La section constraints permet de déclarer les valeurs admissibles pour la base de donnée (attention, la création d’objets du Domaine non plausibles reste possible via _new_, tant qu’on ne les sauvegarde pas en base). Dans le code précédent, ici on restreint le champ origine à une chaîne non nulle et de longueur strictement positive, de taille maximum 50 bytes. On peut aussi imaginer des contraintes libres, qui utilisent une fonction anonyme pour vérifier la plausibilité, comme ci-dessus où la date du voyage est obligatoirement dans le futur. La liste des contraintes imposables est définie dans la documentation en ligne, sous le menu de droite « Quick Reference/Command Line/Constraints », et dans la figure 4.1 de la page 27 de Getting Started with Grails.

One-to-One / One-to-Many

Il est possible de modéliser des relations spécifiques entre différentes données. Par exemple, on pourrait vouloir associer un voyageur à un trajet. Pour cela, il suffit de définir une classe Voyageur, et de rajouter la relation dans la classe Trajet:

Pour une relation multiple, « one-to-many », par exemple pour associer un ou plusieurs voyageurs à un trajet, la syntaxe est moins intuitive:

Un nouveau champ sera créé dans la class Trajet, de nom ‘voyageurs’. Ce champ nous permettra de récupérer la liste des voyageurs. On peut aussi créer la relation inverse dans la classe Voyageur:

Le cas des relations N-M (chaque voyageur peut avoir plusieurs trajets, chaque trajet peut avoir plusieurs voyageurs) sera gérée de manière transparente au travers d’une table pivot, qui permet de transformer les relations N-M en des relations 1-N et 1-M, en incluant un _hasMany_ dans les deux tables.

Méthodes ajoutées aux classes du modèle

Les classes domaine sont décorées d’un ensemble de méthodes permettant de gérer les interactions avec la base (agissant comme DAO).

Cette dernière ligne présage des nombreuses autres possibilités ajoutées par GORM (par exemple des ‘named queries’), qu’on consultera dans la documentation en ligne .

Bootstrapping

Pour démarrer nos applications avec des données initiales, par exemple pour avoir de données en développement, on utilise le fichier grails-app/conf/BootStrap.Groovy

Cette fonctionnalité est vraiment très utile! Elle permet au développeur de travailler en local sur une base en mémoire, en ayant dès le démarrage des données disponibles.

Améliorations pour la vraie vie

Après avoir vu les bases, nous allons maintenant ajouter des concepts de niveau intermédiaire.

Tests

Grails intègre dans son architecture de base un framework de test, sur trois niveaux: tests unitaires, d’intégration, et fonctionnels. Les tests unitaires ont vocation de tester des classes en isolation, tandis que les tests d’intégration vérifie le branchement avec un système extérieur (par défaut, la base de donnée). Les tests fonctionnels garantissent le parcours utilisateur. Un système de mock est mis en place pour mocker les éléments qui ne font pas partie du test en cours (selon le test, ce sera la classe domain et ses méthodes automatiques, les services). Voici un exemple de test unitaire sur le TrajetController présenté ci-dessus (dans ce cas-ci, le test n’est pas très utile, mais il sert d’exemple)

De très nombreux raccourcis sont possibles, ce qui incite grandement le développeur à écrire ses tests.

REST/SOAP

On peut rediriger des verbes HTTP vers une action particulière (dans le contrôleur) :

Au lieu d’une réponse HTML, si l’on souhaite du XML ou du JSON (ce qui correspond à l’exposition d’un webservice, donc consommé par une machine, au contraire de l’HTML à vocation d’être consommé par le navigateur d’un utilisateur):

Le module Groovy HTTPBuilder (qui se base sur la librairie Apache HttpClient) est une encapsulation intuitive pour clients du protocole HTTP. Voici un exemple de script Groovy standalone, qui émet une requête sur notre service de trajets:

On définit le comportement en cas d’échec ou d’erreur. Une division plus fine peut aussi être réalisée sur le code retour de l’appel http (par exemple sur response.404)

Proxy

Il est possible d’ajouter un proxy, habituellement pour avoir accès à internet:

On peut aussi ajouter un proxy pour des appels spécifiques:

Réecriture d’url

Par défaut, une méthode toto d’un contrôleur TrajetController du projet projet1 serait accessible via l’url

Les redirections d’URL, qui permettent d’exposer le service et ses paramètres dans une URL, sont configurées dans le fichier grails-app/conf/UrlMappings.Groovy

Plugins

Grails propose d’étendre le concept java de librairies (jar) en proposant ses plugins: un plugin est un projet grails dont on peut ré-utiliser les différents éléments (GSP, contrôleurs, taglib, etc.). Les plugins facilitent la modularisation, en permettant facilement l’inclusion fonctionnalités.

De très nombreux plugins sont disponibles, on peut en trouver la liste sur le site de grails. L’installation se fait facilement; par exemple, pour installer spring-security-core:

En particulier, le plugin resources et ses descendants d’offrent un cadre pour appliquer les bonnes pratiques d’optimisation de pages web: compression, cache, cdn, minification, etc.

Externalisation de la configuration

Pour séparer l’application de sa configuration, on utilise le fichier grails-app/conf/Config.Groovy:

On remarquera que ce fichier est en groovy. On peut donc configurer l’application en fonction de paramètres externes de manière très dynamique.
On regardera le post de blog sur le sujet  ou la page de documentation pour plus de détails.

Maven

Dans cet exposé, on a présenté la commande ‘grails’ qui permet de créer des classes, lancer l’application dans un serveur, lancer les tests, et même de packager l’application.

S’il l’on souhaite s’intégrer dans un processus de build à base de maven (par exemple pour facilement intégrer le projet dans une plateforme d’intégration continue, comme jenkins), il est très simple d’y reporter la gestion du build. L’intégration de maven via un plugin (voir la documentation sur le sujet pour plus de détails), inclus par défaut, permet de l’utiliser pour les projets grails:

Parmi les goals de maven disponibles, citons grails:create-controller, grails:exec (exécuter une commande grails arbitraire), grails:generate-all (générer le code de scaffold), grails:list-plugins (les dépendances), grails:run-app (lancer la webapp dans un conteneur) et finalement grails:help

Conclusion

Dans cet article, nous avons survolé les possibilités du framework web grails. Nous avons vu les principes de base avec les contrôleurs, les services, les vues et GORM, puis nous avons détaillé des aspects plus avancé comme le bootstrapping, REST/SOAP, la configuration externalisée et programmatique, maven.

Ce framework vraiment très élégant permet de développer efficacement, en imposant un découpage de l’application. Basé sur Spring, il permet de faire de vraies applications Entreprise, et s’intègre sans effort à l’univers Java (librairies, serveurs d’applications, etc.)

Pour une étude plus approfondie de Grails, consultez les références, en particulier Getting Started with Grails et la documentation en ligne. Certains aspects n’ont pas été abordés, comme les layout de SiteMesh, le langage Groovy, le système de log, les taglibs, l’internationalisation, le système de test.

Remerciements

Merci à Alexandre di Costanzo pour la relecture approfondie.

Merci à Anthony Choux pour la relecture du brouillon presque final.

Finalement merci à Julien Fallet pour les encouragements.

Références

Le tutoriel Getting Started with Grails est particulièrement bien fait, et couvre la majeure partie de Grails. Il est recommandé de le lire en entier. La documentation en ligne offre une navigation très efficace, grâce à son menu à droite (Quick Reference).

Laisser un commentaire

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

douze − trois =