Creare web services client con Eclipse, AXIS2 e Tomcat Rosario Turco
In questa seconda parte esaminiamo come realizzare un client di un web service con Eclipse, Axis2 e Tomcat. Per testare un web service, di solito, usiamo il comodo SOAPUI, ma quando dobbiamo realizzare un applicativo client di un web service, dobbiamo rimboccarci le maniche e farlo. Un client è un po’ più complesso a realizzarsi rispetto alla parte server, anche perché occorre conoscere AXIOM e le varie primitive in gioco; inoltre dobbiamo decidere se vogliamo un servizio sincrono bloccato (usiamo solo lo stub) o uno asincrono non bloccato (oltre allo stub dobbiamo usare anche la callback). Se usate un buon IDE è chiaro che vi semplificate la vita e aumentate la vostra velocità di sviluppo (cosa a cui dovreste sempre mirare), diminuendo nel contempo le possibilità di errore, ma dovete sapere cosa fare e bene. Eclipse Helios vi da una buona mano con i suoi plug-in Axis2 e non è dedicato a nessuna piattaforma di sviluppo particolare. Se usate Tomcat in particolare, Axis2 e Axiom sono un must per i web service, service, per cui vediamo come si procede. Se il web service da usare è esistente e attivo (sul vostro PC o su un sistema remoto), abbiamo due possibilità sfruttare il servizio startato su una URL, che vedremo, oppure usare la WSDL fornitoci (il procedimento è simile). Supponiamo semplicemente che il servizio è un servizio di conversione di temperature da gradi Farenheit a Celsius e viceversa; avremmo potuto usare il classico HelloWorld + nome della persona, o un altro servizio classico che fa le quattro operazioni aritmetiche. Insomma qualunque cosa che ci risponda una stringa ad esempio o anche un metodo con più input, cosa che spiegheremo dopo il caso semplice, se no dov ’è il valore aggiunto? Supponiamo che il sorgente del web service startato sia come segue: package wtp; public class Converter
{ public float celsiusToFarenheit ( float celsius )
{ return (celsius * 9 / 5) + 32;
} public float farenheitToCelsius ( float farenheit )
{ return (farenheit - 32) * 5 / 9;
} }
1
Con Eclipse facciamo File->New->Other->Web Service->Web Service Client->Next. Su Service Definition mettiamo la url che ci hanno comunicato del web service come in figura.
Scegliamo poi il nostro server Tomcat 6.0 o superiore, mettiamo Apache Axis2 come Web service runtime, su Client project inseriamo il nome del progetto ad esempio Axis2WSTest o qualsiasi altro e diamo ok ottenendo la figura. Fate Next e lasciate al momento il valore di default. Per curiosità potreste anche generare un test case con JUNIT, ma non è utile a scrivere il vostro client: è uno skeleton generalizzato per vedere se funziona il client, ma non vi da i risultati.
In automatico vi escono i valori di figura e scegliamo di generare un client sia per modalità asincrona che sincrona, anche se lo svilupperemo in modalità sincrona, mettendoci magari un timeout.
2
Fate Next e nel progetto vi ritroverete due file generati come in figura: ConverterCallbackHandler.java e ConverterStub.java
Adesso il primo consiglio è farvi una lettura del file di stub, che è quello che permette la comunicazione remota con il web service reale, è un proxy locale al web service remoto. Di esso ci interessano i tipi dichiarati: la classe stessa ConverterStub, il tipoNomeMetodoRemoto che assomiglia cioè al nome del metodo remoto, nel nostro caso CelsiusToFarenheit e il tipo della response CelsiusToFarenheitResponse. Ora scriviamo il Client ConverterClient.java; da Eclipse sul package wtp facciamo New->Class e come nome classe mettiamo ConverterClient e gli facciamo generare il main e poi aggiungiamo delle righe. package wtp; import java.rmi.RemoteException; import org.apache.axis2.AxisFault; import wtp.ConverterStub.CelsiusToFarenheit; import wtp.ConverterStub.CelsiusToFarenheitResponse; public class ConverterClient { public static void main(String[] args) { final int CLIENT_TIMEOUT = (10*60*1000); float celsiusValue = 100; try {
ConverterStub stub = new ConverterStub(); stub._getServiceClient().getOptions().setTimeOutInMilliSeconds(CLIENT_TIMEOUT); CelsiusToFarenheit c2f = new ConverterStub.CelsiusToFarenheit(); c2f.setCelsius(celsiusValue); CelsiusToFarenheitResponse res = stub.celsiusToFarenheit(c2f); System.out.println("Celsius .println("Celsius : "+celsiusValue+ "+celsiusValue+" " = "+ "+"Farenheit : "+res.get_return()); "+res.get_return()); } catch (AxisFault e) {
3
e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
Per assegnare i valori, come vediamo, dobbiamo usare i metodi set che troviamo nello Stub, come setCelsius. Proviamo un attimo quello che abbiamo creato. Teniamo startato il Tomcat, su cui abbiamo dichiarato la parte Axis2, poi facciamo selezionando il Client col tasto destro del mouse Run As->Java Application e da console vediamo il risultato. Io ho startato sullo stesso server Tomcat, sia il web service server che la parte client. Ovvero ho avviato Tomcat, poi per il web service server ho selezionato il progetto e tasto destro del mouse Run As -> Run On Server->Finish e ottenuto la prima videata del servizio attivo.
Ora starto il client, selezionando il nome del sorgente e tasto destro del mouse Run As -> Java Application (ho scritto il main e faccio la stampa del valore ritornato: avevo chiesto 100 °C a quanti Farenheit corrispondono). In console vedo il risultato:
Ok funziona, andiamo oltre.
4
Se ho, invece, nel web service esposto, un metodo con più “parameter” in input come faccio? E ’ semplice, nello stub troverete un metodo set per ogni input. Per cui a quel punto dovrete usare la variabile del tipoNomeMetodoRemoto (nel nostro caso c2f) e settare con essa ogni parametro cioè fare: c2f.setCelsius(variabile_col_valore); c2f.setFarenheit(variabile_col_valore); etc. Il metodo visto è sincrono/bloccato. Se avessimo usato l ’asincrono non bloccato avremmo dovuto usare anche la callback e registrare il client con l a callback class. Un esempio di completamento della callback è il seguente: package org.example.math; import org.example.math.MathServiceStub.AddResponse; public class CallBack extends MathServiceCallbackHandler { private boolean complete = false; public void receiveResultAdd(AddResponse result) { System.out.println("Result in Callback " + result.getAddResponse().getResult()); complete = true; } public boolean isComplete() { return complete } }
Mentre il client potrebbe essere public static void main(String[] args) MathServiceStub stub try { stub = new MathServiceStub("http://localhost:8080/axis2/services/mathService"); MathServiceStub.Add add = MathServiceStub.Add(); MathServiceStub.MathInput input = new MathServiceStub.MathInput(); input.setX(3); input.setY(5) add.setAdd(input); CallBack cb = new CallBack(); stub.startAdd(add, cb); while(!cb.isComplete()) { System.out.println("Do Something"); } } catch (AxisFault e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } }
Tutto chiaro? Alla prox.
5