Débuter avec du savon

Informations générales

SOAP est l’acronyme de Simple Object Access Protocol qui définit un protocole utilisé pour échanger des données via un appel de procédure distante (RPC) avec d’autres services ou clients SOAP. Il est disponible en deux versions :

SOAP 1.2 obsolète SOAP 1.1, il est donc recommandé d’utiliser SOAP 1.2 si possible.

Il est souvent construit sur HTTP/S et rarement sur SMTP ou FTP, bien qu’il le prenne en charge selon le protocole. Bien que HTTP soit souvent utilisé comme protocole de transport sous-jacent, SOAP n’en utilise qu’un sous-ensemble limité. Pour envoyer des requêtes, il s’appuie presque entièrement sur l’opération “POST” de HTTP. Les invocations GET sont théoriquement possibles depuis la version 1.2, bien que le document doive être passé en tant que paramètre URI et puisse donc dépasser une limite d’environ 3000 caractères qui est rejetée par la plupart des frameworks. De plus, les paramètres liés à la sécurité sont généralement définis dans un en-tête SOAP spécial.

Bien que SOAP et [REST][2] soient appelés services Web, ils sont de nature très différente. Certains frameworks font la distinction entre WS (pour les services basés sur SOAP) et RS (pour les services basés sur REST).

Le tableau suivant donne un bref aperçu des différences entre les deux types de services Web.

Aspect SAVON REPOS
Norme SOAP, WSDL Pas de norme, juste un style architectural
Adressage des ressources Indirect via les opérations SOAP via des identifiants de ressources uniques (URI)
Gestion des erreurs Message d’erreur SOAP Codes de réponse d’erreur HTTP et éventuellement corps de réponse
Représentation des données XML tous les encodages disponibles en HTTP
Utilisation HTTP Comme protocole de transport Actions sur les ressources (CRUD) mappées sur les méthodes HTTP (GET, POST, PUT, DELETE, …)
Accompagnement transactionnel via l’en-tête SOAP en modélisant une transaction comme une ressource
État Avec état (l’action SOAP fait partie de l’application) Sans état (requêtes autonomes)
Découverte de services UDDI/WSDL Aucun en fait ; L’URI de démarrage de l’API doit cependant renvoyer une liste de sous-API
Méthode À l’intérieur du corps du savon Méthode HTTP
Arguments de méthode Défini par le schéma XML dans le WSDL Soit via des en-têtes HTTP ou des paramètres de chemin/requête ou de matrice dans l’URI
Transition d’état Difficile à déterminer car non directement basé sur des données Appel d’URI suivant
Prise en charge de la mise en cache Mise en cache souvent non souhaitée, Simple tel que défini par HTTP

DU SAVON

Une requête SOAP consiste en une enveloppe SOAP qui doit contenir un élément de corps et peut contenir un élément d’en-tête facultatif. L’élément d’en-tête est utilisé pour transmettre certaines configurations au service, par exemple WS-Security peut définir que le message est chiffré ou WS-Coordination/WS -Transaction peut définir que le message doit être exécuté dans une transaction.

Une simple requête SOAP 1.2 via HTTP qui ajoute deux valeurs peut ressembler à ceci :

POST /calculator HTTP/1.1
Host: http://example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 224

<?xml version="1.0"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
 <env:Body>
  <m:AddValues xmlns:m="http://example.org/calculator">
   <m:FirstValue>1</m:FirstValue>
   <m:SecondValue>2</m:SecondValue>
  </m:AddValues>
 </env:Body>
</env:Envelope>

Une réponse à l’exemple de requête ci-dessus peut ressembler à ceci

HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 329

<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
               soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
 <soap:Body xmlns:m="http://www.example.org/calculator">
  <m:AddValuesResponse>
   <m:Result>3</m:Result>
  </m:AddValuesResponse>
 </soap:Body>
</soap:Envelope>

L’exemple ci-dessus définit une requête qui invoque la méthode AddValues avec deux arguments, FirstValue défini sur 1 et SecondValue défini sur 2. La requête a abouti à une exécution de cette méthode sur le serveur SOAP distant qui a calculé une valeur de 3 en conséquence qui est encapsulée dans un élément de réponse séparé, qui par convention est souvent le nom de la méthode invoquée plus une chaîne Response de fin afin que toute personne qui inspecte la réponse puisse conclure que cela est la réponse d’une précédente invocation de la méthode AddValue.

