Exposer un annuaire LDAP en Grails

le 11/03/2008 par Benjamin Magnan
Tags: Software Engineering

L'annuaire pages blanches est une fonctionnalité que l'on retrouve très fréquemment dans le portail intranet d'une société. Cet annuaire est l'outil qui vous fournit les informations sur vos collègues préférés lorsque vous en avez besoin. Les données pages blanches contiennent les données de référence de la société pour un certain nombre d'informations liées aux collaborateurs. Ainsi d'autres applications du système d'information souhaitent elles aussi les utiliser.
Une des solutions pour mettre à disposition ces données à un ensemble d'applications est d'interposer un " émissaire " au dessus de l'annuaire afin de mutualiser l'exposition de ses services.

Cet article a pour objectif de montrer un exemple de réalisation d'un émissaire au dessus d'un annuaire LDAP en utilisant Grails et les web services REST.

Niveau intermédiaire

**

Contexte

**

L'annuaire pages blanches est une fonctionnalité que l'on retrouve très fréquemment dans le portail intranet d'une société. Cet annuaire pages blanches est l'outil qui vous fournit les informations sur vos collègues préférés lorsque vous en avez besoin.

En règle générale cet annuaire se matérialise par un annuaire LDAP (Microsoft AD, Sun One Directory, ...) qui présente toutes ces informations de manière hiérarchique.

Comme le montre le schéma suivant notre annuaire LDAP est bien souvent " consommé " directement par l'application Intranet. Cette dernière accède aux données afin de les présenter et d'offrir aux collaborateurs des fonctions de manipulation (recherche, modification, ...).

L'Intranet utilise directement l'annuaire page blanche

Les données pages blanches contiennent les données de référence de la société pour un certain nombre d'informations liées aux collaborateurs. De ce fait d'autres applications du système d'information envisagent de les utiliser.
Pour répondre à ces nouveaux besoins d'intégration de l'annuaire il est indispensable de réfléchir à la manière dont les échanges auront lieux.
Une première approche serait que chacune de ces applications accèdent de manière directe à l'annuaire au travers de requêtes LDAP (comme le fait l'Intranet ci-dessus). Cette solution semble pourtant avoir quelques limitations :

  • Les applications clientes seraient fortement couplées à cet annuaire, voir même à la structure de l'annuaire
  • La logique de connexion serait dupliquée au niveau de chacune des applications clientes rendant la maintenance difficile
  • Les modifications et évolutions de l'annuaire deviendraient plus complexes

Il existe une meilleure solution pour répondre à ces enjeux, déjà exposée dans cet article : SOA par la pratique.

Pour revenir rapidement sur la solution montrée dans cet article, l'objectif est d'interposer un " émissaire " au dessus d'un système afin d'en exposer ses services à d'autres application.

En l'appliquant à notre cas nous obtenons le schéma suivant :

Un émissaire s'interpose entre les applications clientes et l'annuaire

Cette solution permet de :

  • Diminuer le couplage entre les applications clientes et l'annuaire

  • Ajouter de la logique métier dans l'émissaire pour traiter les données (filtrage, transformation, encodage, enrichissement...)

  • Faciliter la maintenance et l'évolutivité grâce à la mutualisation des services d'accès à l'annuaire

  • Permettre des modifications sur l'annuaire " en douceur " lorsque les besoins apparaissent puisque seules les couches inférieures de l'émissaire seront impactées (par exemple un chantier de refonte des pages blanches vers une technologie de base de données relationnelles).

Voyons maintenant comment implémenter simplement cet émissaire de services.

**

Implémentation de l'émissaire

**

Nous développerons ici des web services selon une architecture REST en utilisant une stack dite " légère ".
Ce choix se justifie par la motivation de commencer ce développement de manière " simple " et de l'agrémenter de fonctionnalités, d'outils lorsque le besoin s'en fait ressentir.

Pour ceux qui ne sont pas familier avec le modèle REST, je vous conseille de vous reporter au cahier OCTO : Services Web : choix architecturaux.

En termes d'outillage technique pour l'implémentation de l'émissaire, nous utiliserons le framework Grails. Vous trouverez une présentation rapide de ce framework dans un article précédent.

