Google fait les cartes, Spring fait le REST

Logo google mapsLa cartographie est maintenant utilisée communément sur le Web. On ne peut plus consulter un site marchand sans pouvoir calculer son itinéraire jusqu’au point de vente, se renseigner sur un pays sans pouvoir explorer sa géographie, parfois même faire une sortie jogging ou vélo sans consulter ultérieurement son parcours sur une carte…

Les deux grands fournisseurs de cartographie sont actuellement Google avec sa Google Maps API et Microsoft avec Bing Maps. La plupart du temps, leur utilisation passe par du code Javascript exécuté côté client. Pourtant, il est parfois nécessaire de faire des traitements de géolocalisation côté serveur. Pour cela, les deux fournisseurs ont prévu une API de type REST. La suite de cet article ne s’intéressera plus qu’au monde “Google” et à son API, capable de générer une réponse de type XML ou JSON.

Be API avec le REST de Google !

Les principes de base

Pas de grosse surprise pour effectuer une requête géographique : on reste sur des principes REST classiques, avec une requête pour effectuer une géolocalisation inversée (à partir d’une adresse postale) du type :

http://maps.googleapis.com/maps/api/geocode/xml?address=90+rue+Baudin+92300+Levallois+Perret&sensor=false

Cette requête, qui peut être jouée directement sur un navigateur, permet de récupérer un message XML du type :

OK street_address <formatted_address>90 Rue Baudin, 92300 Levallois-Perret, France</formatted_address> <address_component> <long_name>90</long_name> <short_name>90</short_name> street_number </address_component> <address_component> <long_name>Rue Baudin</long_name> <short_name>Rue Baudin</short_name> route </address_component> <address_component> <long_name>Levallois-Perret</long_name> <short_name>Levallois-Perret</short_name> locality political </address_component> <address_component> <long_name>Hauts-de-Seine</long_name> <short_name>92</short_name> administrative_area_level_2 political </address_component> <address_component> <long_name>Île-de-France</long_name> <short_name>IdF</short_name> administrative_area_level_1 political </address_component> <address_component> <long_name>France</long_name> <short_name>FR</short_name> country political </address_component> <address_component> <long_name>92300</long_name> <short_name>92300</short_name> postal_code </address_component> 48.8989222 2.2877605 <location_type>RANGE_INTERPOLATED</location_type> 48.8975800 2.2864066 48.9002780 2.2891046 48.8989222 2.2877507 48.8989358 2.2877605

Le message résultat est immédiatement compréhensive à un esprit humain. C’est sans doute pour cela qu’il n’est absolument pas documenté par Google, qui ne fournit pas même un XSD…  🙁

REST ou JSON ?

Google préconise plutôt l’utilisation du service JSON.

JSON est clairement une notation beaucoup plus compacte que le verbeux XML et donc plus efficace. Cependant, elle n’offre pas tout l’attirail de XML, notamment en ce qui concerne la description des signatures de service et le contrôle des formats des messages. J’ai toujours tendance à privilégier XML pour les échanges de serveur à serveur et JSON pour les interactions internes à un système (interrogation AJAX d’un client web sur son serveur par exemple).

On est ici sur des échanges serveur à serveur, donc va pour le XML !

Comment conjuguer REST et Spring

La classe RestTemplate

Spring fournit la classe RestTemplate, qui elle-même fournit des méthodes de haut niveau pour invoquer les 6 méthodes principales du protocole HTTP. Elle simplifie énormément la programmation de la partie cliente d’un appel REST en gérant toute la plomberie habituelle liée à l’utilisation du protocole HTTP et la conversion des objets Java.

La lecture de la doc Spring conduit vite à la constatation que l’appel du service Google maps précédent peut se faire sous la forme :

restTemplate.getForObject( "http://maps.googleapis.com/maps/api/geocode/xml?address={address}&sensor=false", String.class,"90 rue Baudin, 92300 Levallois Perret");

L’encapsulation de JAXB 2

Le code suivant est simple et de bon aloi, mais ne résout pas la problématique du mapping du résultat (ici un flux XML) vers le graphe d’objets Java.

Heureusement, et c’est là qu’entre la magie du RESTTemplate, il peut être configuré à l’aide d’un marshaller fourni par Spring :

org.springframework.oxm.jaxb.Jaxb2Marshaller

Rien de plus à ajouter que de référencer cette classe, à la fois comme marshaller et comme unmarshaller pour retrouver son modèle métier directement mappé sur le flux XML ! C’est de la pure magie, mais c’est bon !

Un petit projet vaut mieux qu’un long post de blog…

La Mise en place Maven

Il n’existe pas à ma connaissance d’archetype tout prêt pour faire du Spring. Pour notre exemple, nous partirons donc d’un archetype simple, en tapant la commande suivante :

mvn archetype:generate \ -DarchetypeArtifactId=maven-archetype-quickstart \ -DgroupId=fr.ippon.gmap \ -DartifactId=restgmap \ -Dversion=1.0-SNAPSHOT

On obtient ainsi un projet restgmap, dans lequel nous allons nous empresser de modifer le fichier pom.xml pour notamment ajouter les dépendances à Spring :

junit junit 4.10 test org.apache.log4j com.springsource.org.apache.log4j 1.2.15 org.apache.commons com.springsource.org.apache.commons.logging 1.1.1 org.springframework org.springframework.core ${spring.version} org.springframework org.springframework.test ${spring.version} test org.springframework org.springframework.context ${spring.version} org.springframework spring-oxm ${spring.version} org.springframework org.springframework.web ${spring.version} <spring.version>3.0.5.RELEASE</spring.version> com.springsource.repository.bundles.release SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases http://repository.springsource.com/maven/bundles/release com.springsource.repository.bundles.external SpringSource Enterprise Bundle Repository - External Bundle Releases http://repository.springsource.com/maven/bundles/external

La création du modèle

L’analyse de la réponse fournie lors d’une interrogation du service de géolocalisation permet assez facilement de construire un modèle objet comme suit :

Modèle de géolocalisation

Ce modèle en poche, les annotations JAXB se font très facilement même s’il aurait été plus simple de faire tout cela à partir d’une XSD, directement fournie par Google…

On a par exemple la classe Geometry comme suit :

package fr.ippon.gmap.model.gmap; import javax.xml.bind.annotation.XmlElement; public class Geometry { @XmlElement private GeoPosition location; @XmlElement private Viewport viewport; @XmlElement private Viewport bounds; public GeoPosition getLocation() { return location; } }

Pour avoir toutes les informations sur les classes annotées, vous pouvez vous référerez au code qui est disponible sur GitHub à l’adresse : https://github.com/bpinel/restgmap

Le service et son test unitaire

Le reste du code est tout ce qu’il y a de plus standard. Et je vous laisse découvrir le service et les tests unitaires dans le projet git.


Vous avez trouvé cette publication utile? Cliquer sur
Ippon
Ippon est un cabinet de conseil en technologies, créé en 2002 par un sportif de Haut Niveau et un polytechnicien, avec pour ambition de devenir leader sur les solutions Digitales, Cloud et BigData.

Ippon accompagne les entreprises dans le développement et la transformation de leur système d’information avec des applications performantes et des solutions robustes.

Ippon propose une offre de services à 360° pour répondre à l’ensemble des besoins en innovation technologique : Conseil, Design, Développement, Hébergement et Formation.

Nous avons réalisé, en 2016, un chiffre d’affaires de 24 M€ en croissance organique de 20%. Nous sommes aujourd’hui un groupe international riche de plus de 300 consultants répartis en France, aux USA, en Australie et au Maroc.
FRANCE Website LinkedIn