La première partie du sujet nous a permis d’introduire et présenter les Web Services. Nous avons ainsi introduit les notion suivantes : REST, WSDL, SOA, SOAP étant décrit dans des articles précédents, ainsi qu’une analyse de performance et de publication des Web Services.
Dans ce billet, nous allons voir maintenant comment réaliser l’implémentation d’un Web Service en 3 étapes :
- Définir les services de l’interface, par l’intermédiaire du WSDL
- Mettre en œuvre le service. Cela se fait avec le langage PHP.
- Déployer le service sur votre serveur Web
Définir les services de l’interface
Nous allons essayer d’écrire notre propre Web Service SOAP, qui réalisera l’addition / soustraction de deux entiers.
La première tâche est de créer un document WSDL décrivant notre service dans un format compréhensible par les clients.
Contenu
Dans la mesure où il s’agit d’un standard basé sur XML, la structure du WSDL vous semblera familière si vous avez une connaissance un peu approfondie du XML. Le fichier WSDL se divise en plusieurs parties : un ensemble d’éléments décrivant les types de données utilisés par le service, les messages que le service peut recevoir, ainsi que les liaisons SOAP associées à chaque message.
Le document WSDL commence par l’entête XML standard contenant un identificateur de version <?xml version="1.0"?>
, et que l’élément racine du document se nomme
<definitions>
. Ce dernier, donnant le nom du service, peut prendre plusieurs attributs facultatifs, qui le décrivent et déclarent les espaces de noms utilisés (namespaces) à utiliser dans le reste du document.
Ensuite, les types complexes nécessaires pour la définition de l’interface du service sont définis au sein de l’élément types
.
La section message
définie deux messages. Le premier est getResultRequest
, qui est une requête pour relayer le message getResult
et prend deux paramètres de type int
nommés : integer1
, integer2
et un paramètre de type string
nommée : operation
.
L’autre message est getResultResponse
, qui est la réponse au message getResult
, contenant une valeur de type int
, nommé result
.
La section portType
combine plusieurs éléments message
pour composer une opération : getResult
. Chaque opération se réfère à un message en entrée (input
) et à des messages en sortie (output
).
L’élément <binding>
décrit les spécifications concrètes de la manière dont le Web Service sera implémenté et définit la façon dont les messages doivent être transmis. Il spécifie également les espaces de noms et la valeur de l’entête soapAction
pour la méthode getResult
.
Enfin, le service
du document permet d’invoquer le service donné, ce qui sert à regrouper un ensemble de ports reliés (port
). La plupart du temps, c’est une URL invoquant un service SOAP.
Conseils de création
Voici quelques conseils pour créer votre document WSDL :
- Documentez toujours votre fichier WSDL, à la fois par le biais de la balise documentation, et en fournissant de la documentation dans un fichier externe au document WSDL
- Utilisez la Recommendation 2001 de XML Schema
- Utilisez l’élément
type
, dans tous les cas, ne faites pas référence aux types dans l’élément message.
Exemples
Je vais vous décrire pas à pas la construction du WSDL :
Partie 1 : Définitions
On commence par définir l’entête XML, puis l’élément definitions
.
<?xml version="1.0"?>
<!– partie 1 : Definitions –>
<definitions name=’getResult’
targetNamespace=’http://example.org/getResult’
xmlns:tns=’http://example.org/getResult’
xmlns:soap=’http://schemas.xmlsoap.org/wsdl/soap/’
xmlns:xsd=’http://www.w3.org/2001/XMLSchema’
xmlns:soapenc=’http://schemas.xmlsoap.org/soap/encoding/’
xmlns:wsdl=’http://schemas.xmlsoap.org/wsdl/’
xmlns=’http://schemas.xmlsoap.org/wsdl/’>
…
</definitions>
[/sourcecode]
Partie 2 : Message
…
<message name=’getResultRequest’>
<part name=’operation’ type=’xsd:string’/>
<part name=’integer1′ type=’xsd:int’/>
<part name=’integer2′ type=’xsd:int’/>
</message>
<message name=’getResultResponse’>
<part name=’result’ type=’xsd:string’/>
</message>
…
[/sourcecode]
Partie 3 : Port Type
Un port est simplement une suite d’opérations. Dans de nombreux langages de programmation, on appelle ceci une bibliothèque, un module ou une classe, mais dans le monde des Web Services, les points de connexion sont des ports, et la définition abstraite d’un port est appelée « Type de Port ».
Ici, nous créons la définition abstraite d’une procédure getResult
, en WSDL, dont l’input
est le message d’invocation de la méthode, et l’output
le message de retour de la méthode.
…
<portType name=’getResultPortType’>
<operation name=’getResult’>
<input message=’tns:getResultRequest’/>
<output message=’tns:getResultResponse’/>
</operation>
</portType>
…
[/sourcecode]
Partie 4 : Binding
Cette partie va nous permettre de rattacher le port à SOAP. Les types de ports sont indépendants du protocole.
Ici, nous utiliserons des requêtes SOAP (soap:binding
) de type RPC (style='rpc'
) via HTTP (transport='http://schemas.xmlsoap.org/soap/http'
) avec un encodage SOAP (encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'
).
…
<binding name=’getResultBinding’ type=’tns:getResultPortType’>
<soap:binding style=’rpc’ transport=’http://schemas.xmlsoap.org/soap/http’/>
<operation name=’getResult’>
<soap:operation soapAction=’urn:xmethods-delayed-quotes#getResult’/>
<input>
<soap:body use=’encoded’ namespace=’urn:xmethods-delayed-calcul’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’/>
</input>
<output>
<soap:body use=’encoded’ namespace=’urn:xmethods-delayed-calcul’
encodingStyle=’http://schemas.xmlsoap.org/soap/encoding/’/>
</output>
</operation>
</binding>
…
[/sourcecode]
Partie 5 : Service
Le service, déclaré ci-dessous, est défini avec une seule occurrence du port getResultPort
, ainsi que la définition de ce service. Le port est lié à la liaison (binding) getResultBinding
. Enfin, on donne l’information sur l’URL du point de sortie de l’application (ici l’URL du serveur SOAP).
…
<service name=’getResultService’>
<documentation>Retourne le résultat de l’opération </documentation>
<port name=’getResultPort’ binding=’getResultBinding’>
<soap:address location=’http://votre-adresse.com/samples/soap-server.php’/>
</port>
</service>
…
[/sourcecode]
Notez bien que si on ne trouve qu’un seul élément documentation
dans notre documentation, il faudra normalement en déclarer un pour chaque élément…
L’exemple montre bien le caractère verbeux de WSDL. Cependant, il est dans la pratique assez rare d’écrire le corps du fichier à la main : la plupart des environnements de développement savent en effet générer le fichier WSDL sur la base des caractéristiques du service développé.
Bien que vous soyez certainement capable de créer un document WSDL à la main, quelques outils permettent d’automatiser le processus de définition d’un Web Service avec WSDL. Par exemple:
- Omniopera: éditeur XSD, XML et WSDL basé sur GUI
- SOAP Toolkit de Microsoft: boîte à outils qui inclut des assistants pour la création d’interfaces COM à partir de définitions WSDL, et pour générer du WSDL à partir d’interfaces COM
- Zend Framework : Zend_Soap_AutoDiscover du Zend Framework est en mesure d’inspecter une classe au runtime et de générer à la volée le fichier WSDL correspondant.
Séparation et capitalisation
La facilité de maintenance est toujours au cœur des préoccupations des éditeurs. Il se révèle de ce point de vue très bénéfique de distinguer dans un contrat WSDL l’aspect Abstrait (ce qui est indépendant de la technologie et des protocoles) et l’aspect Concret (ce qui est dépendant). Cette distinction permet de joindre ou réutiliser des sous-parties de modèles WSDL et de les redéployer à loisir : le WSDL est classiquement séparable en trois parties :
- Les schémas d’une part, qui définissent les informations contenues dans les messages reçus/émis par le service : ces schémas peuvent préexister avant la notion de service car ils représentent les entités métier
- Une définition abstraite du service, contenant sa description sans les modalités d’implémentation (protocole et déploiement)
- Une partie concrète qui propose les liaisons d’une interface selon un certain format avec un protocole donné à une adresse donné
Dans ce but, WSDL permet d’importer des WSDL et des schémas. La partie concrète d’un contrat WSDL peut donc importer les définitions abstraites des services qui eux même peuvent importer des schémas. Cette démarche apporte une plus grande facilité de maintenance et de lisibilité.
Pour plus d’exemples ou de documentations, consultez :
C’est en rédigeant cet article que je me suis rendu compte qu’il y avait beaucoup de chose à dire sur la création d’un fichier WSDL. Si vous deviez retenir quelques termes de cet article les voici :
- Le WSDL sert à décrire :
- le protocole de communication (SOAP RPC ou SOAP orienté message)
- le format de messages requis pour communiquer avec ce service
- les méthodes que le client peut invoquer
- la localisation du service
-
Une description WSDL est un document XML qui commence par la balise
<definitions>
et qui contient les balises suivantes :<binding>
: définit le protocole à utiliser pour invoquer le service web<port>
: spécifie l’emplacement actuel du service<service>
: décrit un ensemble de points finaux du réseau
-
Un WSDL est décomposé en trois parties :`
- Schéma
- Définition Abstraite
- Projection Concrète
Suite à la longueur de cet article j’ai décidé de créer une troisième partie qui permettra de mettre en œuvre et déployer le Web Service. Vous trouverez également les différents fichiers à télécharger, ainsi qu’une démonstration de l’appel à la méthode getResult
.
Pensez-vous qu’il faut devenir un gourou du WSDL ? Quelle est votre démarche de production des WSDL ?