Groovy and Grails

Groovy avancé

Meta Object Protocol (MOP)

Ce concept permet d’ajouter des clôtures à n’importe quelle classe du langage.
Chaque classe a une propriété metaclass sur laquelle on va pouvoir ajouter les clôtures.

Voici un exemple simple dans lequel on souhaite ajouter la clôture spellIt() à la classe java.lang.String.


String.metaClass.spellIt = {

def chars = delegate.toCharArray();

for(char c : chars){

println c;

}

}


"hello".spellIt();

/*

h

e

l

l

o

*/

Voici un autre exemple qui combine le MOP et le passage de clôture en argument d'une autre clôture.
Ce point technique a un intérêt car c'est souvent utilisé dans Grails.


// Définition de la "meta-clôture"

Collection.metaClass.myForEach = { closureArg ->

for(Object item : delegate){

closureArg(item)

}

}


// Une liste de String :

def list = ["Hello","!", "How", "are", "you", "?"];


// Utilisation de la "meta-clôture" avec une clôture en paramètre

list.myForEach { item ->

print item+" ";

}

// Hello ! How are you ?

L'objet nommé "delegate" correspond a l'instance de l'objet issu de la classe.




Gestion d'XML

Les concepteurs de Groovy ont essayé de trouver des façon simple de générer ou de "parser" des fichiers XML.

Dans cet exemple, on utilise la classe MarkupBuilder pour générer de l'XML.
Vous pouvez constater que la façon d'écrire l'XML est non verbeuse.

def writer = new StringWriter();

def builder = new MarkupBuilder(writer);

builder.doubleQuotes=true;


builder.students {

student(id:"1"){

firstname("prenom")

lastname("nom")

extra(type:"email", "nom.prenom@gmail.com")

}

}

println writer.toString();

Voici le résultat obtenu :

<students>
<student id="1">
<firstname>prenom</firstname>
<lastname>nom</last<ame>
<extra type="email">nom.prenom@gmail.com</extra>
</student>
</students>

Pour "parser" un fichier XML, il existe la classe XML Slurper.
Elle permet d'accéder aux données de manière très simple. On parcours l'arbre XML a partir de la racine un peu à la manière d’XPath.
D’ailleurs, ils ont appelé ça GPath. (pour Groovy Path)

input = """

<students>

<student id="1">

<firstname>prenom</firstname>

<lastname>nom</lastname>

<extra type="email">nom.prenom@gmail.com</extra>

</student>

<student id="2">

<firstname>Etudiant</firstname>

<lastname>Bidon</lastname>

<extra type="email">bidon@etudiant.univ-mlv.fr</extra>

</student>

</students>

"""

//On parse le texte

students = new XmlSlurper().parseText(input)


//Affichage du prénom de l'étudiant ayant l'ID 1

println students.student.find{ it.@id=="1" }.firstname.text()


//Affichage des adresses e-mail des étudiants ayant un nom "Bidon"

students.student.findAll{ it.lastname.text()=="Bidon" }.each{

println it.extra.text();

}

//Changement de la valeur des attributs type par "courriel"

students."*".extra.@type="courriel";


//Génération de l'XML puis affichage.

def outputBuilder = new StreamingMarkupBuilder()

println result = outputBuilder.bind{ mkp.yield students }




Templates

Une autre fonctionnalité intéressante de Groovy est la génération simplifiée de templates.

Il suffit simplement de charger un fichier de template (.gtpl), dans lequel des valeurs ont été insérées à la manière de Groovy.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head><title>Fiche étudiant</title></head>

<body>

Prénom : ${user?.firstname} <br/>

Nom : ${user?.lastname} <br/>

Message : ${message} <br/>

<!-- Insertion de code groovy -->

Surnom : ${ if(user?.firstname=="Robert") "bob" }

</body>

</html>

Puis, à l’aide d’une Map, on va faire correspondre les valeurs afin de générer la page.

class User {

def firstname;

def lastname;

}

def binding = [ user : new User(firstname: "Robert", lastname:"Bidon"),

message : "Bonjour !!"]


def userTemplate= this.class.getResource("user.gtpl");

def templateEngine = new SimpleTemplateEngine();

def template = templateEngine.createTemplate(userTemplate);


println template.make(binding);




Tests unitaires

Comme groovy est un langage très flexible il est vraiment nécessaire d’effectuer des tests unitaires.
Afin de faciliter ceux-ci, les créateurs du langage ont étendu JUnit afin de l’adapter aux spécificités du langage.

Voici une liste quelques méthodes d'assertions qui étendent JUnit :

Par exemple on y trouve la méthode assertScript qui renvoie false si jamais une exception survient lors de l'exécution du script.