vendredi 26 novembre 2010

Personnaliser ses cartes avec Google Maps API V3

Introduction

Dans le cadre d'un projet que je suis en train de mener, il y a le besoin de représenter une mappemonde avec un certain nombre de pays à mettre en évidence.
C'est un besoin assez classique pour un site web, mais cela peut s’avérer fastidieux et chronophage.
Pour ma part, j'ai rapidement pensé à utiliser l'API de Google Maps. Mais il me fallait styliser ma mappemonde.
Je devrais afficher seulement certains éléments, en l’occurrence seulement les terres et les mers. Mais il me fallait aussi changer les couleurs des mers et des terres, plus autoriser seulement un contrôle réduit sur la mappemonde.
Enfin, pour mettre en évidence les pays souhaités, ceux-ci devaient être affichés dans une couleur particulière et cerise sur le gâteau avec le changement de cette couleur sur l'évènement "onmouseover".

Google Maps API V3

Depuis peu, la version 3 de l'API Google Maps a vu le jour et Google a déclaré la version 2 comme dépréciée. Je me suis donc penché sur cette API.
Tout d'abord, il existe deux façons d'utiliser l'API, soit directement en Javascript, soit avec GWT via le module "Google Maps 1.1 Library". Malheureusement cette dernière ne supporte pas encore la version 3 de l'API Google Maps. Il faudra donc attendre une mise à jour pour bénéficier du confort de GWT.

Dans ce billet, je vais montrer comment utiliser l'API en Javascript. L'API Javascript est bien documentée et très claire. Donc, la première étape est de charge l'API de la manière suivante :



Le paramètre sensor permet d'indiquer s'il faut utiliser la fonctionnalité de géolocalisation du navigateur.
Ensuite, il faut créé l'objet Map en donnant l'élément du DOM qui va recevoir la carte et les options de la carte.



A partir de là on a une carte qui s'affiche positionnée, avec les contrôles que l'on souhaite. Maintenant comment stylisée ma carte ?
Depuis la version 3 de l'API, Google permet la personnalisation complète des cartes au travers de l'API "Styled Maps". Pour appliquer les styles à notre carte, il faut procéder comme ci-dessous :



Maintenant l'opération délicate est de mettre en évidence les pays souhaités. Pour cela on va utiliser un fichier standard KML pour décrire l'emplacement de mes pays sous la forme de polygones. Les polygones sont décrits point à point. On peut trouver des fichiers KML notamment dans les galeries de Google Earth, sinon il existe des outils en ligne pour créer ses propres fichiers KML.
Pour exploiter les fichiers KML dans notre mappemonde, j'ai utilise l'API "geoxml3". Pour cela, il faut importer les librairies suivantes :



Puis les utiliser de la manière suivante :



Le paramètre "useTheData" est une méthode que j'ai définie et qui sera appelée à la fin du chargement de mon fichier KML. Dans cette méthode, je pourrais notamment gérer les évènements de "mouseover" et "mouseout" sur mes polygones comme ceci :



Conclusion

Voila donc une manière élégante et simple de gérer ses cartes, bien entendu ce que je viens de vous montrer n'est que la base. Il est possible de faire beaucoup d'autres personnalisations et d'imaginer des interactions avec la carte beaucoup plus élaborées.

lundi 8 novembre 2010

GWT 2.1 RequestFactory : tour du propriétaire

Avec l'arrivée de GWT 2.1, est apparut une nouvelle API nommée RequestFactory. Le but de cette nouvelle API est de simplifier (un peu plus) les échanges entre le client et le serveur.
Les échanges entre le client et le serveur se faisaient traditionnellement avec le mécanisme RPC de GWT. Hors lorsque l'on utilise un ORM et que l'on est dans une architecture "Domain Driven", on se heurte aux problèmes de sérialisations des entités (qui sont des POJO instrumentés).
Plusieurs solutions existent pour palier ce problème : création d'objets DTO, transformation des entités en vrai POJO (avec la librairie Gilead par exemple).
Néanmoins, la mise en place de ces solutions a un coût et il était regrettable de ne pas avoir une solution intégrée par défaut à GWT.
Désormais, c'est chose faite avec l'API RequestFactory. Alors voyons comment fonctionne cette API.

Côté serveur, on va mettre en place une couche de persistance avec JPA. Pour ma part, j'ai choisi Hibernate comme moteur de persistance. Je ne décrirais pas ici la mise en place de cette couche, car ce n'est pas l'objectif de cet article et de nombreux tutoriaux existe à ce sujet. Donc une fois configurée et nos entités créées, puis mappées par annotations, nous allons pouvoir les exploiter avec l'API RequestFactory.

Les entités seront transmissent entre le client et le serveur, sous la forme d'objets DTO sérialisés en Json. C'est objets sont construit par l'API. Mais il faut décrire un minimum ces DTO. Pour cela, il faut créer une interface par entité à transmettre de la manière suivante :




On remarquera que l'on parle de proxy au lieu de DTO, ce qui n'est pas un hasard car la génération de code par defferd binding est très présente (comme dans les mécanismes RPC). D'autre part, il est possible d'utiliser l'API Bean Validation (JSR 303), nous verrons plus loin comment gérer la validation des entités.
Maintenant, on va créer des contextes d'échanges et leur fabrique (RequestFactory) pour le client.

Les contextes d'échanges sont des interfaces qui héritent de RequestContext, elles permettent d'exposer les méthodes statiques de services (un service métier, une DAO, ...) sous la forme d'un objet Request. Elles permettent aussi d'exposer des méthodes d'instance d'objets (une entité, un DTO) sous la forme d'un objet InstanceRequest. Voici deux exemples qui illustre mes propos :





Maintenant il faut créé la fabrique comme ceci :



Désormais tout est prêt, et il faut effectuer les appels côté client. Tout d'abord, on va instancier la fabrique précédemment créée, puis la lier à un EventBus, comme ceci :



Ensuite on va pouvoir récupérer des contextes d'échanges (RequestContext) et faire nos traitements. Voici un exemple de création d'un proxy pour l'entité Employee et l'appel à une méthode statique d'une DAO qui aura en charge de faire persister l'entité :



On voit dans cet exemple qu'il est possible d'avoir un callback sur l’exécution effective de la requête émise par la méthode fire. La méthode onViolation permet de récupérer toutes les violations levées par la validation de l'entité côté serveur.

L'exemple suivant montre comment faire le même traitement mais en invoquant une méthode sur l'instance de l'entité que l'on est en train de créer côté serveur :



C'est là que l'on commence à toucher du doigt le potentiel de cette API ! Je vous laisse le soins d'imaginer comment il est possible de l'exploiter. Voici donc une API qui permet d'augementer encore le rendement les développements GWT , couplé avec les CellWidget cela peut s'avérer redoutable d'efficacité.
Mais cela fera l'objet un d'autre article. Il faudra explorer aussi l'utilisation de cette API avec un conteneur comme Guice ou Spring.

NB :

Lors de mes premiers pas avec l'API RequestFactory, j'ai été confronté à plusieurs problèmes. Le premier est la non compilation des classes avec les annotations @ProxyFor et @Service. Ce problème est lié au plugin Eclipse GWT Designer, le seul contournement que j'ai trouvé est de désinstaller le plugin... Espérons que les prochaines mises à jour du plugin réglera ce problème. Le second problème que j'ai rencontré est de bien veiller à utiliser l'annotation @Id du package javax.persistence dans les entités JPA et ne pas utiliser l'annotation @Id du package com.google.gwt.requestfactory.shared.