Différences entre SOAP 1.1 et 1.2

SOAP 1.2 autorise d’autres protocoles de transport que HTTP tant que le cadre de liaison est pris en charge par le protocole.

SOAP 1.1 est basé sur XML 1.0, tandis que 1.2 est basé sur XML Infoset qui permet de sérialiser les messages SOAP avec d’autres sérialiseurs puis le sérialiseur XML 1.0 par défaut utilisé par SOAP 1.1. Cela permet, par exemple, de sérialiser les messages sous forme de messages binaires et donc d’éviter une surcharge de la nature XML du message. En plus de cela, le mécanisme de sérialisation du protocole sous-jacent utilisé peut être déterminé via la liaison de données.

L’aspect interopérabilité a également été favorisé avec SOAP 1.2 en définissant un modèle de traitement plus spécifique que son prédécesseur qui a éliminé de nombreuses possibilités d’interprétation. SOAP with Attachment API (SAAJ), qui permet d’opérer sur les messages SOAP 1.1 et 1.2, a aidé de nombreux implémenteurs de framework à traiter et créer des messages.

Le W3C a publié un bref aperçu des principaux changements entre SOAP 1.1 et 1.2

Interopérabilité des services Web

Web Service Interoperability (également connu sous le nom de WS-I) est une directive d’interopérabilité régie par certaines entreprises bien connues telles qu’IBM, Microsoft, Oracle et HP pour ne citer qu’elles quelques. Ces directives, entre autres, recommandent d’utiliser un seul élément racine dans le corps SOAP, même si SOAP permet de contenir plusieurs éléments dans le corps.

WS-I se compose de

  • Profil de base WS-I alias WSI-BP
  • Profil de sécurité de base WS-I
  • Profil de liaison de savon simple

