Luca Cabibbo Architettura dei Sistemi Software Programmazione di servizi web SOAP dispensa asw860 marzo 2017 What is elegance? Soap and water! Cecil Beaton 1 - Fonti The Java EE 7 Tutorial https://docs.oracle.com/javaee/7/tutorial/ Chapter 27, Introduction to Web Services Chapter 28, Building Web Services with JAX-WS Papazoglou, M.P. Web Services: Principles and Technology. Pearson, 2008. 2
Obiettivi - Obiettivi e argomenti introdurre alcuni aspetti relativi alla programmazione di servizi web SOAP e di loro client Argomenti introduzione programmazione di servizi web SOAP client di servizi web SOAP discussione 3 * Introduzione Che cosa bisogna fare per realizzare un servizio web SOAP? E per consumare un servizio web? Quanto è complicato utilizzare i diversi standard in gioco (come XML, SOAP e WSDL)? fortunatamente le diverse piattaforme di sviluppo (come.net e Java/Java EE) semplificano l implementazione, il rilascio e il consumo di servizi web che sono anche interoperabili tra piattaforme diverse nei casi più semplici, gli strumenti di sviluppo nascondono agli sviluppatori (almeno in parte) la complessità dei diversi standard in gioco come XML, SOAP e WSDL in modo tale che gli sviluppatori possano concentrarsi sullo sviluppo di funzionalità, logica applicativa e servizi nei casi più complessi (non esaminati qui), tuttavia, è possibile che parte della complessità emerga di nuovo 4
Java EE e servizi web SOAP La piattaforma Java EE (così come altre piattaforme) fornisce le API e gli strumenti per realizzare servizi web SOAP e i loro client essi sono completamente interoperabili, con altri servizi web e client, realizzati sia con tecnologie Java che con altre tecnologie è possibile avere servizi web nello stile procedurale, con operazioni, parametri e valori restituiti oppure servizi web orientati ai documenti, che consentono di inviare documenti che contengono dati nei casi più semplici non è richiesta nessuna programmazione di basso livello, perché l implementazione delle API si occupa della gestione di tutti i protocolli e dei formati previsti dagli standard per i servizi web SOAP in particolare, Java EE fornisce il supporto per la definizione e il consumo di servizi web SOAP basati su XML e gli standard SOAP e WSDL mediante la tecnologia JAX-WS Java API for XML-Web Services 5 * Viene ora esemplificata l implementazione di un servizio web SOAP realizzato con JAX-WS JAX-WS supporta sia l implementazione di servizi che l implementazione di client di servizi (discussa più avanti) è sufficiente compilare e deployare il codice che segue come applicazione web in un application server (ad es., GlassFish) la specifica WSDL del servizio viene generata automaticamente dagli strumenti di Java EE a partire dal codice 6
- Il servizio CalculatorService La classe Calculator implementa alcune semplici operazioni l aggiunta di alcune annotazione JAX-WS rendono questa classe un servizio web SOAP package asw.ws.calculator; import javax.jws.webservice; import javax.jws.webmethod; @WebService public class Calculator { @WebMethod public double sqrt(double x) { return Math.sqrt(x); @WebMethod public double exp(double x) { return Math.exp(x); 7 CalculatorService WSDL generato automaticamente 8
CalculatorService WSDL <?xml version='1.0' encoding='utf-8'?><!-- Published by JAX-WS RI... --> <definitions... xmlns:tns="http://calculator.ws.asw/" targetnamespace="http://calculator.ws.asw/" name="calculatorservice"> <types> <xsd:schema> <xsd:import namespace="http://calculator.ws.asw/" schemalocation="http://10.11.1.111:8080/asw/ws/calculatorservice?xsd=1"/> </xsd:schema> </types>... </definitions> 9 CalculatorService types Il documento http://10.11.1.111:8080/asw/ws/calculatorservice?xsd=1 <?xml version='1.0' encoding='utf-8'?><!-- Published by JAX-WS RI... --> <xs:schema xmlns:tns="http://calculator.ws.asw/" targetnamespace="http://calculator.ws.asw/"...> <xs:element name="sqrt" type="tns:sqrt"/> <xs:element name="sqrtresponse" type="tns:sqrtresponse"/> <xs:element name="exp" type="tns:exp"/> <xs:element name="expresponse" type="tns:expresponse"/> <xs:complextype name="sqrt"> <xs:sequence> <xs:element name="arg0" type="xs:double"/> </xs:sequence> </xs:complextype> <xs:complextype name="sqrtresponse"> <xs:sequence> <xs:element name="return" type="xs:double"/> </xs:sequence> </xs:complextype> <xs:complextype name="exp"> <xs:sequence> <xs:element name="arg0" type="xs:double"/> </xs:sequence> </xs:complextype> <xs:complextype name="expresponse"> <xs:sequence> <xs:element name="return" type="xs:double"/> </xs:sequence> </xs:complextype> </xs:schema> 10
CalculatorService WSDL <message name="sqrt"> <part name="parameters" element="tns:sqrt"/> </message> <message name="sqrtresponse"> <part name="parameters" element="tns:sqrtresponse"/> </message> <message name="exp"> <part name="parameters" element="tns:exp"/> </message> <message name="expresponse"> <part name="parameters" element="tns:expresponse"/> </message> 11 <porttype name="calculator"> <operation name="sqrt"> <input wsam:action="http://calculator.ws.asw/calculator/sqrtrequest" message="tns:sqrt"/> <output wsam:action="http://calculator.ws.asw/calculator/sqrtresponse" message="tns:sqrtresponse"/> </operation> <operation name="exp"> <input wsam:action="http://calculator.ws.asw/calculator/exprequest" message="tns:exp"/> <output wsam:action="http://calculator.ws.asw/calculator/expresponse" message="tns:expresponse"/> </operation> </porttype> CalculatorService WSDL <binding name="calculatorportbinding" type="tns:calculator"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="sqrt"> <soap:operation soapaction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> <operation name="exp"> <soap:operation soapaction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="calculatorservice"> <port name="calculatorport" binding="tns:calculatorportbinding"> <soap:address location="http://10.11.1.111:8080/asw/ws/calculatorservice"/> </port> </service> 12
* Client di servizi web SOAP Viene ora esemplificato l accesso al precedente servizio web SOAP JAX-WS supporta anche l implementazione di client di servizi web SOAP tuttavia, lo stesso servizio web può essere anche acceduto da client realizzati con altre tecnologie così come JAX-WS può essere utilizzato per accedere servizi web realizzati con altre tecnologie 13 - Client per CalculatorService In generale, nella realizzazione di un client per un servizio web SOAP, è possibile utilizzare degli opportuni strumenti di sviluppo in particolare, dei compilatori di specifiche WSDL ogni compilatore di WSDL è specifico per un certo linguaggio di programmazione target un compilatore di WSDL genera, a partire da una specifica WSDL (o dalla sua URI), un client proxy (stub) nel linguaggio target, composto da un certo numero di classi e interfacce l applicazione client viene poi realizzata facendo esplicito utilizzo di questo stub oppure definendo un ulteriore proxy o adattatore per un certo linguaggio target, ci possono anche essere più compilatori diversi che generano stub differenti talvolta anche un singolo compilatore può fornire più modalità differenti di realizzazione (binding) dello stub 14
Client per CalculatorService Nel caso di JAX-WS, lo stub generato per il nostro servizio CalculatorService comprende le seguenti classi Calculator un interfaccia che definisce le operazioni sqrt e exp del servizio CalculatorService una classe per il servizio, che fornisce delle operazioni factory per accedere a un proxy per il servizio (con riferimento a un suo specifico endpoint) ad es., Calculator getcalculatorport() Sqrt e SqrtResponse rappresentano il messaggio di richiesta e di risposta dell operazione sqrt Exp e ExpResponse rappresentano il messaggio di richiesta e di risposta dell operazione exp 15 Client Java per CalculatorService 16 package asw.ws.calculator.client; import asw.ws.calculator.endpoint.calculatorservice; import asw.ws.calculator.endpoint.calculator; import javax.xml.ws.webserviceref; public class CalculatorClient { @WebServiceRef(wsdlLocation = "http://10.11.1.111:8080/asw/ws/calculatorservice?wsdl") private static CalculatorService service; factory per accedere private Calculator calculator; al proxy del servizio public CalculatorClient() { this.calculator = service.getcalculatorport(); public void run() {... calculator.sqrt(100)...... calculator.exp(3)... le classi generate dal compilatore di WSDL proxy al servizio
Richiesta Un interazione con CalculatorService <?xml version="1.0" encoding="utf-8"?> <S:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <S:Body> <tns:sqrt xmlns:tns="http://calculator.ws.asw/"> <arg0>100.0</arg0> </tns:sqrt> </S:Body> </S:Envelope> Risposta <?xml version="1.0" encoding="utf-8"?> <S:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <S:Body> <tns:sqrtresponse xmlns:tns="http://calculator.ws.asw/"> <return>10.0</return> </tns:sqrtresponse> </S:Body> </S:Envelope> 17 - Client C# per CalculatorService using System; using System.Collections.Generic; using System.Text; using asw.ws.calculator.calculatorservice; stub generato da Visual Studio a partire dall URI del servizio namespace Asw.Ws.CalculatorClient { class Program { static void Main(string[] args) { CalculatorService calculator = new CalculatorService(); System.Console.WriteLine( calculator.sqrt(100.0) ); System.Console.WriteLine( calculator.exp(3.0) ); 18
- Client Java per CalculatorService (AXIS2) package asw.ws.calculator.client; import java.rmi.remoteexception; import asw.ws.calculator.endpoint.calculatorservicestub; import asw.ws.calculator.endpoint.calculatorservicestub.*; public class CalculatorClientProxy { private CalculatorServiceStub stub; public CalculatorClientProxy() throws RemoteException { this.stub = new CalculatorServiceStub(); public double sqrt(double x) throws RemoteException { Sqrt request = new Sqrt(); request.setarg0(x); SqrtResponse response = stub.sqrt(request); return response.get_return(); 19 - Client asincrono con callback (AXIS2) public class CalculatorClientProxyAsincrono {... public void startsqrt(double x) throws RemoteException { Sqrt request = new Sqrt(); request.setarg0(x); CalculatorServiceCallbackHandler callback = new CalculatorServiceCallbackHandler(this) { public void receiveresultsqrt(sqrtresponse response) { double result = response.get_return(); CalculatorClientProxyAsincrono proxy = (CalculatorClientProxyAsincrono) getclientdata(); proxy.callbacksqrt(result); public void receiveerrorecho(exception e) {... gestisci e... ; stub.startsqrt(request, callback); public void callbacksqrt(double result) {... fa qualcosa con result... 20
* Discussione Alcune funzionalità offerte da JAX-WS generazione bottom up di un servizio web SOAP a partire da classi Java (POJO) oppure da enterprise bean di tipo stateless generazione top down dello skeleton dell implementazione di un servizio web a partire da una specifica WSDL consente un uso più flessibile dei diversi MEP il ciclo di vita delle istanze dei servizi è gestito da un contenitore con la possibilità di definire metodi di callback associati alla gestione del ciclo di vita dei servizi 21 diverse modalità di generazione dello stub per i client di un servizio web a partire da una specifica WSDL con riferimento a diverse modalità di binding dei dati di solito maggior flessibilità nell utilizzo di un servizio comporta maggior complessità del codice da scrivere (e viceversa)