Introduction au langage de script Groovy

Cet article est une introduction à Groovy, un langage de script pour Java inspiré entre autres de Python, Java, Ruby et Smalltalk

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Lancé en 2003 par James Strachan et Bob McWhirter, le projet Open Source Groovy est un langage de script dont les caractéristiques principales sont :

  • un langage orienté objet pour la JVM Java  qui s'inspire entre autres de Python, Java, Ruby et Smalltalk ;
  • un langage dynamique et agile (ex. : typage dynamique, codage facilité par le point-virgule facultatif en fin de ligne) ;
  • une syntaxe proche de Java ;
  • le bytecode qui est généré directement ;
  • la réutilisation des librairies Java.

Groovy est aujourd'hui géré au sein du JCP dans la JSR 241, ce projet étant dirigé par le français Guillaume Laforge.

Alors Groovy, me direz-vous, pour quelles utilisations ? Eh bien elles sont nombreuses :

  • le prototypage (ou développement rapide) ;
  • les fonctionnalités « clefs en main » de Groovy pour manipuler du XML, des collections, etc. ;
  • les tests ;
  • les applications financières ;
  • etc.

Voilà, maintenant le décor est planté, c'est parti pour un voyage découverte de Groovy…

II. Installation

La page de téléchargement http://groovy.codehaus.org/Download propose divers liens pour obtenir Groovy.

Les exemples de cet article utilisent la dernière version groovy-x.x-jsr-xx.zip de Groovy disponible à l'adresse suivante http://dist.codehaus.org/groovy/distributions.

Il faut extraire l'archive groovy-x.x-jsr-xx.zip dans le répertoire de votre choix et créer une variable d'environnement GROOVY_HOME avec pour valeur ce répertoire (ex:GROOVY_HOME=c:/groovy-x.x-jsr-xx).

Ajouter ensuite %GROOVY_HOME%/bin au PATH.

Et enfin, ouvrir une console de commande et exécuter la commande groovyConsole.bat, la console de Groovy doit apparaître comme ceci :

Image non disponible

III. Premiers pas, premiers scripts

Une fois la console ouverte, dans la partie haute, taper l'instruction suivante puis la combinaison CTRL + R pour l’exécuter :

Le script tradition
Sélectionnez
println "Bonjour le monde !"

Vous observez alors la sortie suivante dans la partie basse de la console :

 
Sélectionnez
groovy> println "Bonjour le monde !"

Bonjour le monde !

Voilà pour notre premier script, vous pouvez également demander l'évaluation d'un calcul, dans la partie haute, taper :

Un calcul
Sélectionnez
12*12+6

Et vous obtiendrez (après avoir utilisé la combinaison CTRL + R, mais ça, je ne le dirai plus) :

 
Sélectionnez
groovy> 12*12+6

Result: 150

III-A. Les variables

Exécutons maintenant ce script :

Concaténation de chaînes
Sélectionnez
age = 77
phrase = "Le capitaine a " + age + " ans"
println phrase

Le résultat est le suivant :

 
Sélectionnez
groovy> age = 77
groovy> phrase = "Le capitaine a " + age + " ans"
groovy> println phrase

Le capitaine a 77 ans

Nous avons donc créé une variable age, puis une variable phrase et affiché une concaténation de ces deux variables.

Vous remarquerez qu'aucun type n'a été fixé pour ces variables, c'est une des fonctionnalités de Groovy : le typage dynamique.

