Introduction au framework Grails

Grails_logo

 

L’objectif de cet article et de ceux à venir est de vous présenter les avantages que peut vous apporter le framework Grails. Pourquoi, quand et comment l’utiliser ? Nous verrons cela par la suite.

 

 

Présentation de GRAILS

 

Grails est un framework web open source, de développement rapide, basé sur le langage Groovy, lui-même basé sur le langage Java.

Il utilise plusieurs principes qui permettent une haute productivité :

– Don’t Repeat Yourself (DRY) : le framework est basé sur le modèle MVC.

– Convention plutôt que configuration (Convention over configuration ou coding by convention) : Grails propose de nombreux comportements par défaut, vous n’aurez presque rien à configurer lors du développement de votre application. Par exemple, une classe dont le nom termine par « Controller » sera automatiquement considérée comme un contrôleur web.

– Architecture orientée modèle : pour réaliser une application basique, vous aurez uniquement à vous préoccuper de vos modèles. Les vues, les contrôleurs et les tests seront générés.

– Prototypage : Grails vous permet de générer vos vues, contrôleurs et tests à partir de vos modèles grâce à des méthodes de scaffolding. Vous pouvez ainsi obtenir une application de CRUD très rapidement. Vous pouvez également créer vos propres templates pour ajouter des fonctionnalités à la génération, ou simplement modifier l’apparence de votre application.

– Plugins : de nombreux plugins sont disponibles pour Grails. Ils vous permettront d’implémenter rapidement des fonctionnalités, telles que l’authentification avec le plugin Spring Security Core.

 

Historique

 

Le développement de Grails a été débuté en juillet 2005 par Graeme Rocher. Le framework était alors connu sous le nom de “Groovy on Rails”, car inspiré de “Ruby on Rails”. La première version (0.1) a été publiée le 29 mars 2006. Le même mois, il est renommé en “Grails” sous la demande du créateur de Ruby on Rails, David Heinemeier Hansson. Les principales versions suivantes sont:

 

[table id=1 /]

 

Peu après la sortie de la version 1.0, la société G2One (The Groovy Grails Company) est rachetée en novembre 2008 par SpringSource, elle-même rachetée en août 2009 par VMware.

 

Architecture

 

Grails utilise de nombreuses technologies existantes. Les principales sont :
– Le langage Groovy
– Hibernate
– Spring
– Sitemesh pour gérer la mise en page
– Le célèbre système de logging Log4J
– JUnit pour les tests unitaires

Celles-ci sont organisées comme montré ci-dessous :

architecture_grails

 

Toute application Grails est organisée en quatre parties : les domaines (les modèles), les services, les contrôleurs et les vues. Nous verrons plus en détail cette organisation par la suite avec un exemple d’application.

Les vues sont gérées par le framework SiteMesh, permettant notamment de créer des layouts, tandis que le cœur de Grails est géré par le framework Spring. La persistance des données est facilitée par GORM (Grails Object Relational Mapping). Celui-ci est basé sur Hibernate et utilise par défaut sa base de données intégrée HSQLDB, il permet de faire la relation entre les domaines et la base de données. Nous le verrons plus en détail dans un article suivant. Gant quant à lui est basé sur Ant, il sera utilisé notamment lorsque nous exécuterons une commande pour gérer Grails telle que « grails run-app ».

Pour terminer, tout objet de votre application pourra être développé soit en Java soit en Groovy. Dans les deux cas, votre objet sera compilé en bytecode et exécuté par la JVM.

 

Installation

 

Nous allons maintenant voir comment mettre en place un environnement de développement pour utiliser Grails.

Avant de commencer, il faut bien évidemment avoir installé un JDK (en version 1.6 ou supérieure), avoir configuré la variable d’environnement JAVA_HOME, pointant vers le dossier d’installation de votre JDK, et avoir ajouté le dossier bin/ du JDK à votre variable PATH.

Il existe plusieurs solutions pour utiliser le framework Grails. La première, la plus simple, consiste à télécharger l’IDE Groovy/Grails Tool Suite (GGTS). Il s’agit d’un environnement de développement basé sur Eclipse, tout comme Spring Tool Suite (STS). Il vous suffit ensuite d’extraire l’archive téléchargée, et de lancer GGTS.

Si vous possédez déjà STS, vous pouvez facilement installer le plugin Grails en suivant ces directives.

