I web services sono un paradigma di progettazione fondato sul concetto di interoperabilità dei servizi. Chi non conoscesse i web services può trovare un'introduzione all'argomento qui, e un esempio di implementazione pratica (client-server) qui.

Sull'argomento esistono alcune controversie che riguardano la definizione stessa di web service. Secondo alcuni un web service è qualsiasi tecnologia che permetta lo scambio di dati tra piattaforme diverse, offrendo un'interfaccia indipendente dai sistemi coinvolti. Da questo punto di vista una comune chiamata Ajax è un web service. Secondo altri, un web service deve utilizzare il protocollo SOAP e deve dichiarare le proprietà dell'interfaccia mediante un documento WSDL (Web Service Definition Language): da questo punto di vista, alcuni servizi REST non sarebbero a rigore web services, perché non espongono un WSDL e non utilizzano il protocollo SOAP.

Noi preferiamo schierarci dalla parte della definizione allargata, per cui qualsiasi tecnologia in grado di garantire l'interoperabilità tra piattaforme diverse può essere considerata un web service, al di là di quale sia il protocollo utilizzato e come sia definita l'interfaccia del servizio. In questi termini, il WSDL è probabilmente il modo migliore di descrivere l'interfaccia di un web service, ma non è strettamente necessario. Con il WSDL 2.0 anche i servizi REST possono esporre un WSDL, cosa che dovrebbe risolvere una volta per tutte la diatriba sulla definizione di web service. Oggi andremo a vedere come creare un semplice WSDL, per sfatare il mito secondo cui i WSDL sono complicati e astrusi.

Struttura di un WSDL

  • <?xml … ?> : dichiarazione versione XML
  • <wsdl:definitions … > : dichiarazione del WSDL
  • <wsdl:types>... </wsdl:types> : definizione dei dati
  • <message> … </message>: elenco messaggi
  • <portType> … </portType>: elenco delle porte
  • <binding> … </binding>: associazione tra operazioni e trasporto
  • <service> … </service>: definizione del servizio

di primo acchito, il fatto di avere almeno sette sezioni in un WSDL può scoraggiare, ma ricordiamoci del motto dividi et impera e affrontiamole una alla volta. Dopotutto si tratta solo di XML, come vedremo tra poco.

La prima sezione è la normale definizione della versione del XML, per cui niente di nuovo. Nella seconda sezione definiamo tutti i prefissi ed i namespace utilizzati nel WSDL, esattamente come per un XML Schema Definition (XSD), ad esempio

<wsdl:definitions name="il_mio_web_service" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="https://www.aziendeitalia.com/webservices"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns:tns="https://www.aziendeitalia.com/webservices"

ecc...

nella terza sezione, racchiusa tra le tag <wsdl:types>, troviamo le definizioni degli elementi XML che andranno a comporre i messaggi d'ingresso (request) e d'uscita (response): anche in questo caso si tratta di un normale set di definizioni XSD.

Le uniche novità sono le quattro sezioni rimanenti, ovvero: messaggi, porte, binding e servizio. Un modo di spiegare a cosa servono, e come vanno progettate, è procedere dal basso verso l'alto, ponendo l'accento sulle relazioni tra queste sezioni. Iniziando dalla sezione servizio abbiamo

<service name="il_mio_web_service"> <port name="service_port" binding="tns:main_binding"> <soap:address location="http://www.placeholder.org/"/> </port> </service>

l'elemento più importante è binding, che indica dov'è definito il trasporto del servizio, in questo caso main_binding. Nella sezione binding dovremo quindi definire un elemento del tipo

<binding name="main_binding" type="tns:main_port"> <soap:binding style="document"

transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="getData"> <soap:operation style="document"

soapAction="https://www.aziendeitalia.com/webservices/getData"/>

... </operation> </binding>

la sezione specifica che il trasporto dei messaggi avviene via protocollo HTTP, e che l'operazione getData è associata alla porta main_port. Nelle specifiche SOAP una porta può essere pensata come l'astrazione dell'operazione, cosa che permette di disaccoppiare la definizione dell'operazione vera e propria dalla definizione dell'interfaccia ad essa associata. In questo caso ci aspettiamo quindi che esista una porta del tipo

<portType name="main_port"> <operation name="getData"> <input message="tns:inputMessage"/> <output message="tns:outputMessage"/> </operation> </portType>

Con questo abbiamo chiuso il giro, perché qui sopra stiamo precisando che l'operazione getData riceve in ingresso il messaggio inputMessage e fornisce in uscita il messaggio outputMessage: ciò che significa che nella sezione dei messaggi (all'interno della tag message) troveremo la definizione di questi messaggi astratti nei termini degli elementi XSD contenuti nella sezione <wsdl:types>.

Ovviamente, semplificando al massimo l'argomento, abbiamo omesso qualche dettaglio, ma la chiave di lettura vista qui sopra è sostanzialmente corretta e dovrebbe aiutarci a interpretare un generico WSDL. Il passo successivo potrebbe essere quello di prendere un WSDL già esistente e provare a modificarlo, oppure creare un "template WSDL" generico, da usarsi per produrre i WSDL che ci servono.