Le
specifiche di SOAP 1.2 sono definite in due diversi
documenti ("Part 1: Messaging Framework" e
"Part 2: Adjuncts") a cui è stato aggiunto
un terzo documento di introduzione. Sebbene gran parte
della logica e dei concetti di SOAP 1.1 sia mantenuta
in SOAP 1.2, in quest'ultima versione sono state applicate
diverse piccole variazioni, cambi di nomi e chiarimenti
di semantica, che rendono incompatibili le due versioni.
Per di più, si noti che la presenza di namespace
specifici all'interno dei messaggi è il meccanismo
utilizzato da SOAP per garantire che un nodo elabori
un messaggio in funzione della specifica versione in
cui è stato codificato. Ad esempio, un servizio
è in grado, analizzando il messaggio, di verificare
se questo è stato codificato secondo le specifiche
SOAP 1.1 oppure SOAP 1.2 ed attivare le due differenti
gestioni, in funzione della versione.
In questo capitolo si considererà solo SOAP 1.1,
in quanto è la versione stabile attualmente disponibile
e quella supportata dalla piattaforma Java e dalla maggior
parte degli strumenti disponibili.
Nelle
specifiche SOAP convivono quattro diversi aspetti che
affrontano differenti parti del problema:
- il
modello di scambio dei messaggi;
- l'encoding
SOAP;
- il
collegamento tra SOAP ed http;
- l'utilizzo
di SOAP come meccanismo di RPC.
Il
modello di scambio dei messaggi definisce un modo standard
per definire come strutturare messaggi XML che saranno
scambiati tra i diversi nodi, come vengono gestiti gli
errori e come si devono chiamare i tag XML che contengono
le informazioni.
L'encoding SOAP fornisce una specifica (opzionale),
per definire come strutture dati anche complesse, come
enumerazioni e vettori sparsi, vengono rappresentate
in XML. E' basata su una prima bozza delle specifiche
XML Schema.
Il collegamento con HTTP, invece, definisce come i messaggi
SOAP debbano essere veicolati tramite questo protocollo
di filo e come devono essere utilizzate le intestazioni
HTTP ed i codici di ritorno per l'invio di messaggi
SOAP.
Infine, il modello RPC definisce come SOAP può
essere utilizzato per rappresentare chiamate a procedure
remote. Le specifiche SOAP consentono infatti di realizzare
applicazioni di semplice messaggistica o più
evolute applicazioni distribuite, anche se mancano i
dettagli per aspetti legati alla sicurezza ed alla garbage
collection distribuita.
Anatomia
del messaggio
La comunicazione tramite SOAP avviene tramite lo scambio
di messaggi strutturati in modo specifico comprendente
elementi obbligatori ed elementi opzionali. Il tag principale
che racchiude tutti gli altri è Envelope (busta).
Dentro questo è presente Header (intestazione)
e Body (corpo). Il primo è opzionale, mentre
nel corpo sono presenti tutte le informazioni applicative
che il nodo vuole inviare.
Listato
1 - Esempio di richiesta SOAP
<?xml
version="1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/>
<SOAP-ENV:Body>
<ns1:getRate xmlns:ns1="urn:xmethods-CurrencyExchange">
<country1>England</country1>
<country2>Japan</country2>
</ns1:getRate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Nel
listato 1 è presente un esempio di semplice messaggio
SOAP. I tag Evelope e Body appartengono al namespace
http://schemas.xmlsoap.org/soap/envelope. L'utilizzo
di SOAP-ENV è semplicemente una convenzione:
al suo posto si sarebbe potuto utilizzare un qualsiasi
nome simbolico, come ad esempio "ns1", utilizzato
nel corpo del messaggio.
Come si può notare, all'interno del tag Body
è definito il messaggio applicativo: nel tag
getRate sono presenti i tag country1 e country2. Questo
blocco SOAP potrebbe essere un messaggio utilizzato
in una applicazione che si occupi di fornire il tasso
di conversione tra diverse valute.
L'utilizzo dei namespace è importante: consente
di essere sicuri che non ci siano conflitti di nomi:
come due classi Java con lo stesso nome possono convivere
nello stesso programma se appartengono a package differenti,
anche in SOAP possono coesistere tag con lo stesso nome,
purché questi appartengano a namespace diversi.
La risposta SOAP (listato 2) è strutturata in
modo similare, con tag Envelope e Body e con una risposta
applicativa all'interno di quest'ultimo.
Listato
2 - Esempio di risposta SOAP
<?xml
version="1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/>
<SOAP-ENV:Body>
<ns1:getRateResponse xmlns:ns1="urn:xmethods-CurrencyExchange">
<return>154.9423</return>
</ns1:getRateResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Per
convenzione, il nome del tag utilizzato nella risposta
è lo stesso della richiesta, a cui è aggiunto
la parola "Response". Nell'esempio, il tag
applicativo contiene il valore di ritorno della chiamata
al servizio, e cioè il tasso di conversione tra
le due divise specificate.
I due blocchi SOAP visti in precedenza presuppongono
un modello di interazione tra due nodi di tipo request/response:
a ciascuna richiesta, il ricevente fornisce una risposta
al chiamante. SOAP è utilizzabile anche in modalità
oneway (a senso unico, detta anche fire&forget),
dove il client si limita ad inviare un messaggio al
server, senza che questo formuli una risposta. Queste
due modalità verranno viste più in dettaglio
nella parte dedicata a WSDL, che tra l'altro, ne definisce
di ulteriori.
SOAP
su HTTP
Le regole per utilizzare SOAP su HTTP ben si sposano
con quest'ultimo protocollo, in quanto non vengono aggiunti
elementi estranei, ma vengono sfruttate le semantiche
già esistenti. In particolare, le regole di mappatura
possono essere così riassunte:
-
il Content-Type deve essere "text/xml";
-
l'intestazione HTTP deve riportare il campo SOAPAction.
Questo indica al server Web od al firewall l'intento
del messaggio, per eventuali operazioni di filtro.
Entrambe
queste indicazioni sono obbligatorie.
L'invio di una richiesta dal client al server, avviene
tramite una operazione di POST, come si evince dall'esempio
presente nel listato 3. Qui è possibile vedere
l'intestazione HTTP di una classica richiesta SOAP,
con l'indicazione corretta del Content-Type e di SOAPAction.
Listato
3 - Richiesta SOAP veicolata sul protocollo HTTP
POST
/StockQuote HTTP/1.1
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
SOAPAction: "http://electrocommerce.org/abc#MyMessage"
<SOAP-ENV:Envelope...
Per quanto concerne la risposta (un esempio è
presente nel listato 4), il client deve fare affidamento
sul codice HTTP di risposta per capire se tutto è
andato bene o se si è verificato qualche problema.
Listato
4 - Risposta SOAP veicolata sul protocollo HTTP
HTTP/1.1
200 OK
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope...
Nel
caso del listato 4 il server ha ritornato il codice
200, che indica la corretta elaborazione della risposta.
In entrambi i casi, ovviamente, il campo Content-Length
conterrà la corretta dimensione del corpo del
messaggio SOAP.
Se
qualcosa va male
Se avviene qualche errore in fase di elaborazione del
messaggio SOAP, il server può inviare come risposta,
al posto della normale risposta SOAP, una specifico
messaggio di errore, detto Fault. Questo definisce,
in modo standardizzato, le specifiche dell'errore occorso.
I contenuti del tag Fault possono essere:
-
faultcode;
- faultstring;
- faultactor;
- detail.
Questi
elementi identificano, nell'ordine, il codice dell'errore,
la descrizione dell'errore, l'entità che lo ha
generato ed opzionalmente i dettagli dell'errore, strutturati
come un blocco XML applicativo. Nel listato 5 è
presente un esempio di Fault SOAP.
Listato
5 - Esempio di Fault SOAP
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>Errore server</faultstring>
<detail>
<e:myfaultdetails xmlns:e="Some-URI">
<message>
Si è verificato un errore applicativo
</message>
<errorcode>
1001
</errorcode>
</e:myfaultdetails>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Il
codice dell'errore è una stringa, composta da
parole concatenate, come ad esempio "Client.Authentication".
Lo scopo delle specifiche è quello di fornire
un meccanismo che sia più flessibile ed espandibile
rispetto ai più classici codici di errore numerici,
come quelli utilizzati in HTTP.
I prefissi che possono essere utilizzati nei codici
di errore sono predefiniti, e sono:
- VersionMismatch.
Indica che il namespace sul tag Envelope che identifica
la versione, ha un valore diverso da quello atteso;
- MustUnderstand.
L'elaborazione obbligatoria di una parte dell'intestazione
ha avuto esito negativo;
- Client.
Può indicare errori in merito alla strutturazione
del messaggio di richiesta;
- Server.
Indica l'impossibilità di elaborare una risposta,
anche a fronte di richieste correttamente strutturate
(ad esempio nel caso di inconsistenze interne del
componente server);
Un
utilizzo interessante del tag detail è quello
che prevede la sua valorizzazione con lo stack trace
della chiamata che ha generato l'errore, in modo da
semplificare il debug dell'applicazione. Questa informazione,
infatti, non è obbligatoriamente da mostrare
all'utente, ma l'applicazione la potrebbe mostrare solo
a sviluppatori e sistemisti fornendo una informazione
preziosa per indivudare l'errore.
Il
collegamento con il protocollo HTTP definisce che il
blocco SOAP Fault debba essere veicolato con un messaggio
con codice di errore 500 (utilizzato in HTTP per identificare
gli errori del server), come si evince dal listato 6.
Listato
6 - Fault SOAP veicolato tramite HTTP
HTTP/1.1
500 Internal Server Error
Content-Type: text/xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
Encoding
Il concetto di encoding riguarda le informazioni applicative
contenute nel tag Body: definisce come i dati vengono
rappresentati in XML. Le specifiche SOAP lasciano una
certa libertà, ma suggeriscono l'uso dell'encoding
SOAP. Altri, come Apache, hanno storicamente proposto
un econding più semplice, denominato encoding
letterale.
Ecoding
letterale
Questo tipo di encoding è semplicemente un blocco
XML applicativo appartenente opzionalmente ad un determinato
namespace. Un esempio è presente nel listato
7.
Listato
7 - Un esempio di encoding letterale
<Contatti>
<Persone>
<Persona id="1">
<Nome>Mario</Nome>
<Cognome>Rossi</Cognome>
</Persona>
<Persona id="2">
<Nome>Giuseppe</Nome>
<Cognome>Verdi</Cognome>
</Persona>
</Persone>
</Contatti>
Anche
i primi esempi SOAP visti in precedenza (listati 1 e
2), utilizzano un encoding letterale, utilizzando però
uno specifico namespace. Come si nota, la codifica è
molto semplice, ma non sono presenti informazioni sui
tipi di dati.
Encoding
SOAP
L'encoding SOAP definisce regole (derivate da una prima
versione di XML Schema), per rappresentare il tipo di
dato utilizzato nel blocco dati applicativo, mutuando
le tipologie dai più diffusi linguaggi di programmazione
e dai tipi di dati utilizzati nei database.
Le strutture complesse, come i dati compositi (ad esempio
le struct del linguaggio C), trovano quindi uno standard
per la loro serializzazione in XML.
Sono previsti diversi tipi di dati, come:
- tipi
semplici (numeri interi, reali, stringhe, etc);
- enumerazioni;
- array
di bytes (base64);
- strutture;
- array;
La gestione degli array in particolare è molto
potente, in quanto consente anche di specificare array
sparsi, dove cioè, gli indici possono anche non
essere contigui (ad esempio possono essere presenti
solo gli elementi 1, 3, 4, 11).
L'encoding SOAP è più stringente rispetto
all'encoding letterale. Questo consente di rendere più
facile l'interoperabilità delle informazioni
trasferendo, insieme ai dati, anche metainformazioni
che ne descrivono il tipo. Ad esempio, è possibile
capire direttamente dal flusso XML se un determinato
tag è di tipo stringa o numerico.
Per esempio, nel blocco XML:
<X1>12</X1>
il
valore 12 potrebbe essere numerico, ma il tag potrebbe
anche potenzialmente essere di tipo alfanumerico). Con
l'encoding SOAP avremmo:
<X1 xsd:type="String">12</X1>
il
contenuto dell'attributo type chiarisce che il tipo
di dato è alfanumerico. Sempre in merito ai listati
1 e 2, è possibile codificarli con l'encoding
SOAP, come esemplificato nei listati 8 e 9.
Listato
8 - Un esempio di chiamata codificata con l'encoding
SOAP
<?xml
version="1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getRate xmlns:ns1="urn:xmethods-CurrencyExchange"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<country1 xsi:type="xsd:string">England</country1>
<country2 xsi:type="xsd:string">Japan</country2>
</ns1:getRate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Listato
9 - Un esempio di risposta codificata con l'encoding
SOAP
<?xml
version="1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:getRateResponse xmlns:ns1="urn:xmethods-CurrencyExchange"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xsi:type="xsd:float">154.9423</return>
</ns1:getRateResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Si
può notare in questi esempi (listati 8 e 9),
come ciascun tag applicativo specifichi anche un attributo
che identifica il tipo di dato.
SOAP
RPC
Le specifiche SOAP definiscono anche gli standard per
utilizzare messaggi SOAP per realizzare semplici applicazioni
distribuite di tipo Remote Procedure Call (RPC). In
particolare, le chiamate sono descritte all'interno
del tag body ed i parametri ed il valore di ritorno
sono modellati come strutture, anche se la scelta dell'encoding
è libera. In caso di errore, questo è
codificato come Fault SOAP.
La
differenza tra semplici messaggi SOAP e SOAP-RPC è
che nel primo caso si parla di generici messaggi di
notifica che possono veicolare meri contenuti informativi
(come ad esempio, un intero documento XML da inserire
in un database). In caso di SOAP-RPC, nel corpo del
messaggio SOAP è presente una formalizzazione
in XML di una chiamata a metodo, quindi tipicamente
le informazioni sul nome del metodo ed i valori dei
parametri.
SOAP-RPC
verrà visto più nel dettaglio nella prossima
puntata, tramite un esempio pratico.
Conclusioni
In questo articolo abbiamo affrontato gli aspetti salienti
del protocollo SOAP. Nella prossima puntata vedremo
come applicare in pratica questa tecnologia utilizzando
le API Java per la messaggistica XML: JAXM.
|