On type en général les variables par def si on désire un typage dynamique (vérification à l'exécution comme en smalltalk), si on omet le mot clef def il est utilisé par défaut :

Typage dynamique
Sélectionnez
def film = "Mon nom est personne"
def nbvision = 7
println "J'ai vu $nbvision fois le film $film"

Donnera en sortie de console :

 
Sélectionnez
groovy> def film = "Mon nom est personne"
groovy> def nbvision = 7
groovy> println "J'ai vu $nbvision fois le film $film"

J'ai vu 7 fois le film Mon nom est personne

Mais on peut également typer les variables (comme en Java) si on désire un typage fort :

Typage fort
Sélectionnez
String film = "Mon nom est personne"
int nbvision = 7
println "J'ai vu $nbvision fois le film $film"

Donnera en sortie de console :

 
Sélectionnez
groovy> String film = "Mon nom est personne"
groovy> int nbvision = 7
groovy> println "J'ai vu $nbvision fois le film $film"

J'ai vu 7 fois le film Mon nom est personne

III-B. Les listes et les maps

Dans Groovy, les listes sont le pendant des interfaces java.util.List en Java.

Une liste se déclare comme ceci :

La banane par les deux bouts
Sélectionnez
liste = ['banane','poire','pomme','banane']

On peut par exemple utiliser la taille de la liste, accéder à un élément particulier, ce qui donne en sortie de console :

 
Sélectionnez
groovy> liste = ['banane','poire','pomme','banane']
groovy> println liste.size()
groovy> println liste[2]

4
pomme

Les maps sont des listes d'éléments associés à une clef. On peut alors accéder à un élément particulier, non pas par son index, mais par sa clef associée.

Une map se déclare comme ceci :

Utile lors des longs voyages
Sélectionnez
departement = [ "Ain":01, "Vosges":"88", "Rhône Alpes":69 ]

Et comme pour les listes, des méthodes pour travailler avec les maps :

Deux façons d'accéder aux valeurs d'une map
Sélectionnez
groovy> departement = [ "Ain":01, "Vosges":"88", "Rhône Alpes":69 ]
groovy> println departement.Vosges
groovy> println departement["Rhône Alpes"]

88
69

Vous remarquerez encore une fois que le type des valeurs de la map est hétérogène, et Groovy se débrouille très bien avec.

Pour modifier une valeur de la map :

Modifier une valeur de la map
Sélectionnez
groovy> departement = [ "Ain":01, "Vosges":"88", "Rhône Alpes":69 ]
groovy> departement["Vosges"] = 666
groovy> println departement["Vosges"]

666

Pour parcourir une liste, c'est extrêmement simpliste, en reprenant l'exemple de nos fruits :

Affichage de tous les éléments d'une liste
Sélectionnez
liste = ['banane','poire','pomme','banane']
liste.each {
  println it
}

nous obtiendrons en sortie de console :

 
Sélectionnez
groovy> liste = ['banane','poire','pomme','banane']
groovy> liste.each {
groovy>   println it
groovy> }

banane
poire
pomme
banane

Enfin pour créer des listes vides et ensuite y ajouter des éléments :

Liste et map vide, ajouter un élément
Sélectionnez
mamap = [:]
maliste = []
mamap.put("TOTO",44)
maliste.add("TITI")
println mamap["TOTO"]
println maliste[0]

Une autre variante pour peupler les listes et les maps :

Autres exemples d'ajout d'éléments
Sélectionnez
mamap = [:]
maliste = []
mamap["TOTO"]= 44
maliste << "TITI"
maliste + "TOTO"

III-C. Les tests conditionnels

Comme dans beaucoup de langages, Groovy permet de contrôler le flux d'un programme :

Un exemple avec le if
Sélectionnez
variable1 = "Homme"
variable2 = 12

if (variable1 == "Homme" && variable2 > 6 )
println "Hello, tu es rentré dans le test!"

ce qui donnera en sortie de console :

 
Sélectionnez
groovy> variable1 = "Homme"
groovy> variable2 = 12
groovy> if (variable1 == "Homme" && variable2 > 6 )
groovy> println "Hello, tu es rentré dans le test!"

Hello, tu es rentré dans le test!

On retrouvera également les opérateurs habituels pour combiner des tests booléens :

  • == : égalité
  • != : différence

Finalement, c'est très proche de Java, mais vous étiez prévenus en introduction.

III-D. Les closures

Groovy est capable d'interpréter du code contenu entre les caractères { et }, d'en faire le corps d'une méthode et ceci sans avoir à créer une classe : c'est une fonctionnalité appelée closure.

La syntaxe d'une closure est la suivante :

 
Sélectionnez
{ [closureArguments->] statements }


Aussi, en utilisant le code suivant :

Créer une méthode avec les closures
Sélectionnez
helloWorld = {String nom, String profession -> println "Hello $nom, laisse-moi regarder ma boule de cristal...tu es $profession"}
helloWorld("eric","informaticien")

on obtiendra en sortie de console :

 
Sélectionnez
groovy> helloWorld = {String nom, String profession -> println "Hello $nom, laisse-moi regarder ma boule de cristal...tu es $profession"}
groovy> helloWorld("eric","informaticien")

Hello eric, laisse-moi regarder ma boule de cristal...tu es informaticien

Les possibilités des closures sont très étendues et mériteraient à elles seules un article, mais puisque vous le demandez si fort, voici quelques exemples en plus à essayer :

Quelques closures en plus
Sélectionnez
affiche = {value -> println(value);}
affiche(['a','b','c'])
Quelques closures en plus
Sélectionnez
def c = { arg1, arg2-> println "${arg1} ${arg2}" }
def d = c.curry("Ici")
d("Zebra 3")
Quelques closures en plus(je vous laisse imaginer le code suivant en Java)
Sélectionnez
trouvepetit = {liste->  liste.findAll { it.size() <= 4 }.each { println it } }
trouvepetit(["Eric", "Jean-Claude", "Paul-Edouard","Luc"])

IV. Les expressions régulières

Groovy supporte nativement les expressions régulières en utilisant l'expression ~"...", un objet Java Pattern est alors compilé.

Quelques exemples d'utilisation :

Tester la présence d'une chaîne
Sélectionnez
assert "Introduction au langage Groovy" =~ "langage"
Remplacement de chaîne
Sélectionnez
def phrase = ("Introduction au langage Groovy" =~ /Introduction au/).replaceFirst("Tutoriel sur le")
println phrase
Trouver un texte
Sélectionnez
def liste = "tokenUN TEXTE A TROUVERtoken" =~ /token(.*)token/
println liste[0][1]

Pour en savoir plus sur la syntaxe des expressions régulières, voir ici.

V. Le SQL avec Groovy

Pas de limites, Groovy est capable d'interagir avec votre SGBD via un pilote JDBC grâce à son module GSQL.

L'exemple suivant fonctionnera si une base MySql est installée localement, avec un compte dont les identifiants sont ROOT/ROOT (pour login/password).

Vous devrez également copier un pilote JDBC dans le répertoire lib de l'installation de Groovy (on trouve ce genre de pilotes dans toutes les bonnes crèmeries, mais aussi sur la page suivante Download Connector/J 5.0).

Un petit exemple ? Créons une table dans notre base de données :

Création d'une table
Sélectionnez
import groovy.sql.Sql

def sql = Sql.newInstance("jdbc:mysql://localhost:3306/test", "root",
                      "root", "com.mysql.jdbc.Driver")

sql.execute("create table DEPARTEMENT (CODE CHAR(3), LIBELLE VARCHAR(100))")

On va maintenant peupler cette table DEPARTEMENT :

Insertion de données
Sélectionnez
import groovy.sql.Sql

def sql = Sql.newInstance("jdbc:mysql://localhost:3306/test", "root",
                      "root", "com.mysql.jdbc.Driver")
                      
sql.execute("insert into DEPARTEMENT values ('88','Vosges')")
sql.execute("insert into DEPARTEMENT values ('69','Rhone Alpes')")

et enfin, parcourir les données qu'elle contient :

Sélection de données
Sélectionnez
import groovy.sql.Sql

def sql = Sql.newInstance("jdbc:mysql://localhost:3306/test", "root",
                      "root", "com.mysql.jdbc.Driver")

sql.eachRow("select * from DEPARTEMENT") {
    println "Département = ${it.LIBELLE}"
}

Le dernier script donnera alors en sortie de console :

 
Sélectionnez
groovy> import groovy.sql.Sql
groovy> def sql = Sql.newInstance("jdbc:mysql://localhost:3306/test", "root",
groovy>                       "root", "com.mysql.jdbc.Driver")
groovy> sql.eachRow("select * from DEPARTEMENT") {
groovy>     println "Département = ${it.LIBELLE}"
groovy> }

Département = Vosges
Département = Rhone Alpes

VI. Intégrer Groovy dans du code Java

Avec Groovy, un script peut être utilisé via un code Java qui pourra interagir avec ce script.

Un petit scénario : vous avez une application qui calcule une rentabilité, ce calcul est inconnu des personnes qui devraient le spécifier pour le moment, et ce que vous savez c'est qu'il sera amené à être modifié par la suite (ça vous est forcément arrivé un jour ce scénario ?).

Dans ce cas-là, Groovy va grandement vous aider à réaliser ce système de fonctionnement.

Un peu de pratique, nous avons ce script Groovy tout simple enregistré dans un fichier :

Contenu du fichier exemple1.gy (dans les sources en téléchargement)
Sélectionnez
println('Hello World : ' + argument)
return "Valeur de retour"

Et la classe suivante qui chargera le script, lui passera un paramètre et récupérera sa valeur de retour :

Utiliser un script Groovy depuis Java
Sélectionnez
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;

import java.io.File;
import java.io.IOException;

import org.codehaus.groovy.control.CompilationFailedException;

public class MaClasseGroovy {

    public static void main(String[] args) {

    GroovyShell shell = new GroovyShell();
    Script script;
    try {
        // Chargement du script groovy
        script = shell.parse(new File("scripts/exemple1.gy"));
        Binding binding = new Binding();
        // Création d'un paramètre
        binding.setVariable("argument", "Saint Nicolas");
        script.setBinding(binding);

        // Exécution du script
        Object retour = script.run();
        // Affichage de la valeur de retour du script
        System.out.println(retour);

    } catch (CompilationFailedException e) {

        e.printStackTrace();
    } catch (IOException e) {

        e.printStackTrace();
    }

    }
}

En exécutant cette classe Java, la console affichera :

 
Sélectionnez
Hello World : Saint Nicolas
Valeur de retour

Magnifique, non ?

Les sources de cet exemple sont disponibles ici sous la forme d'un projet pour Eclipse.

VII. Quelques différences avec Java

Les aficionados de Java remarqueront vite quelques différences entre la syntaxe utilisée par Groovy et leurs habitudes :

  • le point virgule est optionnel en fin de ligne ;
  • le typage des variables peut être dynamique ou statique (nous l'avons vu dans certains exemples précédents). Pour rappel, là où en Java nous aurions String maChaine = "Mon texte", Groovy permet maChaine = "Mon texte" ;
  • le contenu d'un tableau en Groovy se déclare avec des crochets (ex: int[] tab = [1,2,3]) et en Java avec des accolades (ex: int[] tab = {1,2,3}) ;
  • une boucle for en Groovy s'écrit for (i in 0..len-1) ;
  • les classes internes ne sont pas encore supportées en Groovy, les closures s'y substituent.

De nombreuses différences existent encore, je vous invite à consulter la page suivante pour en savoir plus : Differences from Java

VIII. Conclusion

Voilà, une petite présentation de Groovy qui peut-être trouvera son utilité dans un de vos projets.

Vous vous apercevrez vite que les possibilités de Groovy sont très étendues, pour exemple les fonctionnalités suivantes :

  • les expressions régulières ;
  • la gestion des langages de balises avec GroovyMarkup ;
  • le requêtage XML avec Gpath ;
  • les servlets avec Groovlets ;
  • Grails Object Relational Mapping (GORM) : un module de persistance ;
  • GSP pour GroovyServer Pages : similaire aux pages JSP ;
  • Etc.(pour toutes celles que vous trouverez sur le site officiel de Groovy).

Vous comprendrez rapidement combien Groovy mérite que l'on s'y intéresse, ce n'est pas pour rien qu'il est discuté au JCP dans une JSR 241: The Groovy Programming Language

IX. Liens

Les sources de l'exemple Java sont disponibles ici sous la forme d'un projet pour Eclipse.

http://groovy.codehaus.org : Le site officiel de Groovy

JSR 241: The Groovy Programming Language

Vous avez une IDE Java de prédilection ? vous trouverez sûrement son plugin Groovy ici : IDE Support

X. Remerciements

Un grand merci à Guillaume Laforge, Denis Cabasson, Christophe Jollivet, Xavier Mehaut et Yann Marec pour la relecture de cet article et leurs bons conseils.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 22/10/2006 Eric Reboisson. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.