Si vous souhaitez utiliser Grails avec un autre IDE comme IntelliJ IDEANetBeans ou TextMate, nous vous laissons consulter la documentation officielle à ce propos.

 

Conclusion

 

Après cette présentation, vous pouvez déjà apercevoir les avantages que peut fournir Grails. Il utilise le langage moderne Groovy, le réputé framework Spring, de nombreux plugins, le principe de « coding by convention », le prototypage… Il s’agit d’un framework bien adapté au développement très rapide d’applications basiques, vous laissant en même temps la possibilité de réaliser des fonctionnalités bien plus avancées que du simple CRUD.

Dans les prochains articles, nous verrons plus en détail le fonctionnement du framework par un exemple d’application.

 

Sources

http://grails.org/

http://en.wikipedia.org/wiki/Grails_(framework)

http://www-igm.univ-mlv.fr/~dr/XPOSE2009/Groovy_and_Grails/grails_architecture.php

JAVA EE 7 et JSON

Nous sommes de plus en plus souvent amenés à échanger des données en JSON en remplacement de XML.

JSON est né avec AJAX et les Web Services REST dans le but d’obtenir un format d’échange simple et peu verbeux (à l’inverse du XML).

Pour plus de détails sur JSON voir l’article de Wikipedia ou pour les plus techniques le site json.org.

Mais Java ne permettait pas, jusqu’à peu, de traiter nativement des messages JSON.

La version 7.0 de Java EE intègre le support de la JSR 353 qui est l’API Java pour le JSON Processing (JSON-P) et définit l’API pour analyser, générer, transformer et requêter du JSON.

L’avantage de cette spécification est de standardiser le traitement des flux JSON en Java. Mais nous allons voir dans cet article si elle apporte suffisamment en comparaison de frameworks Java de traitement JSON tels que Gson, même pour des traitements très simples.

Nous créons un objet People qui nous permet de tester les différents cas (tableau, composition, …) :

public class People {
	
	private String name;
	private String firstName;
	private Date birthDate;
	private Address address;
	private List<PhoneNumber> phones;
	...

public class Address {
	
	private String addressStreet1;
	private String addressStreet2;
	private int addressNumber;
	private String zipcode;
	private String town;
	...

public class PhoneNumber {
	
	private String type;
	private String number;
	...

Création d’un jeu de tests :

		people = new People();
		Address address = new Address();
		address.setAddressNumber(12);
		...
		PhoneNumber mobilePhone = new PhoneNumber();
		...
		PhoneNumber workPhone = new PhoneNumber();
		...		
		people.setFirstName("Paul");
		people.setName("Dubois");
		...
		ArrayList<PhoneNumber> phones = new ArrayList<PhoneNumber>();
		phones.add(mobilePhone);
		phones.add(workPhone);
		people.setPhones(phones);
Données de test

JSON-P

JSON-P propose deux modèles de développement :

  • Le modèle objet crée un arbre qui représente les données JSON en mémoire (équivalent au DOM en XML).
  • Le modèle Streaming permet de parcourir un document JSON à partir d’évènements (début ou fin d’un objet ou d’un tableau, lecture d’une clé ou d’une valeur, …) (équivalent StAX en XML).

Les classes principale de l’API sont :

  • JsonObjectBuilder & JsonArrayBuiler : pour créer des objets ou tableaux JSON
  • JsonReader & JsonWriter : pour lire et écrire des objets JSON
  • JsonObject, … : réprésentation des types de données JSON
		JsonObjectBuilder jsonBuilder = Json.createObjectBuilder()
				.add("firstName", people.getFirstName())
				.add("name", people.getName())
				.add("birthDate", people.getBirthDate().toString())
				.add("address", Json.createObjectBuilder()
						.add("addressNumber", people.getAddress().getAddressNumber())
						.add("addressStreet1", people.getAddress().getAddressStreet1())
						.add("addressStreet2", people.getAddress().getAddressStreet2())
						.add("addressZipCode", people.getAddress().getZipcode())
						.add("town", people.getAddress().getTown())
						.build()
						);
		JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
		for (PhoneNumber phoneNumber : people.getPhones()) {
			arrayBuilder.add(Json.createObjectBuilder()
					.add("type", phoneNumber.getType())
					.add("number", phoneNumber.getNumber()));
		}
		
		jsonBuilder.add("phones", arrayBuilder);
		
