Realizzare un Web Services in pochi minuti con Apache Axis (domenica 19 dicembre 2004) - Viene illustrato il framework di sviluppo per i Web Service Apache Axis. Viene inoltre mostrato come realizzare un semplice Web Service con strumenti open source e con il linguaggio Java - Introduzione - L'Axis nella manica - Il server servente - Coding: lato server - Il client ordina ed ottiene - Un po' di sicurezza: ma molto poca - Link - Commenta l'articolo Introduzione I Web Services (WS) rivoluzioneranno il mondo dell'informatica grazie all'uso del linguaggio XML: questo oramai lo abbiamo capito, ma come facciamo allora a sviluppare WS? Innanzitutto scegliete il vostro linguaggio di programmazione preferito: se la vostra scelta è Java allora quasi d'obbligo è l'uso di Apache Axis su Tomcat. Axis è il framework di sviluppo per i WS mentre Tomcat è l'application server dove avviene l'esposizione dei WS. L'Axis nella manica Axis permette lo sviluppo di WS sia in Java che in C++ ma noi ci occuperemo solo del lang di casa Sun, Java implementa gli standard: - JAX-RPC: insomma SOAP con il classico RPC - SAAJ: permette di manipolare il messaggio SOAP e gestire gli attachment - tanti altri... Axis implementa quindi il modello JAX-RPC e supporta anche SAAJ, per un maggiore approfondimento vedi articolo precedente. Non tutto nasce però da Apache, il prodotto iniziale è merito di IBM, che poi molto gentilmente decise di regalare al consorzio Apache tutto il codice. Viene alla luce quindi Apache SOAP e poi la sua evoluzione: Apache Axis. Le caratteristiche più importandi del framework sono: http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 - implementazione SOAP 1.1/1.2 - supporto JWS (Java Web Services): permette un facile e immediato deploy dei WS - supporto serializzazione/deserializzazione - implementazione WSDL - utility WSDL2Java e Java2WSDL - Soap Monitor e TCP Monitor: due applicazioni scritte in Java che permettono di monitorare il traffico SOAP - possibilità di usare tre differenti metodi per l'invocazione dei WS: Dynamic Invocation Interface, Stub generato dal WSDL e Dynamic Proxy I componenti di Axis sono quindi: un engine per l'elaborazione dei messaggi SOAP, handler per la gestione dei messaggi, vari meccenismi di deploy, serializzazione/deserializzazione, configurazione e di trasporto dei messaggi. Il server servente Come primo passo è necessario aver configurato Java su una macchina Linux. E' possibile scaricarsi dal sito della Sun il pacchetto in vari formati: l'installazione è molto semplice ed avviene tramite una wizard grafica. Al termine dell'installazione è necessario settare le varibili di sistema $JAVA_ HOME e $PATH, che contengono rispettivamente il percorso della directory d'installazione di JAVA e degli esegubili, come ad es.: export JAVA_HOME = /usr/java/jdk1.5.0 export PATH = $PATH:$JAVA_HOME/bin Per quanto riguarda Axis è sufficiente scaricarsi il pacchetto dal sito e scompattarlo (io consiglio sempre /opt/axis, da questo momento in poi farò riferimento a questa directory). L'installazione di Tomcat avviene con le modalità classiche (compilazione o RPM, anche in questo caso considero come home di Tomcat la directory /opt/tomcat). Esistono comodi script per l'avvio e l'arresto dell'application server che si trovano in $CATALINA_HOME/bin. La verifica della corretta configurazione si ottiene digitando nel browser http://localhost:8080 e verificando la comparsa della home page Tomcat. Axis si integra molto semplicemente con Tomcat: l'unica operazione da eseguire è la copia della directory webapps/axis (nella home di Axis, quindi /opt/axis/webapps/axis) all'interno di webapps (nella home di Tomcat, quindi /opt/tomcat/webapps). Successivamente, per comodità, si possono configurare un po' di varibili globali: http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 export JAVA_ENDORSED_DIRS = $CATALINA_HOME/bin: $CATALINA_HOME/common/lib: $CATALINA_HOME/webapps/axis/WEB-INF/lib export AXIS_HOME = /opt/axis export AXIS_LIB=$AXIS_HOME/lib export AXISCLASSPATH = $AXIS_LIB/axis.jar: $AXIS_LIB/commons-discovery.jar: $AXIS_LIB/commons-logging.jar: $AXIS_LIB/jaxrpc.jar: $AXIS_LIB/saaj.jar: $AXIS_LIB/log4j-1.2.8.jar: $AXIS_LIB/xml-apis.jar: $AXIS_LIB/xercesImpl.jar La variabile $AXISCLASSPATH rappresenta i riferimenti alle librerie jar che contengono l'implementazione degli standard sui WS come SAAJ e JAX-RPC; osservate l'ultima libreria dove è incluso il parser XML Xerces, Java include il parser Crimson ma Apache consiglia Xerces: entrambi funzionano adeguatamente quindi la scelta è puramente personale. Eventualmente potreste settare un'ulteriore variabile globale $CLASSPATH che contiene il percorso di altre librerie, io di solito copio tutti i jar che mi servono in $CATALINA_HOME/common/lib ma ognuno può adottare il metodo che preferisce. In alcuni casi potrebbe essere necessario l'uso della libreria activation.jar, che può essere scaricata comodamente dal sito della Sun. La verifica della corretta integrazione tra Axis e Tomcat si ottiene facendo puntare il browser http://localhost:8080/axis: dovrebbe compare la semplice home page testuale di Axis da cui è possibile effettuare alcune operazioni. Coding: lato server Apache AXIS implementa, come già accennato, il nuovo standard JWS di Java che permette di effettuare il deploy di un WS in maniera semplice e veloce. E' sufficiente sviluppare la propria classe in Java, testarla, cambiare l'estensione da .java e .jws e il WS è pronto: niente di più immediato. Axis lo tratterà in maniera simile ad una JSP ossia lo compilerà e si occuperà dell'interfacciamento con SOAP mediante la conversione automatica SOAP-JAVA. Tale metodo ha ovviamente il pregio della semplicità a scapito della flessibilità: è infatti impossibile decidere quali metodi esporre e specificare conversioni specifiche tra SOAP e JAVA. Un metodo più flessibile è l'uso dei file WSDD (Web Service Deployment Descriptor), introdotti da Axis, ma per il primo WS l'uso del JWS è più che adeguato. Un WS accessibile è quindi una classe Java che espone i propri metodi http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 pubblici e non-static. Scriviamo ora una semplice classe di esempio che controlla se un numero è pari oppure dispari: l'esempio è ovviamente molto semplice (direi ridicolo ma non volevo fare il solito esempio del saluto Hello User, I'm your WS), ma potrebbe essere il primo metodo di una classe matematica che si occupa di effettuare appunto calcoli matematici. Il metodo pari restituisce un valore di tipo String. public class matematica{ public String pari(int numero) { return (numero%2)==0 ? "pari" : "dispari"; } } Chiamamo il file matematica.jws e copiamolo nella direcotory $CATALINA_HOME/webapps/axis. Ora è necessario eseguire il deploy, ovvero quella operazione che permette di rendere disponibile il nostro WS ottenendo il file WSDL descrittore del WS. Per ottenere questo e verifare la corretta interpretazione e compilazione dei WS si digiti nel browser: http://localhost:8080/axis/matematica.jws?WSDL. Il file WSDL ottenuto è il seguente: <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/axis/matematica.jws" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://localhost:8080/axis/matematica.jws" xmlns:intf="http://localhost:8080/axis/matematica.jws" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <wsdl:message name="pariResponse"> <wsdl:part name="pariReturn" type="xsd:string"/> </wsdl:message> <wsdl:message name="pariRequest"> <wsdl:part name="numero" type="xsd:int"/> </wsdl:message> <wsdl:portType name="matematica"> <wsdl:operation name="pari" parameterOrder="numero"> <wsdl:input message="impl:pariRequest" name="pariRequest"/> <wsdl:output message="impl:pariResponse" name="pariResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="matematicaSoapBinding" type="impl:matematica"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="pari"> http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 <wsdlsoap:operation soapAction=""/> <wsdl:input name="pariRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://DefaultNamespace" use="encoded"/> </wsdl:input> <wsdl:output name="pariResponse"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/matematica.jws" use="encoded"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="matematicaService"> <wsdl:port binding="impl:matematicaSoapBinding" name="matematica"> <wsdlsoap:address location="http://localhost:8080/axis/matematica.jws"/> </wsdl:port> </wsdl:service> </wsdl:definitions> E' immediato vedere come il file sia di facile lettura, ad esempio si possono individuare: - wsdl:message: indicano il tipo dei dati scambiati, int in ingresso e string in uscita - wsdl:portType: il tipo di operazione e i parametri - wsdl:bindings: il tipo di protocollo usato - wsdl:service: caratteristiche del WS come l'indirizzo Il WS è completamente realizzato ed esposto, ossia accessibile... ma ora come possiamo interrogarlo? Il client ordina ed ottiene Ci sono varie tecniche di interfacciamento al WS e molte di queste usano come informazione il file WSDL generato (stub) e reso disponibile dal server: tali techniche non sono immediate, noi come primo esempio useremo invece la Dinamic Invocation che non fa uso del WSDL. Prima di tutto dovete però; armarvi di buona pazienza e, come nel server, impostare la variabile d'ambiente $AXISCLASSPATH Ecco il semplice codice del client: import org.apache.axis.client.Call; import org.apache.axis.client.Service; import org.apache.axis.encoding.XMLType; import org.apache.axis.utils.Options; import java.net.URL; http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 import javax.xml.rpc.ParameterMode; public class clientMatematica { public static void main(String[] args) throws Exception { Integer numero= new Integer(args[0]); String nameWS = "http://localhost:8080/axis/matematica.jws"; URL endPointWS=new URL(nameWS); //inizializzazione WS Service service = new Service(); Call call = (Call) service.createCall(); call.removeAllParameters(); //configurazione parametri WS call.setTargetEndpointAddress(endPointWS); call.addParameter("numero",XMLType.XSD_INT,ParameterMode.IN); call.setOperationName("pari"); call.setReturnType(XMLType.XSD_STRING); //invocazione WS String risultato = (String)call.invoke(new Object[]{numero}); System.out.println("Il numero "+numero+" e' "+risultato); } } La lettura del codice è agevole: - istanzazione degli oggetti Call e Service - configurazione dell'endpoint: in questo caso l'indirizzo del WS (setTargetEndpointAddress) - indicazione tipo parametri d'ingresso (addParameter) - indicazione del nome del metodo da invocare (setOperationName) - indicazione tipo parametri d'output (setReturnType) - indicazione parametri e invocazione del medoto (invoke) - gestione del risultato E di seguito compilazione, avvio ed output: # javac -classpath $AXISCLASSPATH clientMatematica.java # java -cp $AXISCLASSPATH clientMatematica 5 Il numero 5 e' dispari Il messaggio SOAP inviato dal client al serve dovrebbe assomigliare a qualcosa di simile: <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:pari xmlns:ns1="http://localhost:8080/axis/matematica.jws"> <arg0 xsi:type="xsd:int">5</arg0> </ns1:pari> </SOAP-ENV:Body> </SOAP-ENV:Envelope&gt mentre la risposta è: <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:pariResponse xmlns:ns1="http://localhost:8080/axis/matematica.jws"> <arg0 xsi:type="xsd:string">dispari</arg0&gt </ns1:pariResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope&gt Non commento i due messaggi SOAP per non insultare la vostra intelligenza, infatti sono solo indicati i parametri e il WS esposto. Tutto molto semplice, fin troppo semplice. Vi ricordo però che questa metodologia è la meno flessibile poiché non considera il file WSDL e quindi non permette un'automatizzazione della procedura. L'uso del JWS, come già illustrato, ha delle limitazioni poiché si deve disporre del codice sorgente e rende impossibili gestioni personalizzate: un risultato maggiormente scalabile si ottiene ricorrendo al WSDD e le utility WSDL2Java e Java2WSDL. Un po' di sicurezza: ma molto poca I WS presentano vari problemi di sicurezza: primo tra tutti sono testo HTTP in grado di invocare metodi e passare inosservati attraverso i firewall. Sono allo studio vari protocolli di sicurezza, alcuni sono già disponibili e completamente funzionanti ma risulta difficile applicarli ad una piccola realtà. E' per questo che la prima generazione di WS non ha tecniche di sicurezza ad-hoc ma usa modalità ereditate dal vecchio HTTP: ossia i tunnel SSL/TLS over HTTP, insomma il cosiddetto HTTP-Secure (HTTPS). Per usare HTTPS, poiché i WS risiedono su un application server, si deve come prima cosa configurare Tomcat per accettare connessioni cifrate. Si deve creare un certificato per il server tramite l'utility keytool di Java, successivamente si deve configurare il web server in modo tale che accetti connessioni https sulla porta 8443 modificando il file di impostazioni server.xml inserendo/decommettando le seguenti righe: http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33 <!--Definea SSL Coyote HTTP Connector on port 8443 --> < Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" disableUploadTimeout="true" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" &nbsp/> La correttezza della procedura può essere verificata controllando: https://localhost:8443/axis/matematica.jws Ora il client deve interrogare il server WS sulla porta 8443: ciò può avvenire in due modi differenti: - autenticazione one-way (stile browser per intederci): solo il server ha il certificato, allora si devono riscrivere (vuoti) un paio di metodi Java - autenticazione two-way: il server genera un certificato anche per il client, quest'ultimo deve richiamarlo nel codice. Ma vi sto dicendo già troppo...comunque il prossimo articolo riguarda la sicurezza nei WS...quindi basta aspettare...insomma abbiate un po' di pazienza... !!! Nel mentre divertitevi con Apache Axis !!! Link - www.webservices.org: il portale per definizione - ws.apache.org/axis: il tool Apache Axis - apache.tomcat.org: l'application server Tomcat - webservices.xml.com: il portale del mitico O'Reilly - java.sun.com: Java http://vlain.altervista.org - public void vLAiN [rudi Verago] Powered by Mambo Generated: 29 September, 2016, 16:33