Qu’est-ce que WSDL ?

WSDL est un langage XML qui décrit complètement un service web :

  • Les opérations disponibles
  • Les formats des messages (entrée/sortie)
  • Les protocoles de communication
  • L’emplacement du service

Structure d’un fichier WSDL

Un fichier WSDL se compose de 6 sections principales, de l’abstrait au concret :

definitions (racine)
    ├── types (schémas des données)
    ├── message (définition des messages)
    ├── portType (interface abstraite)
    ├── binding (protocole concret)
    └── service (point d'accès)

1. Definitions (Racine)

Élément racine qui englobe tout le document WSDL.

<definitions 
    name="BankingService"
    targetNamespace="http://www.example.com/banking"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://www.example.com/banking"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    <!-- Contenu du WSDL -->
    
</definitions>

Attributs importants :

  • name : Nom du service
  • targetNamespace : Namespace du service (URI unique)
  • Déclarations des namespaces utilisés

2. Types (Schémas des données)

Définit les types de données complexes utilisés par le service via XML Schema.

<types>
    <xsd:schema targetNamespace="http://www.example.com/banking">
        
        <!-- Type complexe : Compte -->
        <xsd:complexType name="Account">
            <xsd:sequence>
                <xsd:element name="accountNumber" type="xsd:string"/>
                <xsd:element name="accountType" type="xsd:string"/>
                <xsd:element name="balance" type="xsd:decimal"/>
            </xsd:sequence>
        </xsd:complexType>
        
        <!-- Type complexe : Transfert -->
        <xsd:complexType name="TransferRequest">
            <xsd:sequence>
                <xsd:element name="fromAccount" type="xsd:string"/>
                <xsd:element name="toAccount" type="xsd:string"/>
                <xsd:element name="amount" type="xsd:decimal"/>
                <xsd:element name="currency" type="xsd:string"/>
            </xsd:sequence>
        </xsd:complexType>
        
        <xsd:complexType name="TransferResponse">
            <xsd:sequence>
                <xsd:element name="transactionId" type="xsd:string"/>
                <xsd:element name="status" type="xsd:string"/>
                <xsd:element name="timestamp" type="xsd:dateTime"/>
            </xsd:sequence>
        </xsd:complexType>
        
        <!-- Type simple avec restriction -->
        <xsd:simpleType name="AccountStatus">
            <xsd:restriction base="xsd:string">
                <xsd:enumeration value="ACTIVE"/>
                <xsd:enumeration value="SUSPENDED"/>
                <xsd:enumeration value="CLOSED"/>
            </xsd:restriction>
        </xsd:simpleType>
        
    </xsd:schema>
</types>

Types XSD courants :

  • xsd:string : Chaîne de caractères
  • xsd:int / xsd:integer : Nombres entiers
  • xsd:decimal : Nombres décimaux
  • xsd:boolean : Booléen
  • xsd:dateTime : Date et heure
  • xsd:date : Date seulement

3. Message (Définition des messages)

Définit les messages échangés (paramètres et retours).

<!-- Message pour la requête de transfert -->
<message name="TransferFundsRequest">
    <part name="parameters" type="tns:TransferRequest"/>
</message>
 
<!-- Message pour la réponse de transfert -->
<message name="TransferFundsResponse">
    <part name="parameters" type="tns:TransferResponse"/>
</message>
 
<!-- Message pour obtenir le solde -->
<message name="GetBalanceRequest">
    <part name="accountNumber" type="xsd:string"/>
</message>
 
<message name="GetBalanceResponse">
    <part name="balance" type="xsd:decimal"/>
</message>
 
<!-- Message d'erreur -->
<message name="BankingFault">
    <part name="errorCode" type="xsd:string"/>
    <part name="errorMessage" type="xsd:string"/>
</message>

Éléments :

  • name : Nom unique du message
  • part : Partie du message (peut en avoir plusieurs)
    • name : Nom du paramètre
    • type : Type de donnée (référence à types ou XSD)
    • element : Alternative à type, référence un élément XML

4. PortType (Interface abstraite)

Définit l’interface du service : les opérations disponibles et leurs messages.

<portType name="BankingPortType">
    
    <!-- Opération Request-Response -->
    <operation name="TransferFunds">
        <documentation>Effectue un transfert entre deux comptes</documentation>
        <input message="tns:TransferFundsRequest"/>
        <output message="tns:TransferFundsResponse"/>
        <fault name="InvalidAccountFault" message="tns:BankingFault"/>
    </operation>
    
    <!-- Opération Request-Response simple -->
    <operation name="GetBalance">
        <documentation>Obtient le solde d'un compte</documentation>
        <input message="tns:GetBalanceRequest"/>
        <output message="tns:GetBalanceResponse"/>
    </operation>
    
    <!-- Opération One-Way (pas de réponse) -->
    <operation name="NotifyTransaction">
        <input message="tns:TransactionNotification"/>
    </operation>
    
</portType>

Patterns d’opération :

  1. Request-Response : input + output (le plus courant)
  2. One-way : input seulement (notification)
  3. Notification : output seulement (push du serveur)
  4. Solicit-Response : output + input (rare)

5. Binding (Protocole concret)

Définit comment les opérations sont transmises via un protocole (généralement SOAP).

<binding name="BankingSOAPBinding" type="tns:BankingPortType">
    
    <!-- Configuration SOAP globale -->
    <soap:binding 
        style="document" 
        transport="http://schemas.xmlsoap.org/soap/http"/>
    
    <!-- Binding de l'opération TransferFunds -->
    <operation name="TransferFunds">
        <soap:operation 
            soapAction="http://www.example.com/banking/TransferFunds"
            style="document"/>
        <input>
            <soap:body use="literal"/>
        </input>
        <output>
            <soap:body use="literal"/>
        </output>
        <fault name="InvalidAccountFault">
            <soap:fault name="InvalidAccountFault" use="literal"/>
        </fault>
    </operation>
    
    <!-- Binding de l'opération GetBalance -->
    <operation name="GetBalance">
        <soap:operation 
            soapAction="http://www.example.com/banking/GetBalance"
            style="document"/>
        <input>
            <soap:body use="literal"/>
        </input>
        <output>
            <soap:body use="literal"/>
        </output>
    </operation>
    
</binding>

Paramètres importants :

  • style : “document” ou “rpc”
  • transport : Protocole de transport (HTTP, SMTP, etc.)
  • soapAction : En-tête HTTP pour identifier l’opération
  • use : “literal” (respecte le schéma) ou “encoded”

6. Service (Point d’accès)

Définit où le service est accessible (URL concrète).

<service name="BankingService">
    
    <documentation>Service bancaire pour les opérations de compte</documentation>
    
    <port name="BankingSOAPPort" binding="tns:BankingSOAPBinding">
        <soap:address location="http://bank.example.com:8080/services/banking"/>
    </port>
    
    <!-- Peut avoir plusieurs ports pour différents bindings -->
    <port name="BankingHTTPPort" binding="tns:BankingHTTPBinding">
        <http:address location="http://bank.example.com:8080/api/banking"/>
    </port>
    
</service>

Éléments :

  • service : Conteneur pour les ports
  • port : Point d’accès spécifique
    • name : Nom du port
    • binding : Référence au binding utilisé
    • address : URL concrète du service

Exemple complet de WSDL

Service de gestion de bibliothèque avec opérations de recherche et emprunt :

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
    name="LibraryService"
    targetNamespace="http://www.example.com/library"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://www.example.com/library"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
    <!-- TYPES : Définition des structures de données -->
    <types>
        <xsd:schema targetNamespace="http://www.example.com/library">
            
            <!-- Type Book -->
            <xsd:complexType name="Book">
                <xsd:sequence>
                    <xsd:element name="isbn" type="xsd:string"/>
                    <xsd:element name="title" type="xsd:string"/>
                    <xsd:element name="author" type="xsd:string"/>
                    <xsd:element name="available" type="xsd:boolean"/>
                    <xsd:element name="publicationYear" type="xsd:int"/>
                </xsd:sequence>
            </xsd:complexType>
            
            <!-- Type BorrowRequest -->
            <xsd:complexType name="BorrowRequest">
                <xsd:sequence>
                    <xsd:element name="userId" type="xsd:string"/>
                    <xsd:element name="isbn" type="xsd:string"/>
                    <xsd:element name="durationDays" type="xsd:int"/>
                </xsd:sequence>
            </xsd:complexType>
            
            <!-- Type BorrowResponse -->
            <xsd:complexType name="BorrowResponse">
                <xsd:sequence>
                    <xsd:element name="borrowId" type="xsd:string"/>
                    <xsd:element name="dueDate" type="xsd:date"/>
                    <xsd:element name="success" type="xsd:boolean"/>
                </xsd:sequence>
            </xsd:complexType>
            
            <!-- Type ArrayOfBooks -->
            <xsd:complexType name="ArrayOfBooks">
                <xsd:sequence>
                    <xsd:element name="book" type="tns:Book" 
                                 minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
            </xsd:complexType>
            
        </xsd:schema>
    </types>
 
    <!-- MESSAGES : Définition des messages échangés -->
    
    <!-- Messages pour SearchBooks -->
    <message name="SearchBooksRequest">
        <part name="keyword" type="xsd:string"/>
    </message>
    
    <message name="SearchBooksResponse">
        <part name="books" type="tns:ArrayOfBooks"/>
    </message>
    
    <!-- Messages pour GetBookDetails -->
    <message name="GetBookDetailsRequest">
        <part name="isbn" type="xsd:string"/>
    </message>
    
    <message name="GetBookDetailsResponse">
        <part name="book" type="tns:Book"/>
    </message>
    
    <!-- Messages pour BorrowBook -->
    <message name="BorrowBookRequest">
        <part name="parameters" type="tns:BorrowRequest"/>
    </message>
    
    <message name="BorrowBookResponse">
        <part name="parameters" type="tns:BorrowResponse"/>
    </message>
    
    <!-- Message d'erreur -->
    <message name="LibraryFault">
        <part name="errorCode" type="xsd:string"/>
        <part name="errorMessage" type="xsd:string"/>
    </message>
 
    <!-- PORTTYPE : Interface abstraite du service -->
    <portType name="LibraryPortType">
        
        <operation name="SearchBooks">
            <documentation>Recherche des livres par mot-clé</documentation>
            <input message="tns:SearchBooksRequest"/>
            <output message="tns:SearchBooksResponse"/>
        </operation>
        
        <operation name="GetBookDetails">
            <documentation>Obtient les détails d'un livre par ISBN</documentation>
            <input message="tns:GetBookDetailsRequest"/>
            <output message="tns:GetBookDetailsResponse"/>
            <fault name="BookNotFoundFault" message="tns:LibraryFault"/>
        </operation>
        
        <operation name="BorrowBook">
            <documentation>Emprunte un livre</documentation>
            <input message="tns:BorrowBookRequest"/>
            <output message="tns:BorrowBookResponse"/>
            <fault name="BookUnavailableFault" message="tns:LibraryFault"/>
        </operation>
        
    </portType>
 
    <!-- BINDING : Liaison avec SOAP -->
    <binding name="LibrarySOAPBinding" type="tns:LibraryPortType">
        
        <soap:binding 
            style="document" 
            transport="http://schemas.xmlsoap.org/soap/http"/>
        
        <operation name="SearchBooks">
            <soap:operation 
                soapAction="http://www.example.com/library/SearchBooks"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
        
        <operation name="GetBookDetails">
            <soap:operation 
                soapAction="http://www.example.com/library/GetBookDetails"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
            <fault name="BookNotFoundFault">
                <soap:fault name="BookNotFoundFault" use="literal"/>
            </fault>
        </operation>
        
        <operation name="BorrowBook">
            <soap:operation 
                soapAction="http://www.example.com/library/BorrowBook"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
            <fault name="BookUnavailableFault">
                <soap:fault name="BookUnavailableFault" use="literal"/>
            </fault>
        </operation>
        
    </binding>
 
    <!-- SERVICE : Point d'accès concret -->
    <service name="LibraryService">
        <documentation>
            Service de gestion de bibliothèque permettant la recherche 
            et l'emprunt de livres
        </documentation>
        
        <port name="LibrarySOAPPort" binding="tns:LibrarySOAPBinding">
            <soap:address 
                location="http://library.example.com:8080/services/library"/>
        </port>
    </service>
 
</definitions>

Flux d’utilisation du WSDL

  1. Le client télécharge le WSDL
  2. Il génère le code client (proxy) à partir du WSDL
  3. Il appelle les opérations définies dans le portType
  4. Les messages sont formatés selon les types
  5. Ils sont transmis selon le binding (SOAP)
  6. Vers l’adresse définie dans service

Points clés à retenir

Hiérarchie logique :

Service (où ?) 
  └─> Port (comment accéder ?)
      └─> Binding (quel protocole ?)
          └─> PortType (quelles opérations ?)
              └─> Operations (quel flux ?)
                  └─> Messages (quelles données ?)
                      └─> Types (quelle structure ?)

Parties abstraites (réutilisables) :

  • types
  • message
  • portType

Parties concrètes (spécifiques) :

  • binding
  • service

Exercice : Écrire un WSDL

Service météo avec deux opérations :

  • GetCurrentTemperature(city: string) : decimal
  • GetForecast(city: string, days: int) : ArrayOfForecast
<?xml version="1.0" encoding="UTF-8"?>
<definitions 
    name="WeatherService"
    targetNamespace="http://www.example.com/weather"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://www.example.com/weather"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 
    <types>
        <xsd:schema targetNamespace="http://www.example.com/weather">
            
            <xsd:complexType name="Forecast">
                <xsd:sequence>
                    <xsd:element name="date" type="xsd:date"/>
                    <xsd:element name="minTemp" type="xsd:decimal"/>
                    <xsd:element name="maxTemp" type="xsd:decimal"/>
                    <xsd:element name="condition" type="xsd:string"/>
                </xsd:sequence>
            </xsd:complexType>
            
            <xsd:complexType name="ArrayOfForecast">
                <xsd:sequence>
                    <xsd:element name="forecast" type="tns:Forecast" 
                                 minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
            </xsd:complexType>
            
        </xsd:schema>
    </types>
 
    <message name="GetCurrentTemperatureRequest">
        <part name="city" type="xsd:string"/>
    </message>
    
    <message name="GetCurrentTemperatureResponse">
        <part name="temperature" type="xsd:decimal"/>
    </message>
    
    <message name="GetForecastRequest">
        <part name="city" type="xsd:string"/>
        <part name="days" type="xsd:int"/>
    </message>
    
    <message name="GetForecastResponse">
        <part name="forecasts" type="tns:ArrayOfForecast"/>
    </message>
 
    <portType name="WeatherPortType">
        
        <operation name="GetCurrentTemperature">
            <input message="tns:GetCurrentTemperatureRequest"/>
            <output message="tns:GetCurrentTemperatureResponse"/>
        </operation>
        
        <operation name="GetForecast">
            <input message="tns:GetForecastRequest"/>
            <output message="tns:GetForecastResponse"/>
        </operation>
        
    </portType>
 
    <binding name="WeatherSOAPBinding" type="tns:WeatherPortType">
        
        <soap:binding 
            style="document" 
            transport="http://schemas.xmlsoap.org/soap/http"/>
        
        <operation name="GetCurrentTemperature">
            <soap:operation 
                soapAction="http://www.example.com/weather/GetCurrentTemperature"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
        
        <operation name="GetForecast">
            <soap:operation 
                soapAction="http://www.example.com/weather/GetForecast"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
        
    </binding>
 
    <service name="WeatherService">
        <port name="WeatherSOAPPort" binding="tns:WeatherSOAPBinding">
            <soap:address location="http://weather.example.com/services/weather"/>
        </port>
    </service>
 
</definitions>