		JsonObject jsonObject = jsonBuilder.build();
		
		StringWriter stWriter = new StringWriter();
		JsonWriter jsonWriter = Json.createWriter(stWriter);
		jsonWriter.writeObject(jsonObject);
		jsonWriter.close();
		
		String jsonData = stWriter.toString();
JSON-P

1 & 2 – Création du JsonObjectBuilder et ajout des propriétés simples.

5 – Ajout d’un objet Address à l’objet People

13 – Création d’un tableau pour représenter la liste de téléphone

22 – Création du JsonObject représentant notre People

25 & 29 – utilisation d’un JsonWriter pour représenter notre People sous forme de String

 

{
  "firstName": "Paul",
  "name": "Dubois",
  "birthDate": "Mon Jun 12 08:06:24 CEST 1978",
  "address": {
    "addressNumber": 12,
    "addressStreet1": "Rue de la République",
    "addressStreet2": "Immeuble des tests",
    "addressZipCode": "13001",
    "town": "Marseille"
  },
  "phones": [
    {
      "type": "mobile",
      "number": "0612345678"
    },
    {
      "type": "work",
      "number": "0412345678"
    }
  ]
}
Résultat JSON-P

 GsON

Gson est une librairie Java développée par Google pour transformer des objets Java vers leur représentation JSON et vice-versa.

Les objectifs principaux de Gson sont :

  • Fournir un mécanisme simple pour convertir un objet Java en JSON et vice-versa
  • Permettre de convertir des objets existants et non modifiables
  • Permettre d’obtenir une représentation personnalisée des objets

 

La classe principale de Gson est Gson. Elle permet de convertir très rapidement un objet Java en JSON :

		Gson gson = new Gson();
		gson.toJson(people);
Gson

Le code parle de lui-même…

{
  "name": "Dubois",
  "firstName": "Paul",
  "birthDate": "Jun 12, 1978 8:06:24 AM",
  "address": {
    "addressStreet1": "Rue de la République",
    "addressStreet2": "Immeuble des tests",
    "addressNumber": 12,
    "zipcode": "13001",
    "town": "Marseille"
  },
  "phones": [
    {
      "type": "mobile",
      "number": "0612345678"
    },
    {
      "type": "work",
      "number": "0412345678"
    }
  ]
}
Résultat Gson

Le résultat est sensiblement le même que pour JSON-P si ce n’est le formatage des dates différent.

Gson propose un mécanisme de Serializer et Deserializer personnalisé qui nous permet d’appliquer un formatage particulier à un type donné (Date par exemple) ou plus généralement une représentation particulière pour un objet.

L’exemple suivant montre la création d’un Serializer personnalisé :

public class PeopleSerialiser implements JsonSerializer<People> {
	public JsonElement serialize(People people, Type arg1,
			JsonSerializationContext arg2) {
		final JsonObject jsonObject = new JsonObject();
		jsonObject.addProperty("firstName", people.getFirstName());
		jsonObject.addProperty("name", people.getName());
		jsonObject.addProperty("birthDate", people.getBirthDate().toString());
		jsonObject.addProperty("addressNumber", people.getAddress().getAddressNumber());
		jsonObject.addProperty("addressStreet1", people.getAddress().getAddressStreet1());
		jsonObject.addProperty("addressStreet2", people.getAddress().getAddressStreet2());
		jsonObject.addProperty("addressZipCode", people.getAddress().getZipcode());
		jsonObject.addProperty("town", people.getAddress().getTown());

		final JsonArray jsonAuthorsArray = new JsonArray();
        for (final PhoneNumber phoneNumber : people.getPhones()) {
        	final JsonObject number = new JsonObject();
        	number.addProperty("type", phoneNumber.getType());
			number.addProperty("number", phoneNumber.getNumber());
            jsonAuthorsArray.add(number);
        }
        jsonObject.add("phones", jsonAuthorsArray);
		return jsonObject;
	}
}

1 & 2 : Notre Serializer implémente l’interface JsonSerializer et définit la méthode serialize qui prend notamment en paramètre un objet People pour renvoyer un JsonElement.

4 : La suite ressemble un peu à JSON-P avec la création d’un JsonObject qui est la représentation de l’objet en JSON (JsonArray pour les tableaux).

Dans cet exemple on construit une représentation de notre objet People en publiant une adresse « à plat » et non comme objet au sein de People.

