Perché
WSDL
L'utilizzo di WSDL ha due vantaggi: per prima cosa,
alcuni strumenti di sviluppo sono in grado di prendere
in input un file WSDL e produrre del codice che implementa
l'infrastruttura per realizzare il servizio, oppure
per crearne un runtime per la semplice implementazione
di un client; in secondo luogo, è un modo per
disaccoppiare il servizio Web dal protocollo di trasporto
e dai percorsi fisici, come gli endpoint.
Come accennato, nel file WSDL è presente l'indicazione
del protocollo da utilizzare: un sistema di runtime
che supporti diversi protocolli di comunicazione XML,
come SOAP ed XML-RPC, potrebbe capire dal WSDL come
ricondurre a messaggi SOAP o XML-RPC reali, le rappresentazioni
astratte contenute nel documento WSDL. Un servizio potrebbe
infatti partire utilizzando SOAP come protocollo, ma
poi passare a XML-RPC con l'intento di ottimizzarne
le prestazioni, ad esempio per via della sua potenziale
minor occupazione di banda. Se il client del servizio
viene codificato direttamente su SOAP, il suo passaggio
a XML-RPC potrebbe essere problematico. Con un runtime
dinamico che supporta entrambi i protocolli e che faccia
riferimento al file WSDL per conoscere quale protocollo
deve essere fisicamente utilizzato, la migrazione potrebbe
essere più indolore.
Sicuramente uno scenario del genere comporta l'utilizzo
di infrastrutture per i servizi Web più complesse
di quelle fornite da JAXM e SAAJ. Inoltre, un'esigenza
di questo tipo potrebbe più facilmente nascere
in un futuro, magari quando esisterà un legacy
di servizi Web in SOAP e XML-RPC e si dovrà migrare
ad un ipotetico nuovo protocollo di comunicazione XML.
Ma anche senza considerare aspetti così futuribili,
l'utilizzo dinamico di WSDL potrebbe limitarsi anche
alla sola acquisizione dell'endpoint del servizio: invece
che configurare direttamente l'URL del servizio, questo
andrebbe letto dal documento WSDL. Si introduce così
un livello di indirezione, simile a quanto fanno i servizi
di DNS sugli indirizzi Internet.
Il vantaggio di avere un livello di indirezione è
che se si hanno molti client che puntano ad un file
WSDL per ottenere l'endpoint di un servizio, nel momento
in cui questo cambia indirizzo, non è necessario
riconfigurare tutti i client, ma è sufficiente
modificare il solo file WSDL.
All'interno
di WSDL
Un documento WSDL è un file XML contentente un
insieme di definizioni. Nello standard WSDL è
possibile trovare quattro diversi tipi di informazioni.
Sicuramente l'aspetto principale sono l'insieme di regole
che consentono di definire in modo astratto un servizio
Web; oltre a ciò, sono presenti le specifiche
per collegare il servizio a SOAP, HTTP e MIME.
La definizione astratta dei servizi Web di WSDL è
composta da cinque diversi elementi:
-
i tipi (types);
- i
messaggi (messages);
- le
operazioni (portType);
- i
collegamenti (bindings);
- la
definizione del servizio (service);
La
struttura di un file WSDL è presente nel listato
1.
Listato
1 - Struttura di un file WSDL
<wsdl:definitions
name="nmtoken"? targetNamespace="uri"?>
<import
namespace="uri" location="uri"/>*
<wsdl:documentation
.... /> ?
<wsdl:types>
?
<wsdl:documentation .... />?
<xsd:schema .... />*
<-- extensibility element --> *
</wsdl:types>
<wsdl:message
name="nmtoken"> *
<wsdl:documentation .... />?
<part name="nmtoken" element="qname"?
type="qname"?/> *
</wsdl:message>
<wsdl:portType
name="nmtoken">*
<wsdl:documentation .... />?
<wsdl:operation name="nmtoken">*
<wsdl:documentation .... /> ?
<wsdl:input name="nmtoken"? message="qname">?
<wsdl:documentation .... /> ?
</wsdl:input>
<wsdl:output name="nmtoken"? message="qname">?
<wsdl:documentation .... /> ?
</wsdl:output>
<wsdl:fault name="nmtoken" message="qname">
*
<wsdl:documentation .... /> ?
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding
name="nmtoken" type="qname">*
<wsdl:documentation .... />?
<-- extensibility element --> *
<wsdl:operation name="nmtoken">*
<wsdl:documentation .... /> ?
<-- extensibility element --> *
<wsdl:input> ?
<wsdl:documentation .... /> ?
<-- extensibility element -->
</wsdl:input>
<wsdl:output> ?
<wsdl:documentation .... /> ?
<-- extensibility element --> *
</wsdl:output>
<wsdl:fault name="nmtoken"> *
<wsdl:documentation .... /> ?
<-- extensibility element --> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service
name="nmtoken"> *
<wsdl:documentation .... />?
<wsdl:port name="nmtoken" binding="qname">
*
<wsdl:documentation .... /> ?
<-- extensibility element -->
</wsdl:port>
<-- extensibility element -->
</wsdl:service>
<--
extensibility element --> *
</wsdl:definitions>
Tipi
I tipi definiti da WSDL sono l'equivalente delle strutture
(struct) del linguaggio C: strutture dati anche complesse
che sono utilizzate come elementi base per costruire
i messaggi di input ed output definiti nella sezione
"messaggi". Ad esempio, la seguente porzione
di file XML (listato 2), definisce due elementi: TradePriceRequest,
composto da una stringa e TradePrice, composto da un
valore in virgola mobile.
Listato
2 - Un esempio di definizione di tipi
<types>
<schema targetNamespace="http://example.com/stockquote.xsd"
xmlns="http://www.w3.org/2000/10/XMLSchema">
<element name="TradePriceRequest">
<complexType>
<all>
<element name="tickerSymbol" type="string"/>
</all>
</complexType>
</element>
<element name="TradePrice">
<complexType>
<all>
<element name="price" type="float"/>
</all>
</complexType>
</element>
</schema>
</types>
In
questo caso, dove la struttura dati contiene un solo
campo, la definizione di un tipo specifico non è
indispensabile: la sua utilità è per lo
più relativa alla manutenibilità del documento
WSDL. In questo modo infatti viene creato un "alias"
e nel resto del documento WSDL si utilizzeranno i tipi
definiti al posto che i tipi di dati primitivi, disaccoppiando
il resto delle definizioni dai tipi di dati reali.
Messaggi
I messaggi sono gli elementi che costituiscono gli input
e gli output dei servizi. I singoli messaggi possono
contenere i tipi di dati complessi definiti nella sezione
types (Figura 1), oppure semplici dati primitivi.
Figura 1 - La struttura di un
messaggio WSDL
Un
esempio di messaggio è presente nel listato 3,
ed è relativo al file WSDL del servizio di cambio
valute utilizzato nel paragrafo precedente. Come si
può notare osservando il listato, vengono definiti
due diversi messaggi, uno relativo alla richiesta, getRateRequest,
ed uno relativo alla risposta, getRateResponse. Il primo
definisce due elementi, di tipo stringa, chiamati country1
e country2; il secondo definisce un unico elemento di
risposta Result, di tipo float.
Listato
3 - Un esempio di definizione di messaggi
<message
name="getRateRequest">
<part name="country1" type="xsd:string"/>
<part name="country2" type="xsd:string"/>
</message>
<message name="getRateResponse">
<part name="Result" type="xsd:float"/>
</message>
Operazioni
Questa sezione definisce le operazioni fornite dal servizio
Web. Se si ponessero in relazione i servizi Web con
la programmazione distribuita, ad esempio RMI, le operazioni
WSDL equivarrebbero ai singoli metodi dell'oggetto remoto
(Figura 2). Per ciascuna operazione, WSDL definisce
i messaggi di input e di output. Un esempio di operazione
è presente nel listato 4, sempre estratto dal
WSDL del servizio di cambio valuta.
Figura 2 - L'accesso al servizio Web
avviene tramite le "port"
Listato
4 - Un esempio di operazione
<portType
name="CurrencyExchangePortType">
<operation
name="getRate">
<input message="tns:getRateRequest" />
<output message="tns:getRateResponse" />
</operation>
</portType>
L'elemento
<operation> definisce una singola operazione e
può contenere opzionalmente almeno uno dei due
sottoelementi <input> ed <output>. La presenza
e l'ordine di questi elementi determina la tipologia
di servizio, che può rientrare all'interno di
quattro diverse nature:
- one-way.
Anche detto fire&forget, è una configurazione
dove l'endpoint si limita a ricevere il messaggio
inviato dal client. In questo caso è presente
un solo elemento di input;
- request-response.
In questo caso l'endpoint riceve un messaggio di richiesta,
esegue l'elaborazione necessaria e restituisce al
client un messaggio di risposta correlato alla richiesta
ricevuta. Sono presenti gli elementi input ed output;
- solicit-response.
E' l'opposto del precedente. In questo caso è
l'endpoint che inizia la comunicazione inviando un
messaggio al client che a sua volta dovrà rispondere
di conseguenza. Nel file WSDL è presente prima
l'elemento output e poi quello input;
- notification.
E' l'opposto della tipologia one-way. In questo caso
è l'endpoint ad inviare un messaggio al client,
senza che questo debba inviare una risposta. E' presente
il solo elemento output.
Il
modello di interazione da utilizzare dipende dalla natura
del servizio. Se l'interazione request-response potrebbe
essere quella usata per la maggior parte dei servizi,
in quanto costituisce il tipico modello di comunicazione
RPC, altre modalità possono essere utili in altri
ambiti. Ad esempio, una interazione one-way può
essere utile in sistemi dove il client invia una serie
di informazioni al servizio, e questo si limita a raccoglierle.
In questo caso il client non è interessato al
risultato dell'elaborazione dei suoi dati, come nell'esempio
relativo alla raccolta dati ambientali descritto all'inzio
del capitolo.
Collegamenti
In questa sezione avviene la mappatura del servizio
astratto, definito nelle sezioni precedenti, al protocollo
concreto di comunicazione (ad esempio SOAP). Il contenuto
di questa sezione è fortemente dipendente dal
protocollo utilizzato, e quindi delle estensioni WSDL
relative.
In WSDL, la struttura di un collegamento (semplificata)
è quella riportata nel listato 5. Quella completa
è presente nella struttura completa di un file
WSL riportata ad inizio paragrafo.
Listato
5 - Sezione WSDL relativa ai collegamenti
<wsdl:binding
name="nmtoken" type="qname">*
<wsdl:operation name="nmtoken">*
<wsdl:input> ?
</wsdl:input>
<wsdl:output>
?
</wsdl:output>
<wsdl:fault
name="nmtoken"> *
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
Come
si può notare, un collegamento può contenere
diverse operazioni, ciascuna delle quali può
avere un elemento di input, di output ed una serie di
elementi di errore (fault). Nel listato 6 è presente
un esempio di collegamento con SOAP, sempre estratto
dal file WSDL per il servizio di cambio valuta. La struttura
del collegamento è la seguente: per prima cosa,
viene definito lo stile del collegamento (può
essere rpc oppure document) ed il tipo di trasporto:
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
In
questo caso la comunicazione è di tipo RPC ed
il trasporto avviene sul protocollo HTTP. In secondo
luogo, è necessario definire, per ciascuna operazione,
come trattare i messaggi di input ed output. Essendo
questo un servizio request-response, le informazioni
sono presenti entrambe. Il messaggi di input è
così definito:
<soap:body use="encoded" namespace="urn:xmethods-CurrencyExchange"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
In
questo elemento viene indicato il namespace del messaggio
(urn:xmethods-CurrencyExchange) ed il tipo di encoding.
L'attributo use può assumere i valori "econding",
oppure "literal". Nel primo caso, l'attributo
encodingStyle dovrà indicare il tipi di encoding
utilizzato. In questo caso, viene utilizzato l'encoding
SOAP.
Listato
6 - Un esempio di collegamento
<binding
name="CurrencyExchangeBinding" type="tns:CurrencyExchangePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getRate">
<soap:operation soapAction=""/>
<input
>
<soap:body use="encoded" namespace="urn:xmethods-CurrencyExchange"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output >
<soap:body use="encoded" namespace="urn:xmethods-CurrencyExchange"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
Definizione
del servizio
L'ultimo elemento di un file WSDL è la definizione
del servizio: questa sezione consente di raccogliere
tutte le operazioni sotto un unico nome (vedi Figura
2). Il servizio è identificato da un nome (l'attributo
name dell'elemento service) e può avere una descrizione,
contenuta nel sottolemento opzionale documentation.
All'interno dell'elemento service vengono elencate tutte
le operazioni esposte dal servizio, sottoforma di elementi
port. Per ciascuno di questi viene indicato il collegamento
utilizzato. Il contenuto dell'elemento port cambia in
funzione del tipo di collegamento utilizzato. Nel listato
7 è presente un esempio di definizione di servizio,
in particolare del servizio di cambio valute, dove il
collegamento utilizzato è quello con SOAP. In
questo caso nell'elemento port è presente un
elemento address appartenente al namespace soap: (utilizzato
in tutto il WSDL per riferirsi agli elementi strettamente
relativi al collegamento di WSDL con SOAP). Questo elemento
indica l'URL fisico dell'endpoint del servizio.
Listato
7 - Un esempio di definizione di servizio
<service
name="CurrencyExchangeService">
<documentation>Returns
the exchange rate between the two currencies</documentation>
<port name="CurrencyExchangePort" binding="tns:CurrencyExchangeBinding">
<soap:address location="http://services.xmethods.net:80/soap"/>
</port>
</service>
L'utilizzo
di WSDL può diventare anche molto complesso nel
momento in cui ci si addentri in collegamenti e protocolli
diversi da SOAP ed HTTP. Per ciascun protocollo e livello
di trasporto è infatti necessario definire una
estensione WSDL specifica e costruire i documenti WSDL
secondo questa grammatica. Il vantaggio della grande
estensibilità di WSDL si paga quindi in termini
di complessità.
|