UDDI e WSDL: navigare sicuri nel mare dei Web Service
Transcript
UDDI e WSDL: navigare sicuri nel mare dei Web Service
F O C U S Servizi Web UDDI Col proliferare dei Web service e delle aziende che li forniscono, si sente il bisogno di mettere ordine, per sfruttare pienamente le potenzialità dei servizi disponibili in rete UDDI e WSDL: navigare sicuri nel mare dei Web service di Massimo Ruocchio [email protected] C ol passare del tempo, la “rete delle reti” somiglia sempre di più ad un oceano. Navigando in quest’oceano ci si può imbattere in bellissimi esemplari animali ed in pericolosissimi squali. Si possono trovare enormi risorse da sfruttare e minacciose trappole da evitare. Una delle migliori risorse della rete sono i Web service. L’idea che sta alla base dei servizi Web è semplice quanto geniale: una volta costruito e testato un modulo software che realizza una certa operazione, può essere messo in rete a disposizione di tutte le altre applicazioni che ne avessero bisogno. Chiunque può utilizzarlo risparmiandosi l’onere di produrre da sé ciò che qualcun altro ha già messo a punto. È la stessa idea che sta alla base della programmazione ad oggetti, l’unica differenza è la posizione in cui sono dislocati i moduli: sul Web anziché in una libreria. A dire il vero un’altra differenza c’è: i servizi Web possono essere realizzati con un linguaggio di programmazione ed in un ambiente operativo completamente differenti rispetto a quelli delle applicazioni che li devono utilizzare. Questa differenza di “piattaforme” può essere superata solo stabilendo un protocollo di comunicazione tra l’applicazione chiamante ed il servizio chiamato. Chi determina il protocollo da utilizzare è, ovviamente, il fornitore del servizio. Lo stesso fornitore deve descrivere il servizio che intende pubblicare, in modo che tutti sappiano a cosa serve e come può essere utilizzato. È laureato in matematica ed è certificato Oracle come Application Developer. Si occupa di analisi, progettazione e sviluppo di applicazioni software. Chi vuole usare un Web service ha bisogno di uno strumento che gli consenta di trovare il servizio che sta cercando. Per venire incontro alle necessità sia dei fornitori sia degli utenti di servizi Web, si sta lavorando alla definizione di due strumenti standard: WSDL (Web Services Description Language) e UDDI (Universal Description, Discovery and Integration). Descrizione del servizio con WSDL WSDL è un linguaggio basato su XML. Per utilizzare WSDL bisogna distinguere due aspetti del servizio: la descrizione astratta, che non dipende dalla piattaforma su cui il servizio è fornito, e la descrizione delle implementazioni concrete, che sono legate strettamente alle piattaforme utilizzate e a tutti gli aspetti pratici (ad esempio l’URL con cui è possibile trovare il servizio). La distinzione serve a favorire il riutilizzo delle definizioni astratte in caso di nuove implementazioni concrete. Lo schema XML di WSDL può essere consultato all’indirizzo http://schemas.xmlsoap.org/wsdl/. 33 CP 110 F O C U S Servizi Web in un documento WSDL sono <import> e <type>. Il primo LISTATO 1 Il sorgente HTML utilizzato per chiamare Abysal SendEmail consente di includere altri documenti WSDL, per consentire una <html> maggiore leggibilità delle descri<head> zioni più lunghe e complesse, il <title>Test di un Web Service</title> secondo consente di definire tipi <script> di dato. I tipi di dato possono function send_email() essere definiti utilizzando la sin{ var uri_post = “http://www.abysal.com/abysal_webdtp”; tassi di XML Schema ma questa var soap_action = “http://www.abysal.com/DoTPCall” + scelta, seppur fortemente consi“#abysal_program=soapmail&abysal_environment=soap”; gliata, non è un vincolo. var xreq = “<e:Envelope xmlns:e=’http://schemas.xmlsoap.org/soap/envelope/’>\n” + Dopo aver definito i legami con “ <e:Body>\n” + altri documenti - con l’elemento “ <m:SendEmail xmlns:m=’http://www.abysal.com/Abysal-webDTP’>\n” + <import> - e i tipi di dato com“ <From>” + From .value + “</From>\n” + “ <FromAddress>” + FromAddress.value + “</FromAddress>\n” + plessi da utilizzare - mediante “ <To>” + To .value + “</To>\n” + <type> - si passa a descrivere in “ <ToAddress>” + ToAddress .value + “</ToAddress>\n” + maniera astratta il servizio. “ <Subject>” + Subject .value + “</Subject>\n” + “ <MsgBody>” + MsgBody .value + “</MsgBody>\n” + In astratto di un servizio interes“ </m:SendEmail>\n” + sano fondamentalmente due cose: “ </e:Body>\n” + quali messaggi vengono scambiati “</e:Envelope>”; tra il servizio e l’applicazione che var hreq = new ActiveXObject( “Microsoft.XMLHTTP” ); lo utilizza e quali operazioni possono essere portate a termine SOAPmsg.value = xreq; mediante questi messaggi. hreq.open( “POST”, uri_post, false ); I messaggi vengono definiti hreq.setRequestHeader( “Content-Type”, “text/xml” ); mediante l’elemento <message>. hreq.setRequestHeader( “SOAPAction”, soap_action ); hreq.send( xreq ); Ogni messaggio è costituito da una o più parti. Ogni parte si defiSOAPret.value = hreq.responseText; nisce con l’elemento <part>. var dom = new ActiveXObject( “MSXML.DOMDocument” ); L’altro elemento che deve essere var bret = dom.loadXML( hreq.responseText ); utilizzato per descrivere in astratto var val = dom.selectSingleNode( “//ReturnCode” ).text; un servizio è <portType>. if (val==”0”) Un Port Type non è altro che Risultato.value = val + “ - E-mail Inviata!”; una serie di operazioni, ognuna else delle quali utilizza uno o più Risultato.value = val + “ - Errore!”; } dei messaggi definiti in prece</script> denza. Le operazioni si definiscono con l’elemento <opera</head> tion>. Esistono quattro tipi di <body > <font face=”COURIER” size=”3”> operazioni: One-Way, RequestResponse, Solicit-Response e <h1 align=”center” >Test di un Web Service</h1> <BR> Notification. Le operazioni di tipo Da.....: <input name=”From” size=”40”></input> One-Way e Notification preveIndirizzo Mittente....: <input name=”FromAddress” size=”40”></input> <BR> dono l’utilizzo di un solo messagA......: <input name=”To” size=”40”></input> Indirizzo Destinatario: <input name=”ToAddress” size=”40”></input> <BR> gio che può essere diretto dalOggetto: <input name=”Subject” size=”110”></input> <BR> l’applicazione al servizio (OneTesto..: <textarea name=”MsgBody” cols=”100” rows=”4”></textarea> Way) oppure dal servizio all’ap<BR> <input type=”button” value=”Invio e-mail” onclick=”javascript:send_email()”> plicazione (Notification). Gli altri <BR> due tipi di operazione prevedono SOAPmsg: <textarea name=”SOAPmsg” cols=”100” rows=”12”></textarea><BR> due messaggi, nel caso di RequestSOAPret: <textarea name=”SOAPret” cols=”100” rows=”7” ></textarea><BR> Esito..: <input name=”Risultato”> Response l’applicazione chiede e il servizio risponde, nel caso di </font> </body> Solicit-Response succede giusto il </html> contrario. È evidente che un’operazione a due messaggi può essere sempre sostituita da due operazioni ad un solo messaggio, ma per chiarezza è Ogni documento WSDL ha come radice <defimeglio utilizzare sempre il giusto tipo di operazione. nitions> che include tutti gli altri elementi fonVediamo come si può descrivere l’implementadamentali. 34 zione concreta di un servizio Web. I primi due elementi che possono essere incontrati CP 110 Prima di tutto si definiscono i binding, vale FIGURA 1 Un esempio della pagina HTML utilizzata per testare Abysal SendEmail a dire le implementazioni di un Port Type astratto con un protocollo reale. Ovviamente uno stesso Port Type può avere più binding con diversi protocolli. L’elemento <binding> include un sotto-elemento <operation> per ogni operazione definita nel Port Type che implementa. Definendo il binding si descrive la struttura fisica dei messaggi che devono viaggiare tra il servizio e l’applicazione che lo utilizza. Nel prossimo paragrafo vedremo un esempio in cui il binding è stato realizzato con SOAP. Una volta descritta l’implementazione concreta dei messaggi resta solo da dire dove si trova il servizio, definito mediante l’elemento <service>. La localizzazione fisica del servizio è detta Port ed è definita mediante l’elemento <port>. Ovviamente lo stesso servizio può essere dislocato a più indirizzi, dunque l’elemento <service> può avere più sotto-elementi <port>. Ricapitolando: prima definiamo astratta<message name=”SendEmailInput”> mente il servizio dicendo di quali operazioni si com<part name=”From” type=”xsd:string”/> pone e quali messaggi devono essere scambiati, <partname=”FromAddress” type=”xsd:string”/> tutto questo prende il nome di Port Type. Poi dichia<part name=”To” type=”xsd:string”/> riamo che il servizio è fatto concretamente di uno <part name=”ToAddress” type=”xsd:string”/> o più Port, fatti ad immagine e somiglianza del <part name=”Subject” type=”xsd:string”/> Port Type, e per ogni Port diciamo a quale indirizzo <part name=”MsgBody” type=”xsd:string”/> si trova e a quale binding si riferisce. Per ogni bin</message> ding dichiariamo il protocollo da utilizzare e quindi descriviamo la struttura dei messaggi. In effetti, questo messaggio non fa altro che pasNel prossimo paragrafo vediamo un esempio di sare i parametri. Si può notare che per definire il WSDL per un servizio effettivamente disponibile in tipo di dati dei parametri si è ricorso ad un tipo rete. Vedremo anche come chiamare il servizio da standard di XML Schema. Il secondo messaggio è una pagina HTML. l’output del sistema Per esempio… Per trovare un esempio reale di WSDL basta andare su http://www.xmethods.net e scegliere un servizio. Il servizio che vedremo consente di inviare messaggi di posta elettronica, è fornito dalla Abysal e si trova nella lista dei servizi di Xmethods con il nome SendEmail. Mediante il link si arriva alla pagina descrittiva del servizio in cui è possibile trovare varie informazioni anche sull’azienda che lo fornisce, il link per il documento WSDL ed una pagina HTML per testare il servizio. Ho apportato qualche modifica alla pagina HTML per togliere tutto il codice superfluo e mettere in evidenza i messaggi SOAP che vengono scambiati tra il codice javascript chiamante ed il servizio. Un esempio di esecuzione della pagina HTML è visualizzato in Figura 1 mentre il codice sorgente della pagina può essere letto in Listato 1 e scaricato dal sito Ftp di Infomedia. Il documento WSDL è riportato in Listato2. Vengono definiti due messaggi, il primo è di input al servizio: <message name=”SendEmailResponse”> <part name=”ReturnCode” type=”xsd:int”/> </message> un codice di ritorno che vale 0 se la e-mail è stata inviata correttamente. Dopo i messaggi si definisce il Port Type: <portType name=”AbysalEmailPortType”> <operation name=”SendEmail”> <input message=”tns:SendEmailInput”/> <output message=”tns:SendEmailResponse”/> </operation> </portType> Si tratta di una sola operazione di tipo RequestResponse. Passiamo alla descrizione dell’implementazione concreta. Iniziamo dal binding dove nella linea <soap:binding style=”rpc” transport=”http://schemas.xmlsoap.org/ soap/http”/> 35 CP 110 F O C U S Servizi Web si legge che, per la trasmissione dei messaggi, sarà utilizzato SOAP inviato via HTTP. RPC (Remote Procedure Calling) è un protocollo per le chiamate remote basato, appunto, su messaggi XML inviati via HTTP. Dopo il binding si definisce il servizio: <service name=”AbysalEmailService”> <port name=”AbysalEmailPort” binding=»interface:AbysalEmailBinding»> <soap:address location=”http://www.abysal.com/abysal_ webdtp”/> </port> </service> Cominciando dal basso, nel body della pagina HTML vengono creati i campi che servono per l’input e per l’output del servizio. A parte i campi utilizzati per inviare la e-mail (descrizione ed indirizzo del mittente, descrizione ed indirizzo del destinatario, oggetto e corpo della e-mail), ho aggiunto dei campi per visualizzare il messaggio SOAP inviato al servizio (SOAPmsg), il messaggio SOAP di risposta del servizio (SOAPret) e l’esito dell’invio. Passiamo al semplice codice javascript. All’inizio vengono dichiarate delle variabili ed inizializzate con l’indirizzo cui mandare la richiesta e con il tipo di richiesta da inviare. Poi viene costruito il messaggio SOAP da inviare. Dopo avere esposto a video il messaggio di richiesta, c’è l’istruzione var hreq = new ActiveXObject(“Microsoft.XMLHTTP”); dove si assegna la location all’unico Port definito. Analizziamo ora brevemente il codice HTML. che definisce un oggetto ActiveX che sarà utiliz- LISTATO 2 La descrizione di Abysal SendEmail realizzata in WSDL <?xml version=”1.0” encoding=”UTF-8” ?> <definitions name=”AbysalEmailService” xmlns=”http://schemas.xmlsoap.org/wsdl/” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” targetNamespace=”http://www.abysal.com/WSDLFiles/AbysalEmail.wsdl” xmlns:interface=”http://www.abysal.com/WSDLFiles/AbysalEmailwsdl” xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/”> <documentation>Servicio de envio de e-mail bajo el sistema Abysal-webDTP de Abysal Systems, S.A.</documentation> <message name=”SendEmailInput”> <part name=”From” type=”xsd:string”/> <part name=”FromAddress” type=”xsd:string”/> <part name=”To” type=”xsd:string”/> <part name=”ToAddress” type=”xsd:string”/> <part name=”Subject” type=”xsd:string”/> <part name=”MsgBody” type=”xsd:string”/> </message> <message name=”SendEmailResponse”> <part name=”ReturnCode” type=”xsd:int”/> </message> <portType name=”AbysalEmailPortType”> <operation name=”SendEmail”> <input message=”tns:SendEmailInput”/> <output message=”tns:SendEmailResponse”/> </operation> </portType> <binding name=”AbysalEmailBinding” type=”tns:AbysalEmailPortType”> <soap:binding style=”rpc” transport=”http://schemas.xmlsoap.org/soap/http”/> <operation name=”SendEmail”> <soap:operation soapAction=”http://www.abysal.com/DoTPCall#abysal_program= soapmail&abysal_environment=soap”/> <input> <soap:body use=”encoded” namespace=”http://www.abysal.com/Abysal-webDTP” encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”/> </input> <output> <soap:body use=”encoded” namespace=”http://www.abysal.com/Abysal-webDTP” encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”/> </output> </operation> </binding> <service name=”AbysalEmailService”> <documentation>Servicio de envio de e-mail bajo Abysal-webDTP</documentation> <port name=”AbysalEmailPort” binding=”interface:AbysalEmailBinding”> <soap:address location=”http://www.abysal.com/abysal_webdtp”/> </port> </service> </definitions> 36 CP 110 zato per inviare il messaggio via HTTP. Il messaggio viene inviato con le linee hreq.open( “POST”, uri_post, false ); hreq.setRequestHeader( “Content-Type”, “text/xml” ); hreq.setRequestHeader( “SOAPAction”, soap_action ); hreq.send( xreq ); A questo punto il messaggio SOAP di risposta è contenuto nella proprietà responseText dell’oggetto hreq, si tratta di un documento XML. Dopo avere messo a video il messaggio lo analizziamo per leggere il codice di ritorno che è incluso nell’elemento <ReturnCode>. Per cercare nel documento XML si definisce un oggetto DOM, si chiama poi il metodo di ricerca dom.selectSingleNode() passando il percorso Xpath “//ReturnCode”, i simboli “//” consentono di navigare l’albero di decomposizione DOM del documento verso il basso scendendo di un numero imprecisato di livelli. Alla fine viene visualizzato un messaggio di successo oppure di errore secondo il valore del codice di ritorno. Con WSDL ci fermiamo qui, nel prossimo paragrafo conosceremo UDDI, utile strumento per la ricerca dei Web service. XML si realizza mediante i quattro elementi <businessEntity>, <businessService>, <bindingTemplate> e <tModel>. Il legame gerarchico tra le informazioni è abbastanza intuitivo: una Business Entity può fornire più Business Service, ogni Business Service può avere più Binding Template ed ogni elemento può fare riferimento ad un tModel. Prima di continuare bisogna fare un po’ di luce sui tModel. Un tModel è un documento generico che può descrivere qualunque cosa. Le informazioni definite in un tModel sono metadati, quindi ci dicono come sono strutturati i dati di un certo elemento. È un modo generico per consentire la descrizione di qualunque servizio non sapendone nulla a priori. FIGURA 2 La logica di funzionamento di UDDI A caccia di Web service UDDI (Universal Description, Discovery and Integration) è un progetto promosso da alcuni big della Information Tecnology, tra cui Microsoft ed IBM, per favorire la nascita di un registro globale dei Web service disponibili in rete e delle aziende che li forniscono. Si può pensare ad UDDI come alle pagine gialle dei fornitori di Web service, con la differenza che le informazioni conservate nel registro riguardano anche i prodotti offerti e non solo le aziende che li offrono. Il progetto UDDI si differenzia dagli altri progetti per la definizione di standard perché si spinge un passo oltre. UDDI non si propone solo di definire le specifiche del registro globale (denominato UDDI business registry), ma di realizzarlo concretamente. La logica di funzionamento di UDDI è rappresentata in Figura 2. Per ottenere la massima compatibilità con tutti i sistemi, UDDI è stato realizzato con XML e SOAP. Lo schema XML di UDDI può essere consultato all’indirizzo http://www.uddi.org/schema/uddi_1.xsd. Cerchiamo di capire come sono organizzate le informazioni in UDDI e come sia possibile leggere e modificare i dati del registro. Le informazioni registrate nell’UDDI business registry sono suddivisibili in quattro gruppi: informazioni sull’azienda fornitrice, informazioni generiche sui servizi offerti, informazioni sulla localizzazione fisica dei servizi e specifiche tecniche per l’utilizzo dei servizi. Tutto questo in un documento Più avanti vedremo un esempio di tModel che rappresenta il legame tra UDDI e WSDL. L’accesso ai dati dell’UDDI business registry può avvenire in due modi: consultando uno dei motori di ricerca disponibili in rete oppure utilizzando da programma l’API di UDDI. Un esempio di motore di ricerca può essere visto all’indirizzo http://www.uddi.org/ find.html dove è possibile scegliere il registro in cui effettuare la ricerca (sono disponibili i registri di IBM e Microsoft) e, in un secondo passo, impostare i criteri per trovare un’azienda o un servizio. Nella stessa modalità on-line è possibile anche effettuare la registrazione di una nuova azienda o servizio. Se la ricerca o la modifica dei dati deve essere effettuata da un programma bisogna utilizzare l’interfaccia programmabile (API) di UDDI. L’API di UDDI è un insieme di interfacce divise in quattro categorie: per la ricerca dei dati sono disponibili le chiamate di tipo find_xx (per la ricerca delle informazioni relative a servizi di cui non si conosce il codice identificativo) e get_xx (per le informazioni relative a servizi di cui si conosce già il codice identificativo). Per la modifica dei dati sono disponibili le chiamate save_xx (per modificare) e delete_xx (per cancellare). Ovviamente l’accesso ai dati è condizionato da una procedura di sicurezza che consente le modifiche 37 CP 110 F O C U S Servizi Web solo a chi è autorizzato. Questo conclude la panoramica generale su UDDI, ora vediamo come UDDI e WSDL possono lavorare insieme. Dove l’elemento <categoryBag> contiene le informazioni con cui gli altri elementi di UDDI possono fare riferimento a questo tModel, chiudendo il cerchio. Le chiavi utilizzate in UDDI per i riferimenti tra elementi sono stringhe alfanumeriche simili a quelle che si utilizzano per registrare il software. Mettiamo insieme i pezzi Abbiamo visto che WSDL serve a descrivere i Web service. Abbiamo poi visto che l’UDDI business registry contiene le descrizioni dei Web service. A questo punto è logico chiedersi se è possibile utilizzare WSDL per descrivere un servizio nel registro di UDDI. Ovviamente la risposta è sì. Vediamo come. WSDL descrive come deve essere utilizzato il servizio Ricordiamo che un documento WSDL può essere diviso in più documenti distinti collegati tra loro mediante l’elemento <import>. Si può dunque pensare di creare un documento WSDL per realizzare solo la descrizione astratta del servizio. In UDDI noi registreremo con WSDL solo le descrizioni astratte dei servizi. Le descrizioni astratte dei servizi, realizzate con WSDL, saranno registrate in UDDI sotto la forma di tModel. In un secondo momento saranno poi creati dei <bindingTemplate> per descrivere le implementazioni concrete dei servizi. In UDDI un tModel che descrive un servizio mediante WSDL viene classificato con il tipo “wsdlspec”. Il tModel non include l’intero documento WSDL ma solo un puntamento al documento. Il puntamento si realizza mediante l’elemento <overviewDoc> il cui sottoelemento <overviewURL> deve contenere l’URL del documento WSDL. Ad esempio: 38 CP 110 <tModel attributi > <name>Abysal SendEmail</name> <description>descrizione generica </description> <overviewDoc> <description>descrizione generica </description> <overviewURL>un certo URL </overviewURL> </overviewDoc> <categoryBag> <keyedReference tModelKey=”chiave” keyName=”uddi-org:types” keyValue=”wsdlspec”/> </categoryBag> </tModel> Conclusioni I Web service sono uno strumento sempre più ampio e potente a disposizione dei produttori di applicazioni basate su Internet. Per sfruttare al meglio questo strumento, è necessario avere a disposizione un indice dei servizi disponibili e le specifiche per l’utilizzo di ogni singolo servizio. UDDI e WSDL rispondono a quest’esigenza. Il primo fornisce un registro globale dei servizi e delle aziende che li forniscono, l’ultimo è un linguaggio da utilizzare per realizzare le specifiche per l’utilizzo di un servizio. Abbiamo visto anche come mettere insieme i due strumenti. In Bibliografia e nei Riferimenti è possibile trovare molte altre informazioni sugli argomenti trattati. BIBLIOGRAFIA [1] V. Vasudevan, “A Web Services Primier”, XML. com, 2001. [2] G. Glass, “The Web services (r)evolution, Part 1, 2, 3, 4”, IBM developerWorks, 2000/2001. [3] M. Gudgin, T. Ewald, “Pork Barrel Protocols”, XML.com, 2001. [4] M. Gudgin, M. Hadley, JJ. Moreau, H.F. Nielsen, “SOAP Version 1.2 Part 1,2”, W3C, 2001. [5] E. Christensen, F. Burbera, G. Meredith, S. Weerawarana, “Web Services Description Language 1.1”, W3C, 2001. [6] U. Ogbuji, “Using WSDL in SOAP applications”, IBM developerWorks, 2000. [7] UDDI, “UDDI Executive White Paper”, UDDI. org, 2000. [8] UDDI, “UDDI Technical White Paper”, UDDI. org, 2000. [9] F. Curbera, D. Ehnebuske, D. Rogers, “Using WSDL in a UDDI Registry 1.05”, UDDI.org, 2001. RIFERIMENTI [10] [11] [12] [13] [14] http://www.w3.org http://www.uddi.org http://www.xml.com http://www-106.ibm.com/developerworks http://www.xmethods.net