		final GsonBuilder gsonBuilder = new GsonBuilder();
	    gsonBuilder.registerTypeAdapter(People.class, new PeopleSerialiser());
	    gsonBuilder.setPrettyPrinting();
	    final Gson gson = gsonBuilder.create();
	    gson.toJson(people);

Afin d’utiliser notre serializer on crée un GsonBuilder (1) auquel on passe notre serializer (2).

L’option setPrettyPrinting permet d’obtenir une représentation JSON formatée et indentée.

Puis cette fois on crée notre objet Gson grâce à la méthode create du GsonBuilder (4).

On obtient un résultat conforme à nos attentes :

{
  "firstName": "Paul",
  "name": "Dubois",
  "birthDate": "Mon Jun 12 08:06:24 CEST 1978",
  "addressNumber": 12,
  "addressStreet1": "Rue de la République",
  "addressStreet2": "Immeuble des tests",
  "addressZipCode": "13001",
  "town": "Marseille",
  "phones": [
    {
      "type": "mobile",
      "number": "0612345678"
    },
    {
      "type": "work",
      "number": "0412345678"
    }
  ]
}
Résultat Gson serializer

Conclusion

L’api JSON-P au sein de JEE7 est une vrai avancée car elle permet de traiter nativement du JSON. Mais le manque principal actuel est le binding natif d’un objet Java vers JSON.

On voit que dans le cas où on construit une API basée sur des échanges JSON et des objets métiers, l’utilisation de JSON-P sera bien trop verbeuse et on privilégiera l’utilisation de Gson (ou d’autres framework comme celui-ci) dont le coût de construction sera quasiment nul.

Dans le cas où l’on doit intégrer des messages JSON existants, la question se pose. Soit nos objets métiers n’existent pas et on va avoir tendance à utiliser Gson et le binding, soit nos objets métiers existent et la question se pose car la verbosité des deux API sera quasiment identique.

Il faudrait ensuite approfondir l’étude des deux sur des aspects tels que les performances pour faire son choix. Gson donne quelques indications à ce sujet (ici) mais un comparatif sur un même jeu de données serait intéressant.

Ce manque de binding a clairement été identifié par Oracle, notamment lors d’un sondage sur les nouveautés à apporter à JEE8. Une nouvelle JSR va être soumise d’ici peu pour intégrer une API Java JSON Binding à JEE8.

Prochains tests lors de la sortie de JEE8…

ViaXoft Labs Days : quésako

Les Viaxoft Labs Days quésako ?

Au delà de notre quotidien qui nous conduit à faire évoluer nos applications, il est important d’accorder de la place à la veille technique liée directement ou non à nos préoccupations opérationnelles.

Pour répondre à cette problématique, nous organisons périodiquement les « Viaxoft Lab Days ». Les VLD sont des journées qui regroupent l’ensemble des équipes de développement de ViaXoft.

Notre objectif au cours de chacune d’elle, est de « débroussailler », creuser, explorer un sujet technique, un framework, un concept.

Le livrable en fin de journée est un POC (Proof of concept) qui permet de présenter la techno abordée. L’organisation de chaque journée est définie par l’équipe elle-même en fonction du sujet traité (pair programming, travail en équipe, micro étude préalable, …).

L’équipe liste les idées de sujets à aborder d’une réunion sur l’autre, puis nous votons pour sélectionner le ou les sujets qui seront abordés lors de la prochaine journée. Les journées déjà organisées ont traité des sujets tels que la mobilité, NoSql, API Google, Kinect, Leap Motion et Arduino.
Sujets plus ou moins proches de notre quotidien, mais qui nous permettent d’ouvrir le champ des possibles et d’emmagasiner des connaissances qui pourront peut être nous servir dans le futur.

Scrum : retour aux fondamentaux

Retours sur la méthode Scrum après 6 ans d’utilisation

Les 10 et 11 Avril se déroulait la quatrième édition du ScrumDay. L’occasion pour nous de découvrir pas mal de nouveautés mais également de revenir par certains aspects sur les notions essentielles de l’agilité.

La keynote d’ouverture était assurée par Alistair Cockburn, signataire et co-auteur du manifeste agile. Les slides de la keynote se trouvent ici.

Il est revenu sur les 4 valeurs du manifeste et leur trop (souvent) mauvaises interprétations puis a introduit un concept issu de l’Aïkido qui décrit les 3 étapes de l’apprentissage :

