Interop, services web et utopie

Publié le 17 juin 2007 par Olivier Duval

Dans le cadre d’un projet d’intégration, je suis amené à faire usage d’un service Web qui me facilitera l’intégration d’un logiciel (sous Linux) à un extranet développé avec les technologies .NET : l’objectif d’une intégration étant de rendre transparentes certaines fonctionnalités d’un sous-système à l’utilisateur final, qui lui, ne voit que l’extranet.

Les services Web facilitent la vie pour toutes les parties : diminution du nombre d’API à maintenir grâce à la manière dont les échanges sont effectués (SOAP/REST, XML/JSON/...), passent les firewalls, etc, ...rien que de voir toutes les APIs qui fleurissent (au format REST voire SOAP), le buzz est devenu une réalité (économique ?).

Bref, en ce qui concerne cette intégration, il s’avère que la méthode appelée renvoie des types différents, c’est en fait une méthode générique, à laquelle on précise un service qui sera appelé sur le serveur (en fait une méthode du WSDL). Le seul problème c’est que les services sous-jacents renvoient des types différents : string[], int, ...le client qui appelle le service Web se fie à la signature (WSDL), et en .NET (ou Java), qui sont des langages typés, avoir des types de retour qui varient pose évidemment un problème. Le serveur a été développé en Perl, bien que la fonction soit ingénieuse, on se retrouve confronté à une contrainte du langage indépendamment du WS : Perl, Ruby, Python, etc, sont des langages interprétés et peu typés, C#, Java, ...des langages compilés et fortement typés, la conception et l’implémentation devraient prendre en compte ce type de contrainte pour faciliter justement l’interopérabilité.

Pour m’en sortir je vais certainement utiliser les hooks qui sont possibles grâce à SoapExtention ou exemple de cryptage, classe qui permet d’intercepter le message SOAP avant/après sérialisation/désérialisation, et modifier le message SOAP de retour, pour changer les types de retour afin qu’ils coïncident avec la signature de la méthode appelée réellement : string[] authenticateRemoteAppAndRun(...,string service, ...), donc transformer un int en string[] à la volée (modification du schéma XML…), tout ça pour corriger un défaut du serveur.

Autre attention qu’il faut avoir lors de développement de services Web : renvoyer dans la mesure du possible des types ou des structures simples. Dans un autre projet où l’on devait exporter des données vers un site, le client était cette fois-ci écrit en Python : difficulté de produire un proxy (pour générer des classes, a contrario de .NET ou Java qui ont des outils pour cela), nous étions ainsi dans l’obligation d’exporter des structures simples (arborescence peu profonde), car lire un schéma XML compliqué reste peu humain (heureusement qu’il existe XPath mais quand même ;)).

L’avantage de REST face à SOAP est sa simplicité dans les appels, mais aussi dans les retours qui peuvent prendre différentes formes : XML, JSON, HTML, en SOAP, tout est encapsulé dans un message SOAP, ce qui rajoute une couche de complexité pour la mise en oeuvre (et je ne parle pas des spécifications WS-*...)

Un article très intéressant sur le choix SOAP ou REST, qui résume bien mes cas d’utilisation, qui dépendent des technologies sous-jacentes utilisées.

Une piste à étudier, SOAP c’est bien mais en intra/inter .NET, REST me parait un bon compromis :

  • REST/POX WCF
  • ou en version old-school REST/POX Indigo

Et pour tous ceux qui ne pourront aller au Mix 07 (Miguel de Icaza y sera parait-il), je tenterai de faire un résumé de la journée dédiée aux webdesigners & co.

1 Serveur de listes Sympa : toutes les créations, suppressions de listes, ainsi que la gestion des abonnements doivent être transparentes pour les utilisateurs, qui ne connaissent que l’extranet.

2 string[] authenticateRemoteAppAndRun(...,string service, ...) : service sous-jacent a appelé, ce service est une méthode décrite également dans le WSDL