Introduzione
Come abbiamo visto ([1]), JAXM consente di definire
in modo programmatico messaggi SOAP e di inviarli tramite
HTTP secondo un paradigma di fire&forget (anche
detto Oneway) o di request/response. Come noto, le specifiche
SOAP 1.1 contengono al loro interno indicazioni di come
é possibile utilizzare messaggi che utilizzino
questo formato, non solo per la trasmissione di informazioni,
ma più organicamente come mezzo per implementare
sistemi distribuiti basati su XML.
A
basso livello
Per
sistema distribuito basato su messaggi XML si può
immaginare qualche cosa di simile ad una applicazione
basata su RMI, ma che utilizzi XML come protocollo di
filo. In applicazioni RMI, un server espone dei servizi,
mostrati come metodi di oggetti remoti, ed il client
utilizza questi servizi chiamando le interfacce remote.
Questo avviene in modo trasparente rispetto allo sviluppatore.
L'inizio del processo avviene sul lato client, ma l'elaborazione
avviene sul server: questo é il concetto fondamentale
delle applicazioni distribuite (ove ci siano più
server, o del paradigma client/server se i livelli sono
solo due). Come noto RMI si basa su JRMP per implementare
il protocollo di filo e cioé per definire tutte
quelle meta-informazioni necessarie a far si che la
comunicazione bidirezionale avvenga con successo (anche
se é disponibile anche il protocollo IIOP - quello
nativo CORBA).
Nel mondo dei Web Services, SOAP é il "protocollo
di filo" più diffuso delle applicazioni
distribuite (ne esistono altri, come XML-RPC) e SOAP
RPC é quella parte di specifiche SOAP che definisce
le semantiche di comunicazione.
JAXM é un po' l'API "a basso livello"
per il protocollo SOAP, rappresenta dunque l'implementazione
del protocollo di filo.
Come tutte le API a basso livello, richiede più
lavoro per ottenere le cose. Come si é visto
nell'articolo del mese precedente (e come si vedrà
nelle successive puntate della serie dedicata allo sviluppo
di una chat basata su SOAP la cui prima parte é
pubblicata in questo stesso numero), é necessario
specificare tramite opportune chiamate a metodi, ciascun
elemento del messaggio SOAP, dai tag Envelope, Header
e Body, ai namespace, all'encoding ed anche alle intestazioni
HTTP come SOAPAction.
La buona notizia é che come RMI semplifica notevolmente
il lavoro nello sviluppo di applicazioni distribuite
tradizionali, nel mondo dei Web Services Java, lo stesso
ruolo lo ricopre JAX-RPC.
A prima vista si sarebbe potuto pensare che JAXM e JAX-RPC
si sovrapponessero, in quanto SOAP, che sta alla base
di entrambe, definisce sia standard di messaggio che
protocolli di RPC.
La differenza é che JAXM consente semplicemente
di creare, consumare ed inviare messaggi SOAP mentre
JAX-RPC si occupa degli aspetti ad alto livello e cioé
di mappare interfacce e servizi Java come servizi Web.
JAX-RPC é dunque qualche cosa di più vasto,
che si può appoggiare a JAXM per l'implementazione
di SOAP (in realtà la Early Access 1 di JAX-RPC
utilizza Apache SOAP, anche se é facile aspettarsi
che in futuro l'implementazione venga allineata all'uso
di JAXM), ma che si occupa degli aspetti più
complessi legati a problematiche di RPC. Inoltre queste
API non sono legate solamente a SOAP ma potrebbero utilizzare
protocolli XML di filo diversi da questo.
Basta un file WSDL...
La caratteristica interessante di JAX-RPC é che
può utilizzare, come file di definizione del
servizio, un documento WSDL (Web Services Definition
Language - si veda [2] e [3]). Un file di definizione
WSDL contiene tutte le informazioni necessarie per definire
gli input, gli output e la destinazione fisica del servizio.
Tutte queste informazioni sono sufficienti per eseguire
una mappatura WSDL/Java, che viene eseguita da codice
generato dal tool xrpcc.
(Un esempio di file WSDL é presente nel listato
1).
Listato
1. Un esempio di WSDL
<?xml
version="1.0"?>
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<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>
<message
name="GetLastTradePriceInput">
<part name="body" element="xsd1:TradePriceRequest"/>
</message>
<message
name="GetLastTradePriceOutput">
<part name="body" element="xsd1:TradePrice"/>
</message>
<portType
name="StockQuotePortType">
<operation name="GetLastTradePrice">
<input message="tns:GetLastTradePriceInput"/>
<output message="tns:GetLastTradePriceOutput"/>
</operation>
</portType>
<binding
name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service
name="StockQuoteService">
<documentation>My first service</documentation>
<port name="StockQuotePort" binding="tns:StockQuoteBinding">
<soap:address location="http://example.com/stockquote"/>
</port>
</service>
</definitions>
Questo
file, dato come input al tool xrpcc di JAX-RPC (non
fa parte delle specifiche, ma solo della reference implementation),
produce gli stub e dei ties (simili a skeleton RMI)
per l'implementazione della comunicazione SOAP client/server.
Il tool xrpcc ci porta alla memoria quella che potrebbe
essere considerata la sua controparte nella tecnologia
RMI: rmic.
L'architettura che si ottiene é esemplificata
in Figura 1.
Figura 1 - architettura client/server JAX-RPC
Il
codice sorgente prodotto (pure Java) utilizza il runtime
JAX-RPC e fornisce una rappresentazione tramite interfacce
Java del servizio web. Il tool xrpcc si occupa inoltre
di compilare i sorgenti: i binari server prodotti potranno
poi essere inseriti in un container JAX-RPC (nel JWSDP
ea2 é Tomcat con la RI di JAX-RPC) insieme ad
un file di proprietà che definsce alcuni parametri
di funzionamento.
I binari client potranno essere invece utilizzati sul
lato client per interfacciare il servizio web come se
fosse una classe Java.
Lo strumento xrpcc può generare solo gli stub,
solo i ties o entrambe le cose, in funzione del fatto
che si stia sviluppando un client per un servizio web,
oppure la sua implementazione, oppure tutti e due.
Generare il codice
Il file WSDL deve essere fornito ad xrpcc tramite un
altro file XML intermedio che indica informazioni aggiuntive
necessarie alla generazione del codice, quale il package
di destinazione. Un esempio é presente nel Listato
2.
Listato
2. Esempio file configurazione xrpcc (1)
<?xml
version="1.0" encoding="UTF-8"?>
<configuration
xmlns="http://java.sun.com/jax-rpc-ri/xrpcc-config">
<wsdl name="StockQuoteModel"
location="file:sq.wsdl.xml"
packageName="stockQuote">
</wsdl>
</configuration>
Per
generare il codice é sufficiente invocare il
comando xrpcc:
xrpcc
-both -keep file.xml
Le
opzioni hanno questo significato: both indica di generare
sia gli stub che i tie, mentre keep indica di non cancellare
i file sorgenti dopo la compilazione, questo é
utile per "curiosare" nei sorgenti generati
da xrpcc. L'ultimo parametro del comando é il
nome del file di lancio (quello presente nel listato
2).
L'esempio
WSDL presente nel listato 1 é tratto dalle specifiche
WSDL.
Nota:
sono specifiche prodotte da SUN ed IBM e sottomesse
come "nota" al W3C. NON sono dunque uno
standard W3C ma semplicemente informazioni a lei
inviate e che questo ente ritiene "interessanti"
(le ha riconosciute come "nota"). Tutto
questo materiale (insieme a SOAP 1.2, XML Protocol
e tutte le attività connesse) rientreranno
nel gruppo di lavoro che W3C ha organizzato per
definire i suoi standard per i Web Services. Una
volta prodotte le specifiche finali, queste potranno
essere realmente considerate "standard",
alla stregua di HTML ed HTTP, ma non prima. |
La
brutta notizia é che, anche nell'ultima versione
disponibile "Java Web Services Development Pack"
JWSDP Early Access 2, questo file non é interpretabile
da xrpcc. La cosa é alquanto strana, visto che
la conformità ad uno standard dovrebbe partire
dalla compatibilità almeno con gli esempi presenti
nello standard stesso. Due possibili spiegazioni: la
prima é che la reference implementation (RI)
é in early access, e dunque soggetta a migliorie
prima di arrivare alla versione definitiva. La seconda:
sono tecnologie molto nuove: potrei aver sbagliato qualche
cosa! In questo caso invito i lettori a segnalarmelo:
il primo che mi indicherà l'errore, verrà
citato con onore nel prossimo numero di questa "rubrica".
Ho avuto più fortuna con altri file WSDL: il
servizio Babelfish di Altavista o il servizio per la
lettura delle vignette di Dilbert (http://www.dilbert.com)
non hanno riscontrato problemi (anche se poi dovrà
essere verificata l'effettiva funzionalità di
quanto generato). Per un interessante elenco di servizi
web, é possibile fare riferimento al sito web
www.methods.net.
Da
Java ai Web Services
Abbiamo visto come, partendo da un file di definizione
di un servizio web in formato WSDL, sia possibile generare
sia un client Java per il servizio, sia un framework
per l'implementazione del servizio lato server.
E' possibile anche l'operazione inversa: da una interfaccia
Java é possibile generare stubs, ties ed anche
il file WSDL. In questo modo diventa estremamente semplice
esporre un web service sviluppato in Java, fornendo
all'esterno il file WSDL.
Le possibilità offerte da JAX-RPC sono descritte
in figura 2
Figura 2 - generazione del codice in JAX-RPC
Anche
in questo caso lo strumento é sempre xrpcc, mentre
il file di definizione é diverso e contiene piuttosto
i riferimenti alle interfacce Java da utilizzare. Un
esempio di questo file é presente nel listato
3.
Listato 3. Esempio configurazione xrpcc (2)
<?xml
version="1.0" encoding="UTF-8"?>
<configuration
xmlns="http://java.sun.com/jax-rpc-ri/xrpcc-config">
<rmi name="StockQuoteService"
targetNamespace="http://schemas.mokabyte.it/wsdl"
typeNamespace="http://schemas.mokabyte.it/types">
<service name="StockQuoteService" packageName="stockquote">
<interface name="StockQuoteProvider"
servantName="StockQuoteImpl"/>
</service>
</rmi>
</configuration>
Il
servizio StockQuoteService a cui si riferisce il file
di configurazione di xrpcc é molto semplice.
L'interfaccia é costituita da un singolo metodo
che fornisce la quotazione dell'azione in formato float.
Il nome dell'azione é un dato di tipo String
passato come parametro.
In JAX-RPC le interfacce devono estendere java.rmi.Remote,
in modo che il compilatore xrpcc possa riconoscerle.
Ciascun metodo dovrà lanciare una eccezione java.rmi.RemoteException.
Anche per quanto riguarda le interfacce per i Web Services
JAX-RPC si riscontra una certa congruenza con RMI, cosa
senz'altro positiva.
Nonostante questo, non si può però pensare
di prendere interfacce RMI esistenti e passarle attraverso
JAX-RPC per abilitare ai Web Services una applicazione
RMI esistente, questo perché JAX-RPC ha limitazioni,
sia intrinseche, ma soprattutto legate a SOAP, che non
consentono di implementare tutte le funzionalità
di una classica applicazione distribuita RMI. In particolare
non é disponibile la garbage collection distribuita
e la gestione degli stati persistenti.
Conclusioni
L'insieme delle specifiche che formano JAX-RPC forniscono
una mappatura a due vie: da WSDL a Java e da Java a
WSDL. Questo consente allo sviluppatore di trattare
un servizio web come se questo fosse una classe Java
"tipo" RMI. Inoltre, consente con la stessa
semplicità, di esporre classi Java come servizi
Web.
L'incremento di produttività dato da questi automatismi,
se confrontato al lavoro richiesto per implementare
le stesse funzionalità con JAXM, é notevole.
D'altro canto, come per tutti i meccanismi che forniscono
automatismi, una piccola modifica a livello di interfaccia
può comportare anche una grande variazione ai
livelli più bassi. Per questo motivo é
necessario porre attenzione all'uso che si fa degli
strumenti non sottovalutando le tecnologie sottostanti
che, anche se nascoste, rappresentano un cuore importante
da non dimenticare.
Bibliografia
[1] Massimiliano Bigatti - "Web Services (6) -
Java API for XML Messaging (JAXM)", Mokabyte, Marzo
2002
[2] Specifiche WSDL - http:/www.w3c.org/TR/wsdl
[3] Massimiliano Bigatti "Web services (2):
capire i WSDL", Mokabyte, Giugno 2001
Massimiliano
Bigatti è SUN Certified Enterprise Architect
for Java Platform, Enterprise Edition Technology. Si
occupa di architetture applicative basate su Java ed
Internet, technical writing e musica rock
|