  • Shu (守:しゅ?, « protéger », « obéïr ») — sagesse traditionnelle – apprendre les fondamentaux
  • Ha (破:は?, « se détacher », « digresser ») — casser avec la tradition — trouver les exceptions à la sagesse traditionnelle, trouver de nouvelles approches
  • Ri (離:り?, « quitter », « se séparer ») — transcender — il n’y a pas de technique ou de sagesse traditionnelle, tous les mouvements sont permis

(source wikipedia)

Ce concept est pour lui réplicable quelque soit le domaine d’application et en particulier l’agilité.

Il a ensuite zoomé sur Scrum et ce qu’il nomme le coeur de Scrum :

  1. Livrer à chaque sprint
  2. Laisser l’équipe décider
  3. Inspecter et s’adapter tous les jours, et à chaque sprint
  4. Un Scrum Master a du temps pour lever les obstacles
  5. Le métier ne s’exprime qu’à travers une seule voix (Product Owner)

Mais le plus intéressant est qu’il considère « tout le reste » comme « barnacles » (parasite) ou pire rumeur et ouï-dire :

  • Burn-down charts
  • Kanban (Not-started | Started | Done) boards
  • ScrumMaster is / is not the project manager / product owner / tech lead
  • Product Owner is / isn’t invited to the dailies
  • The “3 questions” at the daily stand-up
  • User stories
  • Planning Poker
  • Fibonacci numbers / hours / story points

Il ne veut pas dire par là que l’on doit jeter toutes ces pratiques à la poubelle mais bien qu’elles doivent être choisi par l’équipe elle même si celle-ci considère que telle ou telle pratique apporte un plus aux 5 points points qui constituent le coeur de Scrum.

Et nous dans tout ça ?

Cela fait presque 6 ans que nous « utilisons » Scrum. Nous avons mis en place toutes ces pratiques et plus, puis en avons abandonné car l’équipe ne les trouvait pas/plus adaptées :

  • Pas adaptée comme par exemple le planning poker : nous trouvions que cette pratique était trop fastidieuse et pas assez productive par rapport à la taille de notre backlog. Avec cette pratique, nous estimions environ 10 user stories en une heure alors que nous en avions 100 à chiffrer. Nous avons depuis mis en place une autre pratique qui nous correspond plus.
  • Plus adapté comme par exemple la revue de backlog : dans les premiers mois/années nous faisions une revue de backlog périodique avec l’équipe qui permettait à notre PO d’affiner les User Stories grâce au commentaires de l’équipe et de débuter une conception de haut niveau. L’expérience (culture) aidant, nous n’avons plus eu besoin de cette revue et si certains points ne sont pas clairs, nous avons la faculté de donner des réponses « à la volée » lors des démarrages de sprint (connaissance partagée).

Depuis quelques mois nous avons débuté de nouveaux produits et patatra… Nous nous sommes pris les pieds dans le tapis, sans vraiment s’en rendre compte. Nous avons adopté les mêmes pratiques et réflexes (nature) que pour notre produit principal, mais en omettant quelques détails :

