Runtime Environment. In Eclipse, configurare il proprio
ambiente di runtime Tomcat. Selezionare
Window > Preferences > Server >
Runtime Environment > New...
Nella finestra che si apre, selezionare Apache
Tomcat 7 e indicare il folder di installazione (La directory padre
della
webapps
dove eseguite i deploy).
CXF. Scaricare e decomprimere la versione 3.x di Apache CXF.
Selezionare
Window > Preferences > Web Services
> CXF 2.x Preferences > Add...
, indicare il folder dove avete appena decompresso l'applicazione, selezionare il checkbutton e
cliccare Finish.
Obiettivo di questo esercizio è descrivere un servizio web
tramite WSDL che emula lo Shopping Service di eBay implementando
l'operazione
GetCategoryInfo
.
Step 1. Creare un nuovo WSDL. Creiamo un nuovo Dynamic Web Project di nome shopping e selezioniamo
File > New.. > WSDL File
. Nel wizard di creazione indichiamo come nome del file
Shopping.wsdl
e come namespace
http://di.unipi.it/lai/shopping/
. Selezionare
Finish
e verificare che venga creato lo scheletro di un WSDL.
Step 2. Types. L'elemento
types
che contiene gli schemi xml dei messaggi utilizzati. Il nostro
servizio utilizza i messaggi definiti dallo schema di eBay, quindi
possiamo riusarlo. Copiamo quindi lo ShoppingService.xsd in nella stessa cartella del
WSDL. Rimuoviamo la definizione dello schema generata da Eclipse e
inseriamone una nuova indicando il targetNamespace di ebay (
urn:ebay:apis:eBLBaseComponents
) ed aggiungiamo include
dello schema.
Step 3. Messages. Completata la definizione degli elementi che
utilizzeremo nel servizio, procediamo con la definizione dei messaggi.
L'operazione di
GetCategoryInfo
è una operazione sincrona, quindi con richiesta e risposta.
Dobbiamo quindi definire due messaggi corrispondenti alla richiesta e
alla risposta. Lo scheletro generato da Eclipse contiene già la
definizione di due messaggi, quindi è sufficiente modificarli
indicando i corretti root element
ebay:GetCategoryInfoRequest
e
ebay:GetCategoryInfoResponse
, ricordandoci di aggiungere il riferimento al prefisso ebay nell'intestazione del file WSDL (xmlns:ebay="urn:ebay:apis:eBLBaseComponents").
Step 4. Port-Types. Definiti i messaggi, procediamo con il
portType, ovvero l'interfaccia astratta del servizio contenente le
operazioni da offrire. Lo scheletro generato da Eclipse contiene
già un portType con una operazione sincrona che utilizza i
messaggi definiti in precedenza come richiesta e risposta. Per
adattarlo alle nostre esigenze, basta cambiare il nome all'operazione
con
GetCategoryInfo
.
Step 5. Binding. Completato il portType, ovvero l'interfaccia astratta del servizio, definiamone il binding, ovvero l'implementazione. Con il binding indichiamo il formato dei messaggi, il protocollo di trasporto e la codifica. Nel nostro caso, vogliamo indicare l'uso del SOAP su HTTP con codifica Document/Literal. Lo scheletro di binding generato da Eclipse è già configurato in questo modo, quindi è sufficiente correggere il nome dell'operazione e personalizzare il valore dell'header SOAPAction.
Step 6. Service. L'elemento service specifica il punto di accesso al servizio. Trattandosi di un binding HTTP, verrà indicata la URL di invocazione, ma in questa fase non sappiamo quale sarà la URL del servizio, quindi possiamo lasciare quella generata da Eclipse. Validiamo il WSDL e verifichiamo che non siano segnalati errori.
Obiettivo di questo esercizio è generare, implementare e deployare un Web Service a partire dal WSDL utilizzando Eclipse e CXF
Step 1. Configurare il Build Path. Aggiungiamo le librerie di
CXF al build path del progetto. Selezioniamo il progetto e
Project > Properties > Java Build Path
> Libraries > Add library...
aggiungere la libreria CXF configurata nei prerequisiti.
Step 2. Generazione dello skeleton. Cliccare con il tasto
destro il WSDL creato nell'esercizio precedente e selezionare
Web Services > Generate Java Bean
Skeleton
. Verificare che la finestra di dialogo successiva presenti questi
valori:
Web Service Type: Top Down
Service definition: path al WSDL
Slider di generazione: Assemble Service
Server runtime: Apache Tomcat
Web Service runtime: Apache CXF 2.x
Service Project: il progetto di destinazione
Selezionare
Finish
e verificare che siano generati i seguenti componenti:
WebContent/WEB-INF/web.xml
: è il deployment descriptor. Nelle precedenti esercitazioni era sostituito dalle annotazioni, ma adesso è necessario. Definisce che tutte le chiamate alla URL/services/*
siano gestite dalla servlet di CXF configurata dal file cxf-beans.xmlWebContent/WEB-INF/cxf-beans.xml
: script di configurazione per la servlet di CXF. Definisce l'endpoint del Web Service, la URL a cui risponde, la classe che lo implementa, il WSDL che lo descrive etc.. Inoltre è preconfigurato per utilizzare la funzionalità di Logging di CXF che esegue il log di tutti i messaggi transitati.Java Resources/src/ebay.apis.eblbasecomponents
: package con le classi annotate JAXB corrispondenti agli elementi definiti dall'XML Schema di eBay generate con XJC.-
Java Resources/src/it.unipi.di.lai.shopping
: package con le classi annotate JAXWS corrispondenti agli elementi definiti dal WSDL del servizio generate con WSDL2JAVA di CXF. Comprendono:Interfaccia del servizio, generata con il nome del portType
Implementazione del servizio, generata con il suffisso
Impl
Se il codice sorgente non fosse generato a causa di errori in console, eseguire lo stesso comando visualizzato in console eclipse da un terminale, eliminando dal path riferito nel comando la directory .cxftmp. In questo caso il comando wsdl2java è disponibile all'interno dell'archivio di CXF, scaricato all'inizio dell'esercitazione.
Step 3. Implementazione. Apriamo e modifichiamo la classe che implementa l'interfaccia del servizio. Il generatore ha prodotto un'implementazione che valorizza tutti i possibili campi della risposta per aiutarci nello sviluppo. Per il momento possiamo mantenere questa implementazione, su cui agiremo successivamente.
Step 4. Deploy e verifica. Esportare il progetto come WAR
chiamato
shopping.war
e deployarlo in Tomcat verificando che non ci siano errori. Verificare
che sia accedibile la servlet di CXF all'indirizzo http://localhost:8080/shopping/services/
e che venga visualizzata la lista dei servizi con il link al WSDL del
servizio.
Obiettivo di questo esercizio è generare, implementare ed eseguire Client per il Web Service sviluppato nell'esercizio precedente.
Step 1. Predisporre il progetto. Creare un nuovo Dynamic Web Progect ed aggiungere le librerie di CXF al build path del progetto.
Step 2. Generazione dello stub. Selezionare
File > New... > Web Services Client
. Verificare che la finestra di dialogo successiva presenti questi
valori:
Service definition: la URL del WSDL del servizio deployato in precedenza
Slider di generazione: Assemble
Server runtime: Apache Tomcat
Web Service runtime: Apache CXF 3.x
Client Project: il progetto di destinazione
Selezionare
Finish
e verificare che siano generati i seguenti componenti:
ebay.apis.eblbasecomponents
: package con le classi annotate JAXB corrispondenti agli elementi definiti dall'XML Schema di eBay generate con XJC.-
it.unipi.di.lai.shopping
: package con le classi annotate JAXWS corrispondenti agli elementi definiti dal WSDL del servizio generate con WSDL2JAVA di CXF. Comprendono:Una factory per l'implementazione di client per il servizio.
Una implementazione di un client.
Step 3. Implementazione. Apriamo e modifichiamo la classe che implementa il client del servizio. Il generatore ha incluso un'implementazione che valorizza tutti i possibili campi della richiesta per aiutarci nello sviluppo.
Step 4. Invocazione. Eseguire il client e verificare il corretto funzionamento. Inoltre verificare che nei log di Tomcat vengano loggati i messaggi SOAP in transito, compresivi degli header http.
Step 5. Analisi. Analizzare e provare a modificare l'implementazione del server, in modo da restituire un elenco di categorie in stile EBay, e l'implementazione del client per stampare l'elenco delle categorie restituite. Nel farlo analizzare come siano mappati gli elementi xml con le corrispondenti classi Java anche facendo riferimento alla sezione Output della documentazione eBay.
I Web Service ed i Client prodotti fino ad adesso sono fortemente vincolati all'ambiente di sviluppo. Con molta probabilità, non saremmo in grado di deployare il Web Service od eseguire il Client in altri ambienti. Eliminiamo le dipendenze dall'ambiente di sviluppo.
Step 1. Includere il WSDL nel WAR. L'annotazione
@WebService
riporta il parametro
wsdlLocation
con il path del WSDL da pubblicare. Il valore assegnato dal generatore
è quello del path assoluto, valido solo nell'ambiente di
sviluppo. Spostiamo il file all'interno della cartella
WebContent
in modo che sia incluso nel WAR di esportazione e modifichiamo il
valore di
wsdlLocation
con il path relativo alla root del WAR (eg:
WEB-INF/wsdl/Shopping.wsdl
)
Step 2. Includere il WSDL nel Client. Tutte le volte che invochiamo il client, il Web Service logga, prima dell'invocazione SOAP, una GET al WSDL. Questo perché per instanziare il client, la factory ha bisogno del WSDL del servizio che consuma e lo recupera invocando la URL fornita in fase di generazione. Questo comportamento, oltre ad essere molto inefficiente, è dipendente dalla riuscita della GET. Modifichiamo il Client in modo da instanziare lo stub fornendo un WSDL locale, non tramite URL remota.
Step 3. Specificare la URL di invocazione del Client. Gli stub utilizzano come URL di invocazione quella indicata nel WSDL. Questo potrebbe non essere corretto, ad esempio nel caso si debba invocare un Proxy applicativo che media le richieste. Modificare il codice in modo da specificare la URL di invocazione:
((BindingProvider) port).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://.....");
Scaricare l'archivio della soluzione
e importarlo in Eclipse con File > Import > General > Existing Project
creando cosi i progetti WebService
e WebService Client
.
Aggiungere ad entrambi i progetti le librerie CXF e al progetto WebService
le librerie Lai API v.1.0.4.
Esportare il progetto WebService
come webservice.war
in Tomcat
e verificare il corretto deploy richiedendo il WSDL del servizio alla url
http://localhost:8080/webservice/services/SOAP?wsdl
Eseguire la classe Shopping_Client
del progetto WebService Client
e verificarne il corretto funzionamento.