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&amp;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