Ce framework peut être présenté rapidement comme un pendant de Rails pour Java.
Les principaux avantages de Grails pour implémenter notre émissaire sont :

  • L'initiation rapide d'une webapp Java

  • La mise à disposition d'abstractions facilitatrices

  • Un DSL pour l'exposition rapide de web services REST

  • Une API simple de lecture/écriture XML

  • L'intégration native avec du Java si besoin

Contrat d'interface

Nous allons développer un web service REST qui nous permet de récupérer les informations d'un collaborateur présentes dans l'annuaire.
La ressource au sens REST est donc le collaborateur accessible au travers de l'URI suivante :
http://{host}:{port}/rest-app/collaborateur/{collaborateuruid}

La représentation de cette ressource retournée par notre web service REST, pour une requête http de type GET, est un fragment XML (d'autres représentations sont possibles JSON, ...) :

Le web service REST met à profit les codes HTTP :

StatusDescription
200Succès, la représentation XML du collaborateur identifié par {collaborateuruid} est dans le body
404Il n'existe pas de collaborateur associé à l'uid {collaborateuruid}

Maintenant que nous avons défini notre contrat de service nous pouvons rentrer dans le détail de son implémentation.

Développement

La structure choisie pour l'émissaire est la suivante :

Nous allons utiliser le DSL REST fournis par Grails qui permet de lier les URI au code des controllers. Sur le schéma précédent le DSL REST est la brique de mapping REST plus la flèche vers le controller.

Ainsi dans le fichier UrlMapping.groovy il faut procéder de la façon suivante :

![](Grails-REST-UrlMapping.png)

Le code ci-dessus défini un certains nombres de mécanismes :

  • Les requêtes http vers l'URL http://{host}:{port}/rest-app/collaborateur/{collaborateuruid} seront traitées par le controller " collaborateur " (la classe CollaborateurController.groovy).

  • Chaque méthode http est traitée par une action du controller

  • Les requêtes GET seront traitées par l'action " getCollaborateur "

  • La définition d'une variable $collaborateuruid permet de mapper directement cette valeur dans un paramètre (nommé " collaborateuruid ") accessible dans le controller

Regardons maintenant ce que contient le controller Grails en charge du traitement des requêtes.

Comme vous pouvez le voir dans la méthode " generateCollaborateurXMLFragment ", afin de générer le fragment XML du body de la réponse nous utilisons une facilitée offerte par le langage Groovy : les MarkupBuilder. Ce module du langage Groovy s'appuie sur le pattern Builder. Si vous le souhaitez des informations complémentaires sont disponibles ici et ici.

Le controller s'appuie sur un Service Groovy afin de récupérer les informations du collaborateur identifié par le collaborateuruid dans l'annuaire pages blanches. A noter que ce service s'appuie sur le framework Spring LDAP pour implémenter toutes les fonctionnalités d'accès à l'annuaire.
L'injection du service dans le controller se fait via Spring en utilisant le pattern Convention over Configuration afin de simplifier l'écriture.

Test dans le navigateur

Il ne nous reste plus qu'à packager et déployer l'application web pour constater avec le navigateur les résultats que nous obtenons :
(A noter qu'un des bénéfices de l'approche REST est que pour le besoin de la démonstration visuelle d'un service en lecture un simple navigateur suffit)

Le cas nominal : Le collaborateuruid donné correspond à un collaborateur dans l'annuaire pages blanches

Le cas d'erreur : Le collaborateuruid donné ne correspond pas à un collaborateur dans l'annuaire pages blanches

En guise de conclusion

Nous venons ici de réaliser rapidement un premier service de notre émissaire. Ce service permet d'accéder en lecture aux informations d'un collaborateur de la société.
Il est désormais envisageable d'ajouter à cet émissaire de nouveaux services résultant d'une étude des besoins des applications clientes de l'annuaire pages blanches.

Du point de vue des applications clientes, un intranet par exemple, l'avantage de l'approche REST est que seul un client http est nécessaire pour récupérer la représentation des ressources. Pour manipuler les représentations des ressources, des parseurs peuvent être requis en plus de ce client http (XML, JSON, ...).

Si vous souhaitez recevoir le code complet de cet exemple et vous faire la main sur les services REST en Grails, demandez le moi à l'adresse suivante : bmagnan@octo.com.