WSI-BP est disponible en 4 versions différentes v1.0 (2004), v1.1 ( 2006), [v1.2 (2010)](http://ws-i.org/profiles/BasicProfile-1.2- 2010-11-09.html), v2.0 (2010) et définit les directives d’interopérabilité pour le service Web de base spécifications telles que SOAP, WSDL et UDDI. Grâce à l’utilisation du langage de description de services Web (WSDL), les services SOAP peuvent décrire leurs opérations et méthodes prises en charge dans un ensemble cohérent à d’autres points de terminaison. WSI-BP utilise WSDL pour définir un ensemble plus restreint que le schéma WSDL ou SOAP complet définirait et élimine ainsi une partie de l’ambiguïté dans la spécification elle-même et améliore ainsi l’interopérabilité entre les points de terminaison.

#WSDL

Afin d’annoncer les opérations SOAP disponibles, leurs paramètres ainsi que les points de terminaison respectifs à invoquer pour les clients, un autre document basé sur XML est utilisé appelé Web Services Description Language ou WSDL en abrégé.

WSDL décrit le point de terminaison de service, la liaison des messages SOAP aux opérations, l’interface des opérations ainsi que leurs types aux clients. WSDL est, comme SOAP, disponible en 2 versions qui diffèrent légèrement dans leur syntaxe bien qu’elles expriment presque la même sémantique pour le client.

WSDL 1.1

Une description WSDL 1.1 contient une section service, une section binding, une section portType et une section message. Il peut en outre importer ou définir des schémas dans le fichier WSDL, comme le montre un exemple de fichier WSDL qui correspond à l’exemple de calculatrice illustré ci-dessus :

<wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema"
                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:calc="http://example.org/calculator"
                  xmlns:tns="http://example.org/calculatorService"
                  targetNamespace="http://example.org/calculatorService">

    <!--
      Abstract type definitions
    -->

    <wsdl:types>
        <!--
        <xs:schema>
            <xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
        </xs:schema>
        -->
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:tns="http://example.org/calculator"
                   targetNamespace="http://example.org/calculator"
                   elementFormDefault="qualified"
                   attributeFormDefault="qualified">

            <xs:element name="AddValuesRequest" type="tns:AddValuesType" />
            <xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />

            <xs:complexType name="AddValuesType">
                <xs:sequence>
                    <xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                    <xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                </xs:sequence>
            </xs:complexType>

            <xs:complexType name="AddValuesResponseType">
                <xs:sequence minOccurs="1" maxOccurs="1">
                    <xs:element name="Result" type="xs:int" />
                </xs:sequence>
            </xs:complexType>

            <xs:attribute name="Timestamp" type="xs:dateTime" />
            <xs:element name="CalculationFailure">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="ErrorCode" type="xs:int" />
                        <xs:element name="Reason" type="xs:string" />
                    </xs:sequence>
                    <xs:attribute ref="tns:Timestamp" use="required" />
                </xs:complexType>
            </xs:element>

        </xs:schema>
    </wsdl:types>

    <!--
        Abstract message definitions
    -->

    <wsdl:message name="AddValuesRequest">
        <wsdl:part name="in" element="calc:AddValuesRequest" />
    </wsdl:message>
    <wsdl:message name="AddValuesResponse">
        <wsdl:part name="out" element="calc:AddValuesResponse" />
    </wsdl:message>
    <wsdl:message name="CalculationFault">
        <wsdl:part name="fault" element="calc:CalculationFailure" />
    </wsdl:message>

    <!--
        Abstract portType / interface definition
    -->

    <wsdl:portType name="CalculatorEndpoint">
        <wsdl:operation name="AddValues">
            <wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
            <wsdl:input message="tns:AddValuesRequest" />
            <wsdl:output message="tns:AddValuesResponse" />
            <wsdl:fault name="CalculationFault" message="tns:CalculationFault" />
        </wsdl:operation>
    </wsdl:portType>

    <!--
      Concrete binding definition
    -->

    <wsdl:binding name="CalculatorBinding" type="tns:CalculatorEndpoint">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="AddValues">
            <soap:operation soapAction="http://example.org/calculator/AddValuesMessage" />
            <wsdl:input>
                <soap:body parts="in" use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body parts="out" use="literal" />
            </wsdl:output>
            <wsdl:fault name="CalculationFault">
                <soap:fault name="CalculationFault" use="literal" />
            </wsdl:fault>
        </wsdl:operation>
    </wsdl:binding>

    <!--
        Concrete service definition
    -->

    <wsdl:service name="CalculatorService">
        <wsdl:port name="CalculatorServicePort" binding="tns:CalculatorBinding">
            <soap:address location="http://localhost:8080/services/calculator" />
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>

Une section “service” définit les points de terminaison concrets que le service écoutera pour les requêtes entrantes. La section binding lie une opération à un style concret et définit les formats de message que le serveur attend ou que le client peut attendre.

La section abstraite est composée d’un bloc portType qui définit les opérations offertes par le service et quels messages sont échangés. Les messages sont spécifiés dans leur bloc on et liés aux types de schéma dont les arguments et les valeurs de retour sont des instances. Les messages peuvent déclarer des paramètres ou renvoyer des valeurs pour être in, out ou inout. Alors que les deux premiers sont assez simples à appréhender, le second imite le comportement des arguments passés par référence. Comme le passage par référence n’est pas pris en charge dans certains langages, cet effet est souvent simulé via certains gestionnaires.

WSDL 2.0

La même calculatrice peut être décrite dans WSDL 2.0 comme ceci :

<?xml version="1.0" encoding="utf-8" ?>
<wsdl:description xmlns:xs="http://www.w3.org/2001/XMLSchema"
                  xmlns:wsdl="http://www.w3.org/ns/wsdl"
                  xmlns:soap="http://www.w3.org/ns/wsdl/soap"
                  xmlns:calc="http://example.org/calculator"
                  xmlns:tns="http://example.org/calculatorService"
                  targetNamespace="http://example.org/calculatorService">

    <!--
      Abstract type definitions
    -->

    <wsdl:types>
        <!--
        <xs:schema>
            <xs:import namespace="http://example.org/calculator" schemaLocation="calc/calculator.xsd" />
        </xs:schema>
        -->
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:tns="http://example.org/calculator"
                   targetNamespace="http://example.org/calculator"
                   elementFormDefault="qualified"
                   attributeFormDefault="qualified">

            <xs:element name="AddValuesRequest" type="tns:AddValuesType" />
            <xs:element name="AddValuesResponse" type="tns:AddValuesResponseType" />

            <xs:complexType name="AddValuesType">
                <xs:sequence>
                    <xs:element name="FirstValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                    <xs:element name="SecondValue" type="xs:int" minOccurs="1" maxOccurs="1" />
                </xs:sequence>
            </xs:complexType>

            <xs:complexType name="AddValuesResponseType">
                <xs:sequence minOccurs="1" maxOccurs="1">
                    <xs:element name="Result" type="xs:int" />
                </xs:sequence>
            </xs:complexType>

            <xs:attribute name="Timestamp" type="xs:dateTime" />
            <xs:element name="CalculationFault">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="ErrorCode" type="xs:int" />
                        <xs:element name="Reason" type="xs:string" />
                    </xs:sequence>
                    <xs:attribute ref="tns:Timestamp" use="required" />
                </xs:complexType>
            </xs:element>

        </xs:schema>
    </wsdl:types>

    <!--
        Abstract interface
    -->

    <wsdl:interface name="CalculatorInterface">
        <wsdl:fault name="fault" element="calc:CalculationFault" />
        <wsdl:operation name="AddValues" pattern="http://www.w3.org/ns/wsdl/in-out" style="http://www.w3.org/ns/wsdl/style/iri" wsdl:safe="true">
            <wsdl:documentation>Adds up passed values and returns the result</wsdl:documentation>
            <wsdl:input messageLabel="in" element="calc:AddValuesRequest" />
            <wsdl:output messageLabel="out" element="calc:AddValuesResponse" />
            <wsdl:outfault messageLabel="fault" ref="tns:fault" />
        </wsdl:operation>
    </wsdl:interface>

    <!--
        Concrete binding definition
    -->

    <wsdl:binding name="CalculatorBinding" interface="tns:CalculatorInterface" type="http://www.w3.org/ns/wsdl/soap" soap:protocol="http://www.w3.org/2003/05/soap/bindings/HTTP/">
        <wsdl:operation ref="tns:AddValues" soap:mep="http://www.w3.org/2003/05/soap/mep/soap-response" />
        <wsdl:fault ref="tns:fault" soap:code="soap:Sender" />
    </wsdl:binding>

    <!--
        Concrete service definition
    -->

    <wsdl:service name="CalculatorService" interface="tns:CalculatorInterface">
        <wsdl:endpoint name="CalculatorEndpoint" binding="tns:CalculatorBinding" address="http://localhost:8080/services/calculator" />
    </wsdl:service>

</wsdl:description>

Différences entre WSDL 1.1 et 2.0

Un aperçu graphique des différences entre les deux versions peut être vu dans l’image ci-dessous.

[![entrez la description de l’image ici][1]]1

Comme on peut le voir sur l’image, la section “message” a été supprimée et est maintenant contenue dans la section “interface”. De plus, certains éléments ont été renommés, d’autres ont une syntaxe différente, mais en général, les deux versions WSDL font essentiellement la même chose, la version 2.0 nécessitant un peu moins de temps d’écriture par rapport à la 1.1.

Outre la moindre empreinte sur la définition de services basés sur SOAP via WSDL 2.0, la nouvelle version fournit également des capacités de définition de services REST via WSDL 2.0 ou même Les WADL ne sont PAS recommandés pour les services RESTful car ils contredisent l’idée réelle qui les sous-tend.

Quel style préférer

La section de liaison WSDL décrit comment le service est lié au protocole de messagerie SOAP. L’exemple ci-dessus utilisait document comme style de liaison, ce qui permet de structurer le corps SOAP de la manière nous voulons tant que la sortie résultante est une instance XML valide. Il s’agit du style de liaison par défaut, souvent appelé “style orienté message”.

Contrairement au style document, les corps de requête de style RPC doivent contenir à la fois le nom de l’opération et l’ensemble des paramètres de la méthode. La structure de l’instance XML est donc prédéfinie et ne peut pas être modifiée.

En plus du style de liaison, la section de liaison définit également un modèle de traduction pour les liaisons aux messages SOAP au nom de literal ou encoded. La différence entre les deux est que le modèle “littéral” doit se conformer à une structure XSD définie par l’utilisateur, qui peut être utilisée pour valider les requêtes et les réponses, tandis que le modèle “encodé” doit utiliser des types de données XSD comme “xs : entier”. ouxs:string` mais en échange ne doit donc pas se conformer à un schéma défini par l’utilisateur. Cela rend cependant plus difficile la validation du corps du message ou la transformation du message via XSLT dans un autre format.

La combinaison du style de liaison avec le modèle d’utilisation permet en fait 4 résultats de message différents. Une 5ème entrée est ajoutée à la liste qui est couramment utilisée (bien que ne faisant pas vraiment partie de la norme).

  • RPC / encodé
  • RPC / littéral
  • Document / encodé
  • Document / littéral
  • Document / littéral (encapsulé)

Dans le style de messagerie document/littéral, il existe un modèle appelé document enveloppé/littéral. Ceci n’est qu’un modèle et ne fait pas partie de la spécification WSDL. Ce modèle est mentionné dans JSR 224 (JAX-WS : API Java pour les services Web basés sur XML). (Source)

La section ci-dessous donne un aperçu des différences concernant WSDL ou la déclaration de schéma et leur impact sur le format de message SOAP résultant sur la modification du style de liaison ou de l’utilisation des définitions de modèle.

RPC / encodé

WSDL :

...
<wsdl:message name="AddValues">
  <wsdl:part name="FirstValue" type="xsd:int" />
  <wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="Result" type="xsd:int" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'RPC' and use to 'encoded' -->
...

Demande SOAP

<soap:envelope>
  <soap:body>
    <AddValues>
      <FirstValue xsi:type="xsd:int">1</FirstValue>
      <SecondValue xsi:type="xsd:int">2</SecondValue>
    </AddValues>
  </soap:body>
</soap:envelope>

Réponse SOAP

<soap:envelope>
  <soap:body>
    <AddValuesResponse>
      <Result xsi:type="xsd:int">3</Result>
    </AddValuesResponse>
  </soap:body>
</soap:envelope>

Avantages

  • WSDL simple
  • Nom de l’opération et éléments disponibles dans la requête et la réponse

Les inconvénients

  • Déclaration explicite des types XSI
  • Difficile à valider
  • Non conforme WS-I

RPC / littéral

WSDL :

...
<wsdl:message name="AddValues">
  <wsdl:part name="FirstValue" type="xsd:int" />
  <wsdl:part name="SecondValue" type="xsd:int" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="Result" type="xsd:int" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'RPC' and use to 'literal' -->
...

Demande SOAP

<soap:envelope>
  <soap:body>
    <AddValues>
      <FirstValue>1</FirstValue>
      <SecondValue>2</SecondValue>
    </AddValues>
  </soap:body>
</soap:envelope>

Réponse SOAP

<soap:envelope>
  <soap:body>
    <AddValuesResult>
      <Result>3</Result>
    </AddValuesResult>
  </soap:body>
</soap:envelope>

Avantages

  • WSDL simple
  • Nom de l’opération et éléments disponibles dans la requête et la réponse
  • Aucune spécification de type XSI nécessaire
  • Conforme WS-I

Les inconvénients

  • Difficile à valider

Document / encodé

N’a aucun sens donc omis.

Document / littéral

WSDL :

...
<types>
  <schema>
    <element name="FirstValueElement" type="xsd:int" />
    <element name="SecondValueElement" type="xsd:int" />
    <element name="ResultValueElement" type="xsd:int" />
  </schema>
</types>

<wsdl:message name="AddValues">
  <wsdl:part name="FirstValue" element="FirstValueElement" />
  <wsdl:part name="SecondValue" element="SecondValueElement" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="Result" element="ResultValueElement" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'Document' and use to 'literal' -->
...

Demande SOAP

<soap:envelope>
  <soap:body>
    <FirstValueElement>1</FirstValueElement>
    <SecondValueElement>2</SecondValueElement>
  </soap:body>
</soap:envelope>

Réponse SOAP

<soap:envelope>
  <soap:body>
    <ResultElement>3</ResultElement>
  </soap:body>
</soap:envelope>

Avantages

  • Pas d’encodage de type XSI
  • Capable de valider le corps
  • Conformité WS-I avec restrictions

Les inconvénients

  • WSDL est plus compliqué en raison de la définition XSD supplémentaire
  • Le nom de l’opération est perdu
  • WS-I n’autorise qu’un seul enfant dans le corps SOAP

Document / littéral (encapsulé)

WSDL :

...
<types>
  <schema>
    <element name="AddValues">
      <complexType>
        <sequence>
          <element name="FirstValue" type="xsd:int" />
          <element name="SecondValue" type="xsd:int" />
        </sequence>
      </complexType>
    </element>
    <element name="AddValuesResponse">
      <complexType>
        <sequence>
          <element name="ResultValue" type="xsd:int" />
        </sequence>
      </complexType>
    </element>
  </schema>
</types>

<wsdl:message name="AddValues">
  <wsdl:part name="in" element="AddValues" />
</wsdl:message>
<wsdl:message name="AddValuesResponse">
  <wsdl:part name="out" element="AddValuesResponse" />
</wsdl:message>

<wsdl:portType name="CalculatorEndpoint">
  <wsdl:operation="AddValues">
    <wsdl:input message="AddValues" />
    <wsdl:output message="AddValuesResponse" />
  </wsdl:operation>
</wsdl:portType>

<!-- binding style set to 'Document' and use to 'literal' -->
...

Demande SOAP

<soap:envelope>
  <soap:body>
    <AddValues>
      <FirstValue>1</FirstValue>
      <SecondValue>2</SecondValue>
    </AddValues>
  </soap:body>
</soap:envelope>

Réponse SOAP

<soap:envelope>
  <soap:body>
    <AddValuesResponse>
      <Result>3</Result>
    </AddValuesResponse>
  </soap:body>
</soap:envelope>

Avantages

  • Pas d’encodage de type XSI
  • Capable de valider le corps
  • Nom de l’opération et éléments disponibles dans la requête et la réponse
  • Conforme WS-I

Les inconvénients

  • WSDL est plus compliqué en raison de la définition XSD supplémentaire

#UDDI

Universal Description, Discovery and Integration (UDDI) est une initiative ouverte de l’industrie créée en 2000 qui agit comme un registre de pages jaunes basé sur XML pour les services Web qui aide à trouver des services qui résolvent des tâches spécifiques. Afin de trouver un service approprié, un service doit d’abord être enregistré auprès d’un registre de services Web tel que l’UDDI.

UDDI fonctionne sur l’échange de messages SOAP et donne accès aux documents WSDL qui peuvent être utilisés pour appeler le service Web réel.

L’UDDI fournit des critères de recherche tels que

  • identifiant d’entreprise
  • nom commercial
  • zone de commerce
  • Catégorie Business
  • type de service par nom
  • URL de découverte

Cependant, un gros inconvénient de l’UDDI actuel est qu’il ne permet d’utiliser qu’un seul critère dans une instruction de recherche. Certains implémenteurs ont donc modularisé leurs implémentations UDDI pour permettre aux requêtes de générer plusieurs UDDI simultanément, puis d’agréger les résultats renvoyés.

Dans la pratique, cependant, UDDI n’est pas souvent utilisé. Certains disent même que l’UDDI est mort depuis qu’IBM, Microsoft et SAP [ont arrêté leurs services UDDI en 2005](https://web.archive.org/web/20070704154230/http://www.theserverside.net/news/ thread.tss?thread_id=38136).

Remarques supplémentaires :

SOAP/WSDL fournit une large gamme d’outils et permet également de générer dynamiquement des classes stub pour les clients et les serveurs, car le type de messages et de données échangés est bien défini via les schémas XSD intégrés ou liés.

Bien que WSDL 2.0 ait moins de surcharge de définition des services Web, certains langages n’ont toujours pas adopté la nouvelle norme. C’est à dire. en Java, les outils populaires tels que wsimport (d’Oracle/Sun) ou wsdl2java (d’Apache CXF) ne sont pas capables de gérer correctement les descriptions WSDL 2.0. Par conséquent, pour des raisons de compatibilité, il est toujours recommandé d’utiliser WSDL 1.1. Si vous avez besoin de développer un service SOAP basé sur WSDL 2.0 en Java, consultez le projet wsdl2javadu projet Apache Axis2.

Cependant, les plus populaires de nos jours sont soit les services API basés sur HTTP, qui mélangent des invocations d’opérations HTTP avec des URI propres et compréhensibles par l’homme et certaines personnalisations du protocole afin de faire leur travail, soit des services basés sur [REST][2], qui sont entièrement conformes aux recommandations réelles, ou propres protocoles au niveau de l’octet, comme par exemple OFTP2.

SOAP est toujours utile de nos jours si vous ne pouvez pas mapper votre tâche directement sur des ressources, comme le font les services de base HTTP/REST, car la tâche à remplir représente naturellement une action ou doit définir une certaine sémantique de transaction. De plus, si vous ne disposez pas des ressources nécessaires pour définir ou implémenter votre propre protocole, vous feriez probablement mieux d’utiliser SOAP. SOAP est particulièrement utile si vous devez gérer l’orchestration car la description WSDL en combinaison avec UDDI permet de combiner des services de manière dynamique.

[1] : http://i.stack.imgur.com/MNNAI.png [2] : https://www.wikiod.com/fr/rest/commencer-avec-le-repos#REST sur HTTP

Création d’un service Web simple et de clients avec JAX-WS (document / littéral)

Ceci est le répertoire du projet.

[![Répertoire du projet][1]][1]

  1. Une interface de point de terminaison de service

Nous allons d’abord créer une interface de point de terminaison de service. L’annotation javax.jws.WebService @WebService définit la classe en tant que point de terminaison de service Web.

<pré> importer javax.jws.WebMethod ; importer javax.jws.WebService ; importer javax.jws.soap.SOAPBinding ; importer javax.jws.soap.SOAPBinding.Style ; importer javax.jws.soap.SOAPBinding.Use ;

// Interface de service avec personnalisation de l’espace de noms cible @WebService(targetNamespace = “http://hello-soap/ws”) @SOAPBinding(style = Style.DOCUMENT, use=Use.LITERAL) //facultatif interface publique HelloSoap {

@WebMethod String getHelloSoap(String name);

}

  1. Mise en œuvre du point de terminaison de service (SEI)

Ensuite, nous allons créer une implémentation de point de terminaison de service. Nous allons créer une interface explicite en ajoutant l’élément endpointInterface à l’annotation @WebService dans la classe d’implémentation. Voici un ensemble de règles 28.1.1 Exigences d’un point de terminaison JAX-WS que les points de terminaison JAX-WS doivent suivre. La méthode getHelloSoap renvoie un message d’accueil au client avec le nom qui lui est transmis.

<pré> importer javax.jws.WebService ;

// Implémentation de service personnalisée (portName,serviceName,targetNamespace sont facultatifs)

@WebService(portName = “HelloSoapPort”, serviceName = “HelloSoapService”, endpointInterface = “com.wonderland.hellosoap.HelloSoap”, targetNamespace = “http://hello-soap/ws”) classe publique HelloSoapImpl implémente HelloSoap {

@Override
public String getHelloSoap(String name) {
    return "[JAX-WS] Hello : " + name;
}

}

  1. Éditeur de point de terminaison de service Web

<pré> importer javax.xml.ws.Endpoint ;

classe publique HelloSoapPublisher {

public static void main(String[] args) {
    // creating web service endpoint publisher
    Endpoint.publish("http://localhost:9000/ws/hello-soap", new HelloSoapImpl());
}

}

  1. Prochaines étapes, nous exécuterons HelloSoapPublisher.java en tant qu’application Java. Ensuite, nous afficherons le fichier WSDL en demandant l’URL http://localhost:9000/ws/hello-soap?wsdl dans un navigateur Web.
 http://localhost:9000/ws/hello-soap?wsdl 

Si le format de données XML est affiché sur le navigateur Web, nous sommes prêts à passer à l’étape suivante.

[![bonjour-savon?wsdl][2]][2]

Remarque : Si vous obtenez une sorte de message d’erreur, vous devrez peut-être utiliser l’outil wsgen pour générer les artefacts portables JAX-WS nécessaires. Nous ne sont pas couverts par l’outil wsgen ici.

  1. Client de service Web

Dernière étape, nous allons créer un client qui accède à notre service publié.

<pré> importer java.net.URL ;

import javax.xml.namespace.QName ; importer javax.xml.ws.Service ;

classe publique HelloSoapClient {

public static void main(String[] args) throws Exception {

    // create wsdl url
    URL wsdlDocumentUrl = new URL("http://localhost:8000/ws/hello-soap?wsdl");
    QName helloSoapService = new QName("http://hello-soap/ws", "HelloSoapService");
    // create web service
    Service service = Service.create(wsdlDocumentUrl, helloSoapService);
    // get object of pointed service port
    HelloSoap helloSoap = service.getPort(HelloSoap.class);
    // testing request
    System.out.println(helloSoap.getHelloSoap("Soap "));

}

}

Production: [JAX-WS] Bonjour : Savon

Remarque : Le numéro de port a été remplacé par “8000” dans notre client de service Web. La raison ici est que j’ai utilisé Eclipse IDE, l’outil intégré TCP/IP monitor pour tracer les messages (Plus d’informations : [Comment tracer un message SOAP dans Eclipse IDE](http://www.mkyong.com/webservices/ jax-ws/how-to-trace-soap-message-in-eclipse-ide/)). À des fins de test fonctionnel, essayez SoapUI | Tests fonctionnels pour les API SOAP et REST.

[1] : https://i.stack.imgur.com/izgZQ.png [2] : https://i.stack.imgur.com/O2rcA.png

Client Java pour le service Web open source du service météo disponible sur http://www.webserviceX.NET

  package com.test.ws.example;

 import javax.xml.soap.MessageFactory;
 import javax.xml.soap.MimeHeaders;
 import javax.xml.soap.SOAPBody;
 import javax.xml.soap.SOAPConnection;
 import javax.xml.soap.SOAPConnectionFactory;
 import javax.xml.soap.SOAPElement;
 import javax.xml.soap.SOAPEnvelope;
 import javax.xml.soap.SOAPMessage;
 import javax.xml.soap.SOAPPart;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.stream.StreamResult;

 /*
  * WSDL url :  http://www.webservicex.com/globalweather.asmx?WSDL
  * Endpoint URL: http://www.webservicex.com/globalweather.asmx   */

    public class WSClient {

   public static void main(String args[]) {

    try {
        SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
        SOAPConnection soapConnection = soapConnectionFactory.createConnection();

        // Generate SOAP request XML

        MessageFactory messageFactory = MessageFactory.newInstance();
        SOAPMessage soapMessage = messageFactory.createMessage();
        MimeHeaders header = soapMessage.getMimeHeaders();
        header.setHeader("SOAPAction", "http://www.webserviceX.NET/GetCitiesByCountry");
        SOAPPart soapPart = soapMessage.getSOAPPart();
        SOAPEnvelope envelope = soapPart.getEnvelope();
        envelope.addNamespaceDeclaration("web", "http://www.webserviceX.NET");
        SOAPBody soapBody = envelope.getBody();
        SOAPElement soapBodyElem = soapBody.addChildElement("GetCitiesByCountry", "web");
        SOAPElement soapBodyElem1 = soapBodyElem.addChildElement("CountryName", "web");
        soapBodyElem1.addTextNode("INDIA");
        soapMessage.saveChanges();
        soapMessage.writeTo(System.out);
        
                    
        // Call webservice endpint
        String url = "http://www.webservicex.com/globalweather.asmx";
        SOAPMessage soapResponse = soapConnection.call(soapMessage, url);
        Source sourceContent = soapResponse.getSOAPPart().getContent();

        // Print SOAP response
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        System.out.println("Response SOAP Message \n");
        StreamResult result = new StreamResult(System.out);
        transformer.transform(sourceContent, result);
        soapConnection.close();

    } catch (Exception e) {

        e.printStackTrace();
    }
}

}