Web Services Description Language (WSDL)

Le langage de description des services web (WSDL), permet aux développeurs de créer un client pour accéder à un service web en fournissant toutes les informations nécessaires. Ainsi, la création d'un fichier WSDL, permet d'exposer un service web pour l'utilisation de celui-ci par quelqu'un d'autre. Le fichier donne des instructions sur la structure des messages que le service attend et qu'est-ce qu'il retourne.

A quoi sert un WSDL

La création d'un service se fait surtout dans le but que d'autres personnes l'utilisent. Pour l'utiliser, ils ont besoins de savoir quelles informations envoyer au service, quelles informations le service va leur renvoyer, et où trouver les services. On pourrait imaginer mettre ces informations dans un document word, mais il est plus judicieux d'utiliser un format standard compréhensible autant par les humains que par les machines. WSDL est ce format standard. Du fait qu'il soit un standard, au format XML, compréhensible par les machines, il permet de créer automatiquement le client et même le squelette d'un service.

XML Schema - Définir les données acceptées dans un message SOAP

La validation XML (XML Validation) est le processus qui garanti que la structure et le contenu d'un document XML, se conforme aux exigences requises. Au début, les DTD étaient utilisées mais elles n'étaient pas suffisantes (pas de prise en charge des namespaces, …), c'est donc les schémas XML qui sont responsables de cette validation. Outre le XML Schema, la spécification 2.0 des WSDL, supporte d'autres schémas (RELAX NG, Schematron)

Création d'un document WSDL

Un document WSDL est basé sur XML. L'élément racine 'definitions' englobe l'ensemble des définitions du service web. En partant du fond, on définit un service. Ce service utilise une liaison (binding) particulière qui est une implémentation d'un portType. Les portType définissent des opérations qui sont composées de messages. Les messages consistent en du XML définit dans la section types.

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
                           targetNamespace="http://ws.apache.org/axis2">

<wsdl:types>
</wsdl:types>

<wsdl:message name="createNewAdRequestMessage">
</wsdl:message>

<wsdl:portType name="ClassifiedServicePortType">
</wsdl:portType>

<wsdl:binding name="ClassifiedServiceBinding">
</wsdl:binding>

<wsdl:service name="ClassifiedService">
</wsdl:service>

</wsdl:definitions>

Etape 1: Définition des types

Les types sont stockés dans un schéma XML intégré au WSDL.

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
       xmlns:ns1="http://org.apache.axis2/xsd" 
       targetNamespace="http://ws.apache.org/axis2">
<wsdl:types>
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
         targetNamespace="http://org.apache.axis2/xsd" 
         elementFormDefault="unqualified" 
         attributeFormDefault="unqualified">

  <xs:element name="createNewAdRequest">
   <xs:complexType>
    <xs:sequence>
     <xs:element type="xs:string" name="content" />
     <xs:element type="xs:string" name="endDate" />
    </xs:sequence>
   </xs:complexType>
  </xs:element>

  <xs:element name="createNewAdResponse">
   <xs:complexType>
    <xs:sequence>
     <xs:element type="xs:int" name="newAdId" />
    </xs:sequence>
   </xs:complexType>
  </xs:element>
...
 </xs:schema>
</wsdl:types>

Etape 2: Création des messages

Une fois les types en place, il est possible de définir les messages envoyé et reçus dans l'enveloppe SOAP.

<wsdl:message name="createNewAdRequestMessage">
 <wsdl:part name="part1" element="ns1:createNewAdRequest" />
</wsdl:message>

<wsdl:message name="createNewAdResponseMessage">
 <wsdl:part name="part1" element="ns1:createNewAdResponse" />
</wsdl:message>

Chaque message possède un nom pour le référencer plus tard. Dans chaque message il faut définir les parties du message. A noter qu'avec la norme WSDL 2.0, une seule partie par message est autorisée, ce qui est le cas ici.

Chaque partie (part) possède un nom (name) ainsi que le nom de l'élément qui la constitue (element). Ce nom se réfère aux types définis précédemment. A noter que le nom est référencé par le préfixe ns:, le préfixe de l'espace de nom qui correspond au targetNamespace du schéma.

Etape 3: Définition des interfaces (portType)

Les messages seuls ne font rien. Il faut les associer à des opérations spécifiques. Celles-ci sont définies en interface (WSDL 2.0). En WSDL <2.0, on utilise portType. Comme les interfaces, le portType ne contient que des définitions et pas d'implémentation. Une opération est créée pour chaque fonction.

<wsdl:portType name="ClassifiedServicePortType">

 <wsdl:operation name="createNewAd">
  <wsdl:input message="tns:createNewAdRequestMessage" />
  <wsdl:output message="tns:createNewAdResponseMessage" />
 </wsdl:operation>

 //Opération one-way
 <wsdl:operation name="finalizeIssue">
  <wsdl:input message="tns:finalizeIssueRequestMessage" />
 </wsdl:operation>
</wsdl:portType>

Selon le type d'opérations (request/response vs one-way), on définit un message d'entrée (input) et un message de sortie (output). Comme les messages qui ont été définis plutôt l'on été avec l'espace de nom par défaut http://ws.apache.org/axis2, on crée l'espace de nom tns qui réfère celui-ci.

Définition de l'implémentation (bindings)

Si les portType sont comme les interfaces, les bindings sont l'implémentations de ces interfaces.

<wsdl:binding name="ClassifiedServiceBinding" type="tns:ClassifiedServicePortType">

 <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />

 <wsdl:operation name="createNewAd">
  <soap:operation soapAction="createNewAd" style="document" />
  <wsdl:input>
   <soap:body use="literal" namespace="http://daily-moon.com/classifieds" />
  </wsdl:input>
  <wsdl:output>
   <soap:body use="literal" namespace="http://daily-moon.com/classifieds" />
  </wsdl:output>
 </wsdl:operation>

 <wsdl:operation name="finalizeIssue">
  <soap:operation soapAction="finalizeIssue" style="document" />
  <wsdl:input>
   <soap:body use="literal" namespace="http://daily-moon.com/classifieds" />
  </wsdl:input>
 </wsdl:operation>
</wsdl:binding>	

Notons que le binding référence l'interface 'ClassifiedServicePortType' déjà créée. Cette implémentation est prévue pour des messages SOAP transitant par HTTP (soap:binding).

Pour chaque opération partageant le nom défini dans portType, une opération soap est rajoutée. Cet élément spécifie que c'est bien une opération soap. L'attribut soapAction (supprimé dans la spécification WSDL 2.0) permet de spécifier un en-tête HTTP envoyé avant le message SOAP.

Chaque opération définit aussi un message d'entrée et éventuellement de sortie avec des informations spécifiques à SOAP.

Etape 5: Définition du service

<wsdl:service name="ClassifiedService">

 <wsdl:port name="ClassifiedServicePort" binding="tns:ClassifiedServiceBinding">
  <soap:address location="http://127.0.0.1:8080/axis2/services/ClassifiedService" />
 </wsdl:port>

</wsdl:service>

Un service peut posséder plusieurs point finaux, chacun défini par son propre élément port qui correspond à une implémentation (binding) spécifique et inclus des informations sur comment y accéder. Ici, le port est accessible en SOAP à l'adresse http://...

Etape facultative mais recommandée: la documentation

Elle peut s'effectuer n'importe où dans le document au moyen de l'élément wsdl:document.