  • Nouveautés produits (fonctionnel et conception)
  • Manque d’expérience de l’équipe : pas en terme d’années mais sur les produits, les rôles (PO) et l’architecture

Ces problèmes sont, bien entendu, remontés lors des rétrospectives de sprint, mais le diagnostic que nous en avons fait était assez parcellaire.

Un petit détour par la Coach Clinic du ScrumDay (merci à Fabrice Aimetti@fabriceaimetti) suite à la keynote, quelques échanges de tweets, et la lumière fut : le contexte dans lequel nous évoluons n’est plus le même, nous devons (ré)apprendre, (re)pratiquer (Shu) pour ensuite progresser dans le Ha et le Ri. L’équipe va donc devoir se réapproprier certaines pratiques qui lui permettront sur ces nouvelles bases d’acquérir l’expérience nécessaire à son évolution.

En conclusion et avec une vision plus « aérienne », nous devons constamment évoluer dans une spirale dynamique : pratique, culture, nature, pratique, culture, nature, … afin de nous permettre de revenir aux fondamentaux lorsque c’est nécessaire pour ensuite transcender et transgresser l’existant pour toujours être en mouvement. (Merci à Pablo Pernot @pablopernot)

« Notre nature est notre culture, et notre culture est notre nature » Edgar Morin. (Pablo, La Horde Agile)

eXtreme Quotation à l’Agile Tour Montpellier

Retours sur la session eXtreme Quotation à l’Agile Tour Montpellier

J’ai assisté à la session eXtreme Quotation animée par Guillaume Duquesnay (@duquesnay) et Jonathan Scher (@jonathan_scher) à l’Agile Tour Montpellier.

Je profite de ce billet pour remercier les organisateurs et les sponsors pour cette journée riche et bien remplie et le super accueil réservé aux participants.

Revenons à nos moutons…

J’étais un peu septique en allant à cet atelier. Le titre était vendeur, m’attirait même. J’y allais surtout car le Planning Poker tel que nous le pratiquons me semble lourd et je cherchais plutôt quelques astuces pour l’améliorer…

Mais là on nous promettait de « chiffrer 90 stories en moins de 20 minutes  » !

Vous trouverez une description détaillée de l’atelier ici et ici (la forme présentée à #atmtp utilisait les tailles de T-Shirt).

Au cours de l’atelier nous avons estimé le backlog de création d’un service de messagerie tel que Gmail.
Nous étions répartis en deux groupes d’environ 20 à 25 personnes (la taille des groupes mettait également à mal l’atelier). Au final nous avons bien estimé environ 50 stories en 20 minutes et malgré la méconnaissance du projet et du contexte général, la répartition s’est faite assez facilement.
Le résultat est donc vraiment positif.

Je pense que nous allons tester cet atelier à la place de notre prochain planning poker ; nous perdrons un peu de précisions sur nos estimations en point mais ce n’est en réalité pas très grave :

  • à ce moment là des estimations nous ne recherchons pas un chiffrage à l’heure près,
  • nous gagnerons beaucoup de temps de l’équipe et pourrons de ce fait en faire plus souvent, notamment pour décomposer et réestimer les user stories atteignant les tailles XL ou XXL,
  • cela permettra de créer une dynamique d’équipe que nous n’avions pas dans le planning poker.

Merci en tout cas aux deux intervenants pour la mise en avant de cette technique, qui montre encore une fois les bienfaits de l’amélioration continue.

Agile Games : soirées Agile After Work

L’Esprit Agile a le plaisir de vous faire découvrir ses prochaines soirées Agile After Work !

Découvrez les ateliers Agile Games !

Voici une brève description de l’apport des jeux proposés :

  • agile gamesChaises non musicales : Le but est de mettre en avant l’importance de l’auto organisation, la communication, la simplicité et la confiance au sein d’une équipe.
  • Agile Airplane : permet de mettre en avant certaines notions d’agilité : priorisation, démo au client, itération, auto-organisation, test d’acceptation, rétrospective.

 

agile games

  • Business Value Game : ce jeu donne des techniques pour trouver la valeur métier des user stories.
  • Marshmallow Challenge : mets en avant l’importance des itérations, des tests et de l’autorganisation.
  • Multitâche : montre que le multitâche est beaucoup moins productif.

 

N’hésitez pas à voter pour votre session préférée sur Doodle.

Agile After Work du 13 juin 2012 – Lego4Scrum

 Agile After Work

 

L’Esprit Agile a le plaisir de vous inviter à participer à sa prochaine soirée Agile After Work :

Le mercredi 13 juin 2012 à partir de 18h30

à L’Hôtel Technologique – 45 Rue Frédéric Joliot Curie – 13013 Marseille

Sur le thème : « Agile Games : Lego4scrum ».

Animateur : Romain Vignes

(https://twitter.com/#!/rvignes)

Le nombre de places à la soirée Agile After Work étant limité, les inscriptions sont obligatoires

Inscription Plan d’accès

Marshmallow Challenge ou l’importance du prototypage

Retours sur le Marshmallow Challenge

Nous avons été invité par le PMI lors d’une après-midi dédiée à l’agilité.

Suite à une présentation de l’agilité par Laurence Hanot du CARA, j’ai fait une présentation de SCRUM en 15 minutes, suivie d’un mini retour d’expérience sur son application.

Puis nous avons scindé la salle en deux ateliers, « Artistes et spécifieurs » pour Laurence et le « Marshmallow Challenge » pour Claire (@clrh) et moi.

C’est de ce dernier atelier dont je vais parler dans ce billet.

 

J’avais assisté à l’atelier animé par Pablo Pernot lors de l’Agile Tour Marseille 2011 et j’avais été surpris par le dynamisme de celui-ci (Pablo y était pour beaucoup  ).

L’objectif de cet atelier est de mettre en exergue l’importance du prototypage (itération) et de tester très tôt.

Vous trouverez toute la documentation nécessaire pour l’organisation du challenge et quelques retours chiffrés très intéressants (nous reprenons ces données dans notre présentation) sur le site du Marshmallow Challenge.

 

Je voulais revenir dans ce billet sur l’évolution de nos équipes tout au long du challenge.

Le groupe était constitué de 2 équipes de 4 personnes et 2 équipes de 3 personnes. Sans trahir la fin du billet, le différenciel de nombre n’a pas eu d’impact sur le résultat.

La première chose frappante est que dès le début de l’atelier les 4 équipes ont sorti une feuille de papier pour commencer une phase de conception.

La première équipe à avoir testé la résistance des spaghettis par rapport au Marshmallow l’a fait au bout de 4’30 (équipe 2), ce qui en soit est pas mal ; mais elle n’a pas su capitaliser sur cet avantage et est reparti dans sa phase de conception.

Les deux équipes suivantes (1 et 3) ont fait leurs premiers tests avec le Marshmallow entre 7’ et 7’30. Pour l’équipe 1 ce n’était pas vraiment un test de résistance mais un début de construction.

Ce qui est intéressant avec l’équipe, c’est qu’en ayant validé cette première phase de construction, ils ont repris une phase de conception sans se soucier réellement du temps qui passait.

L’équipe 4 a fait toute sa phase de construction de la structure à plat sur la table et a voulu la mettre debout au bout de 16’30. Bien sûr ce qui devait arriver arriva, la pyramide n’a pas supporté le poids du Marshmallow.

Au final les 4 équipes ont suivi à peu prêt le même cheminement avec une phase conception assez longue et très peu de tests.

Seule l’équipe 1 a présenté une structure à la fin des 18 minutes, en gardant celle de leurs premiers tests.

Nous avons ensuite fait une rétrospective avec chaque équipe. Le point qui est le plus ressorti de ces rétrospectives est que les membres des équipes se sont bien entendus. Finalement le résultat (et l’échec) passe au second plan car ils ont eu l’impression d’avoir suivi des phases précises mais qu’ils ont eu du mal à gérer le temps assez court.

 

Au final c’était un atelier très intéressant qui je pense a fait comprendre l’importance des itérations et des tests à tous les participants.

1370961836_doc_pdfVoir la présentation Marshmallow Challenge (PDF, 3.41MB)

Sélection de colonnes dans Hibernate

 Liste avec seulement quelques colonnes dans Hibernate

Les outils d’ORM (Hibernate, Ibatis, …) sont aujourd’hui à maturité et ne souffrent plus des problèmes de performance des premières versions. Le code SQL généré, ainsi que la transformation en objets, ont été très largement optimisés.

Cependant selon la taille de la grappe d’objet remontée, il peut subsister des problèmes de performance, liés au nombre et à la complexité des objets à créer. Le cas d’utilisation typique sur une application de gestion est l’affichage d’une liste d’objet complexe sur un écran de recherche.

Prenons le cas par exemple d’une liste de commande (que nous simplifions volontairement) :

public Class Commande {

private Destination destination;

private Set<LigneCommande> lignes;

private Client client;

...

}
Une requête Criteria qui permet de remonter la liste des commandes ressemble à ceci :
DetachedCriteria criteria = DetachedCriteria.forClass(Commande.class,"commande")

.createAlias("commande.Destination", "destination", CriteriaSpecification.LEFT_JOIN)

.createAlias("commande.Lignes", "lignes", CriteriaSpecification.LEFT_JOIN)

.createAlias("commande.Client", "client", CriteriaSpecification.INNER_JOIN);

List<Commande> listCommande = getHibernateTemplate().findByCriteria(criteria);
Cette requête remonte donc tous les objets Commande (toutes les colonnes de la table correspondante), ainsi que les objets liés (et donc toutes les colonnes associées). Dans le cas où la grappe d’objets est importante et composée de nombreux objets, le nombre de lignes remontées devient très important et la constitution des objets très coûteuse  Rappelons que nous souhaitons simplement afficher une liste avec seulement quelques colonnes… au moins 95% des données remontées ne nous servent donc à rien.

Depuis la version 3 d’Hibernate a été introduite la notion de Projection. Celle-ci va nous permettre non seulement de remonter seulement les colonnes qui nous intéressent mais également une liste d’objets non gérés par Hibernate ; par exemple nous allons pouvoir remonter directement une liste de DTO (data transfert object) en se basant sur le même objet criteria (forClass(Commande.class, »commande »)) :

On définit le DTO :

public class DealListDto implements Serializable  {
    private static final long serialVersionUID = 1L;

    private java.lang.String id;
    private String ref;
    private Date date;
    private String nom;
    private String prenom;
    private String destNom;
    ...
}
puis les propriétés que l’on souhaite remonter, ainsi que le bean avec lequel on veut les mapper :
criteria.setProjection(Projections.projectionList()

.add(Property.forName("commande.Id"), "id")

.add(Property.forName("commande.Ref"), "ref")

.add(Property.forName("commande.Date"), "date")

.add(Property.forName("client.Nom"), "nom")

.add(Property.forName("client.Prenom"), "prenom")

.add(Property.forName("destination.nom"), "destNom")

.setResultTransformer( Transformers.aliasToBean(DealListDto.class));

List<DealListDto> listCommande = getHibernateTemplate().findByCriteria(criteria);
Nous obtenons donc une liste de DealListDto, beaucoup plus légers, que nous pouvons  faire remonter directement sur la couche client.

Datasources en hosted mode avec GWT 1.6

Configuration des datasources en hosted mode avec GWT 1.6

La migration de GWT de la version 1.5 à la version 1.6 s’est accompagnée de changements en profondeur au niveau du hosted mode. En effet, celui-ci utilisait précédemment une version embarquée du serveur tomcat, qui a été remplacée dans la dernière version par jetty.

Ce changement a donc entraîné une restructuration au niveau de la configuration des projets et notamment de la déclaration des datasources *. Cet article va donc présenter la configuration des datasources en hosted mode avec GWT 1.6.

La première étape est de rajouter les jar jetty-naming-6.1.11.jar et jetty-plus-6.1.11.jar à notre projet. Ceux-ci permettront d’utiliser notre propre fichier de configuration de jetty. Si comme nous vous utilisez Maven pour gérer les dépendances de votre projet, rajoutez les deux entrées suivants à votre pom.xml :

<dependency>
<groupid>org.mortbay.jetty</groupid>
<artifactid>jetty-naming</artifactid>
<version>6.1.11</version>
</dependency>
<dependency>
<groupid>org.mortbay.jetty</groupid>
<artifactid>jetty-plus</artifactid>
<version>6.1.11</version>
</dependency>

Sinon, vous trouverez ces jars sur le site de jetty.
Il faut maintenant crée un fichier nommé jetty-web.xml qui contiendra la déclaration de nos datasources sous la forme suivante :

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure>
<New id="dataset1">
<Arg>java:comp/env/jdbc/dataset1</Arg> <Arg>
<New>
<Set name="Url">jdbc:mysql://localhost:3306/database1?autoReconnect=true</Set>
<Set name="User">username1</Set>
<Set name="Password">password1</Set>
</New>
</Arg>
</New>
<New id="dataset2">
<Arg>java:comp/env/jdbc/dataset2</Arg>
<Arg>
<New>
<Set name="Url">jdbc:mysql://localhost:3306/database2?autoReconnect=true</Set>
<Set name="User">username2</Set>
<Set name="Password">password2</Set>
</New>
</Arg>
</New>
</Configure>

C’est cette configuration qui va indiquer à quelle base de donnée correspond chacun des datasets, et les paramètres de connexion. Dans cette exemple, nous déclarons deux datasets qui utilisent les bases de donnée MySql database1 et database2 du serveur local.
Il faut ensuite référencer les datasources dans le web.xml pour que notre application soit en mesure de les utiliser :

<res-ref-name>java:comp/env/jdbc/dataset1</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<res-ref-name>java:comp/env/jdbc/dataset2</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

Une fois cette étape réalisée, vous pouvez utiliser vos datasets au sein de votre application comme vous le feriez normalement :

DataSource source = (DataSource)ctx.lookup("java:comp/env/jdbc/dataset2");
Connection connection = source.getConnection();
//...

 

Loading...
X