|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Feb 2008
Città: Bari
Messaggi: 36
|
-Official guide - Web Services con Axis (Diffidate dalle imitazioni)
Ciao a tutti, siamo tre studenti del Dipartimento di Informatica dell’Università di Bari. Recentemente per via di un progetto a cui abbiamo lavorato, ci siamo ritrovati a combattere con una serie di problematiche riguardanti il mondo dei web service. In realtà, parlare del “mondo dei web service” è un po’ esagerato, poiché i problemi si sono presentati lavorando alla creazione dei web service in java mediante l’utilizzo di axis.
Chi come noi ha cominciato a lavorare con axis senza avere la minima idea di come questo strumento permetta la generazione dei web service, sicuramente avrà mosso i primi passi cercando sul web informazioni utili a riguardo. Basta provare a fare una semplice ricerca per notare la quantità di guide che offrono spiegazioni su come “creare web service con axis in pochi minuti” oppure “come creare un web service in java semplicemente cambiando l’estensione da java a jws”. Tutto questo fa pensare a qualcosa di estremamente semplice ed intuitivo che non potrebbe dare alcun tipo di problema nemmeno ad un neofita di axis. Questa sospetta osservazione può avere un fondo di verità se il nostro web service si limiti a restituirci la stringa “Ciao Peppino” se passiamo il parametro “Peppino” oppure che ci restituisca 6 se noi gli passiamo due numeri da moltiplicare, cioè 2 e 3. Ma è davvero difficile trovare qualcuno a cui possa interessare qualcosa di questo tipo. Per questo i nostri problemi sono nati quando abbiamo cominciato a chiederci come fosse stato possibile generare dei web service, a partire dal nostro progetto in java strutturato su più package contenenti diverse classi. Purtroppo le tante guide da noi cercate, lette e rilette proprio non hanno preso in considerazione questo tipo di problematiche. Per questo motivo, dopo aver “combattuto” e “sconfitto” axis, abbiamo deciso di pubblicare questa guida che potrà tornare utile a molti di voi. PROBLEMATICHE DI BASE Prima di descrivere un esempio pratico, è bene fare chiarezza in maniera preventiva sui possibili e frequenti problemi che possono sorgere con axis.
Codice:
set CATALINA_HOME=C:\Programmi\Apache Software Foundation\Tomcat 6.0; set AXIS_HOME=C:\Programmi\Apache Software Foundation\Tomcat 6.0\webapps\axis; set AXIS_LIB=C:\Programmi\Apache Software Foundation\ Tomcat 6.0\webapps\axis\WEB-INF\lib set CLASSPATH=%CLASSPATH%;%AXIS_LIB%\activation.jar;%AXIS_LIB%\axis.jar; %AXIS_LIB%\axis-ant.jar;%AXIS_LIB%\commons-discovery-0.2.jar;%AXIS_LIB%\ commons-logging-1.0.4.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\ log4j-1.2.8.jar;%AXIS_LIB%\mail.jar;%AXIS_LIB%\saaj.jar;%AXIS_LIB%\ wsdl4j-1.5.1.jar;%AXIS_LIB%\xmlsec.jar;%AXIS_LIB%\xml-apis.jar set JAVA_HOME=C:\Programmi\Java\jdk1.6.0_17; GENERARE WEB SERVICE A PARTIRE DAL PROPRIO PROGETTO JAVA Fatte queste premesse, passiamo alla descrizione di un esempio pratico. Il caso da noi analizzato dovrebbe rispecchiare per grandi linee un comune progetto java, in ogni caso questo esempio è utile a capire con quale logica affrontare un problema di questo tipo su un progetto di qualsiasi dimensione. Perciò è bene focalizzare l’attenzione non su cosa la nostra applicazione svolga, ma solo sugli accorgimenti da dover prendere per generare web service correttamente. Supponiamo che la nostra applicazione java abbia il compito di gestire dei conti bancari; il nostro obiettivo è quello di dare la possibilità al sito web della banca X di mostrare il saldo di un determinato cliente mediante l’invocazione di un web service. Il web service in questione dovrà essere generato sfruttando i metodi per la visualizzazione del saldo già presenti nell’applicazione. Per arrivare a capire come sia possibile fare questo, bisogna partire dall’analizzare la struttura del sorgente dell’applicazione stessa: Package principale:
1° PASSO: DICHIARAZIONE DEI METODI DA TRASFORMARE IN WEB SERVICE Dalla descrizione appena formalizzata, si può notare come le uniche differenze da un qualsiasi progetto java siano da ricondurre al solo package web_services. Nel nostro caso la classe WsInterface sarà la seguente: package web_services; Codice:
public interface WsInterface { // metodo per l’autenticazione di un cliente della banca dal web public String autenticazione_web(String username, String password); // metodo per la visualizzazione del saldo di un determinato cliente public Double mostra_saldo(String username, String password, int numeroConto); } Come già accennato, la classe WebServices conterrà l’implementazione dei metodi, per questo motivo saranno presenti tutte le chiamate alle classi appartenenti al package entity, responsabile della logica di business: Codice:
package web_services; import entity.Cliente; import entity.Conto; public class WebServices { public String autenticazione_web(String username,String password) { // istanzia un nuovo oggetto cliente Cliente cliente = new Cliente(); cliente.setUsername(username); cliente.setPassword(password); // verifica che i dati inseriti siano validi if(cliente.readClienteWeb()) return cliente.getUsername(); else return "1"; } public Double mostra_saldo(String username, String password, int numConto) { if(autenticazione_web(username, password).equals(username)) { // istanzia un nuovo oggetto conto Conto conto = new Conto(); conto.setNumero(numConto); conto.readConto(); // esegue la lettura del saldo del conto istanziato return conto.getSaldo(); } else return -1.0; } } Per una questione di comodità è bene copiare l’intera cartella \banca\ e il file config.bat sul desktop. Va precisato, poiché potrebbe non essere banale, che la cartella deve contenere le classi compilate in formato .class e non i sorgenti. Inoltre, è fondamentale utilizzare per tutte le operazioni sempre la stessa istanza della shell affinché non si perdano i percorsi settati nel classpath. Detto questo, una volta posizionati con la shell sul desktop, eseguire il comando config.bat precedentemente creato in modo tale da assicurarci che tutte le variabili d’ambiente siano settate; dopodiché entrare nella cartella \banca\ ed eseguire il comando: Codice:
% java org.apache.axis.wsdl.Java2WSDL -o ws_banca.wsdl -l"http://localhost:8080/axis/services/banca" -n urn:banca -p"banca" urn:banca web_services.WsInterface 3° PASSO: GENERARE LE CLASSI JAVA A PARTIRE DAL WSDL CREATO Il passo successivo prevede l’operazione inversa, per cui a partire dal file wsdl generato, saranno create le classi java necessarie ad instaurare il binding tra web service e la loro implementazione. Basterà eseguire il seguente comando: Codice:
% java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -p ws ws_banca.wsdl La classe generata in origine sarà la seguente: Codice:
package ws; public class BancaSoapBindingImpl implements ws.WsInterface{ public java.lang.String autenticazione_web(java.lang.String in0, java.lang.String in1) throws java.rmi.RemoteException { return null; } public java.lang.Double mostra_saldo(java.lang.String in0, java.lang.String in1, int in2) throws java.rmi.RemoteException { return null; } } Come si può notare, i metodi della classe BancaSoapBindingImpl corrispondono proprio ai metodi dichiarati nella classe WsInterface; per cui ora non bisognerà fare altro che sostituire al posto dei null, gli oggetti che realmente dovranno essere restituiti. Le modifiche apportate saranno le seguenti (in grassetto): Codice:
package ws; import web_services.WebServices; public class BancaSoapBindingImpl implements ws.WsInterface{ WebServices servizio_banca=new WebServices(); public java.lang.String autenticazione_web(java.lang.String in0, java.lang.String in1) throws java.rmi.RemoteException { return servizio_banca.autenticazione_web(in0,in1); } public java.lang.Double mostra_saldo(java.lang.String in0, java.lang.String in1, int in2) throws java.rmi.RemoteException { return servizio_banca.mostra_saldo(in0,in1,in2); } } Una volta che la classe BancaSoapBindingImpl è stata modificata come descritto in precedenza, si può passare alla compilazione dei sorgenti del package ws mediante il comando: Codice:
% javac ws\*.java 5° PASSO: DEPLOYMENT DEI WEB SERVICE SUL SERVER (APACHE TOMCAT) Se la compilazione ha avuto esito positivo si può passare alla creazione del file jar contenente tutte le classi compilate. E’ bene notare che il file jar va creato in modo tale da riprodurre in maniera precisa la struttura ad albero della cartella su cui si sta lavorando, per cui è fondamentale fare attenzione ai percorsi dei package inclusi all’interno del jar. Nel nostro caso andrà eseguito il seguente comando: Codice:
% jar cvf ws_banca.jar entity/*.class data_layer/*.class web_services/*.class ws/*.class E’ importante osservare che se il nostro progetto esegue delle connessioni ad un database oppure utilizza delle librerie esterne, è bene che questi file jar vengano anch’essi copiati all’interno della cartella \WEB-INF\lib\ di axis. Ad esempio, se il nostro web service dovrà collegarsi ad un database di tipo mysql per la lettura di un dato, è fondamentale che venga copiata anche la libreria jdbc per la connessione a mysql. Dopo essersi assicurati che Apache Tomcat sia avviato, si può passare al deployment vero e proprio dei web service. Per cui entrare all’interno della cartella \ws\ ed eseguire il comando: Codice:
% java org.apache.axis.client.AdminClient deploy.wsdd Codice:
<admin>Done processing</admin> Ovviamente la prova del nove può esserci data solo testando i web service mediante un client, il quale accedendo al wsdl (nel nostro caso http://localhost:8080/axis/services/banca?wsdl) restituisca le giuste informazioni in base al web service invocato. La scelta sul client da implementare è abbastanza ampia, si può passare dal flash al php o ancora java. Ma almeno per questo, il web è in grado di fornirvi un’adeguata documentazione che vi possa far creare il client di un web service senza dover passare notti insonni di fronte al computer! Gli amici di Ago
__________________
Che bisogno ha una persona di tenersi un computer in casa? (Kenneth Olsen, fondatore della Digital Equipment, alla convention della World Future Society 1977) Ultima modifica di F@lkland§ : 09-01-2010 alle 17:56. |
![]() |
![]() |
![]() |
#2 |
Junior Member
Iscritto dal: Aug 2009
Città: Molfetta
Messaggi: 2
|
Spero serva a molti questa nostra guida!
![]() Ciao da tutti e 3 gli amici di Ago! |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Feb 2002
Messaggi: 1370
|
Ciao ragazzi, grazie per la guida, sono riuscito a far girare su axis il mio web service ma ora ho un problema con il client, avete qualche suggerimento please?
Ecco il problema: La mia webService si chiama CL se provo dal browser a richiamare il metodo getUserProfile(int user id) funziona, ad esempio se nel browser metto: Codice:
http://localhost:8080/axis/services/CL?method=getUserProfile&u=2 Codice:
Il file XML specificato apparentemente non ha un foglio di stile associato. L'albero del documento è mostrato di seguito. − <soapenv:Envelope> − <soapenv:Body> − <getUserProfileResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <getUserProfileReturn href="#id0"/> </getUserProfileResponse> − <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns1:User"> <ID xsi:type="xsd:int">2</ID> <authorization xsi:type="xsd:int">3</authorization> <name xsi:type="xsd:string">Elisa</name> <surname xsi:type="xsd:string">Esposito</surname> </multiRef> </soapenv:Body> </soapenv:Envelope> Ora sto provando con netbeans a creare un client. Dal wsdl netbeans mi crea un sacco di classi java di cui per ora ignoro il significato, adesso se creo questa semplice classe: Codice:
import java.net.*; import java.rmi.*; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.xml.namespace.*; import javax.xml.rpc.*; import org.apache.axis.client.Call; import stubs.User; public class AAItoCL { public static void main(String[] args) { User u = getUserProfile (2); System.out.println(u.getName()); } private static User getUserProfile (int userId){ Object[] param = new Object[1]; param[0]=Integer.valueOf(userId); User res = new User(); try { Call call = (Call) new org.apache.axis.client.Service().createCall(); call.setTargetEndpointAddress(new URL("http://localhost:8080/axis/services/")); res = (User) call.invoke(new QName("CL", "getUserProfile"), param); } catch (MalformedURLException ex) { System.out.println("Error: invalid URL"); } catch (ServiceException ex) { System.out.println("Error: call fault"); } catch (RemoteException ex) { System.out.println("Error: WS invocation fault"); } finally { return res; } } } Codice:
- Exception: org.xml.sax.SAXException: Deserializing parameter 'getUserProfileReturn': could not find deserializer for type {urn:User}User at org.apache.axis.message.RPCHandler.onStartChild(RPCHandler.java:277) at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1035) at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165) at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1141) at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:345) at org.apache.axis.message.RPCElement.getParams(RPCElement.java:384) at org.apache.axis.client.Call.invoke(Call.java:2467) at org.apache.axis.client.Call.invoke(Call.java:2366) at org.apache.axis.client.Call.invoke(Call.java:1812) at org.apache.axis.client.Call.invoke(Call.java:1727) at AAItoCL.AAItoCL.getUserProfile(AAItoCL.java:120) at AAItoCL.AAItoCL.main(AAItoCL.java:36) Se provo ad utilizzare un metodo che prende ad esempio un parametro intero e restituisce un booleano tale problema non si verifica. Netbeans ha creato, leggendo il wsdl, anche altre classi come "User_SOAPBuilder" e "User_SOAPSerializer" che forse potrebbero essermi utili ma non so come possono essere usate. Please HELP! |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 20:46.