Exposer un annuaire LDAP en Grails

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 :

    Status

    Description

    200

    Succès, la représentation XML du collaborateur identifié par {collaborateuruid} est dans le body

    404

    Il 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 :


    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.

    11 commentaires sur “Exposer un annuaire LDAP en Grails”

  • Yeah très bon article ! Concis et précis avec un exemple complet.

  • Article intelligible même pour les gens qui ne sont pas des hard-codeurs.
    Bien joué.

  • Oui, bravo pour cet article très instructif et bien écrit.

  • Petite question, comment ca se passe, si la requête contient plusieurs paramètres ?

  • Pour répondre à ta question prenons l'exemple d'une ressource qui est la liste des collaborateurs de la société.
    Son URI est : http://{host}:{port}/rest-app/collaborateurs/

    On peut ajouter une fonction de recherche sur les collaborateurs selon deux paramètres : nom et prénom.

    L'URI de cette nouvelle ressource (le résultat d'une recherche) est donc par exemple :
    http://{host}:{port}/rest-app/collaborateurs/?prenom=liam&nom=gallagher

    Le résultat serait un document XML avec un ensemble d'éléments <collaborateur>...</collaborateur> qui correspondent aux paramètres.

    Regardons maintenant comment implémenter :

    Le DSL REST de Grails nous permet de 'binder' la ressource 'Collaborateurs' à l'action getCollaborateurs du controller Collaborateur :

    class UrlMappings {
    static mappings = {
    '/collaborateurs/'(controller:'collaborateur'){
    action = [GET:'getCollaborateurs']
    }

    ...
    }

    Pour traiter les paramètres de la requête, on utilise une autre facilité de Grails qui permet de rendre accessible les paramètres de la requête dans l'action du controller qui la traite.

    Ainsi dans CollaborateurController.groovy nous pourrons récupérer les valeurs des paramètres :

    ...
    def getCollaborateurs = {

    def prenom = params.prenom
    def nom = params.nom
    ?
    //traitement
    ...
    }

    ...

    Ensuite il faut :
    - requêter l'annuaire pages blanches selon les critères de recherche (nom et prénom)
    - construire la représentation XML du résultat
    - retourner le fragment XML de réponse (render)

  • En complément de la réponse de Benjamin ci-dessus.

    On peut aussi imaginer passer plusieurs 'paramètres' identifiants la ressource au sens REST dans une structure hiérarchique de l'URL.

    Par exemple une requête sur l'URL :
    monblog/2008/03/10/my_funky_blog_entry

    Avec le mapping Grails suivant :
    static mappings = {
    '/$blog/$year/$month/$day/$id'(controller:'blog', action:'show')
    }

    Qui décomposera l'URL pour transmettre à votre controlleur Grails les paramètres : [blog=monblog,year=2008,month=03,day=10,id=my_funky_blog_entry]

    Plus d'infos sur grails.org/doc/1.0.x/guid...

  • Désolé pour la réponse tardive, mais je n'ai pas reçu de notification de mise à jour...

    La première url contient des paramètres qui sont difficiles à indexer par des moteurs de recherche. Ce que reste évite normalement.

    La deuxième solution va nous obliger à avoir des mappings compliqué qui vont changer réguliàrement avec toutes les erreurs qui en découlent.

    Je pensais qu'il y a avait un manière plus sympa de passer des paramètres.

    J'ai vu que par exemple le CRUD en rest explotaient les différents méthode http :

    POST pour faire un create
    DELETE pour delete
    GET pour un READ
    ...

    Il n'y a pas moyen de faire quelque chose avec ?? ?

  • A noter le framework Gldapo, pour simplifier l'utilisation de spring-ldap en Groovy :

    ldaley.com/gldapo/

  • Cet article est intéressant , serait il possible d'avoir le code source ? Merci d'avance
  • Article intelligible même pour les gens qui ne sont pas des hard-codeurs. Bien joué.
  • Très bien article
    1. Laisser un commentaire

      Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


      Ce formulaire est protégé par Google Recaptcha