Nelle precedenti parti abbiamo illustrato come progettare, implementare e pubblicare un web service utilizzando Spring-WS. In questa terza parte vedremo come si gestisce la modifica dell‘interfaccia e dell‘implementazione in modo elegante, cercando di mantenere la continuità di servizio.
Modifiche senza interruzioni del servizio
Compresi i meccanismi di pubblicazione e implementazione di un web service con Spring-WS, vediamo ora come sia possibile gestire in maniera elegante la modifica dell’interfaccia e dell’implementazione, in uno scenario dove la continuità del servizio assume un aspetto importante. Il nuovo servizio verrà quindi pubblicato lasciando in esecuzione quello originario, così i consumatori del servizio originario avranno il tempo di adeguarsi alle nuove interfacce, mentre i nuovi otterranno i client a partire dalla pubblicazione del nuovo servizio.
Tutto questo senza interruzioni di servizio, ridondanze di codice o di ambienti di persistenza, sfruttando l’object orientation e il modello di implementazione di Spring-WS che, come abbiamo ampiamente descritto, separa l’implementazione dell’endpoint da quella del servizio.
Dal punto di vista operativo per la pubblicazione del nuovo servizio dovremmo codificare:
- lo schema del nuovo servizio;
- le nuove classi che serializzano il messaggio;
- la classe di implementazione dell’end point;
- la classe di implementazione del servizio;
- il file di configurazione del contesto di Spring-WS.
Le classi che serializzano il nuovo payload XML verranno ottenute estendendo quelle del servizio originario (aggiungendo i nuovi campi), mentre la classe di implementazione del nuovo servizio implementerà l’interfaccia del servizio originale estendendo le nuove funzionalità attraverso un mirato overload di alcuni metodi.
In pratica
La modifica del servizio consiste nell’introduzione delle funzionalità di inserimento e controllo della “tessera di fidelizzazione” oltre alla possibilità di controllare lo stato della spedizione, fornendo al cliente il codice di tracciatura del vettore. La modifica ha anche come oggetto l’anagrafica del cliente dove l’indirizzo di spedizione verrà integrato con la nazione.
Seguendo i passi di implementazione descritti della prima parte, il primo step consisterà nella pubblicazione del nuovo schema, aggiungendo i nuovi campi alla definizione della request e response del servizio originario.
Figura 1 – Pubblicazione del nuovo schema.
Nella tabella 1 sintetizziamo le modifiche introdotte nel nuovo schema.
Tabella 1 – Le modifiche introdotte nel nuovo schema.
Ed ecco di seguito le modifiche all’interfaccia del servizio.
Figura 2 – Modifiche all’interfaccia del servizio.
A fronte di questa nuova definizione di web service aggiorneremo il file di configurazione di Spring-WS. Questa era la definizione originaria.
Figura 3 – Definizione del web service originario nel file di configurazione di Spring-WS.
E questa è la nuova definizione del web service.
Figura 4 – Definizione del nuovo web service nel file di configurazione di Spring-WS.
Nel diagramma di figura 5 vengono rappresentate le classi che serializzano il payload XML come derivazione di quelle del servizio originario.
Circa l’implementazione dell’endpoint e del servizio, il class diagramdi figura 6 mostra come la codifica viene ottenuta attraverso l’estensione dell’endpoint e del servizio originale implementando, per quest’ultimo, le nuove funzionalità attraverso l’overloading di uno dei metodi.
Figura 6 – Class diagram delle implementazioni dei due servizi e loro relazioni.
Attraverso quindi l’object orientation e Spring-WS siamo riusciti a pubblicare un nuovo servizio a partire da quello esistente, senza modificare nulla di quello originale, così da poterlo lasciare in esecuzione. Un approccio analogo dovrà essere seguito in ordine all’implementazione delle classi di persistenza. Di seguito riportiamo la codifica della logica di invocazione al nuovo servizio.
//*** INVOCAZIONE DELLA LOGICA DEL SERVIZIO String codicePrenotazione = acquistoNuovoServiceImpl.verificaDisponibilitaProdotti( acquistoNuovoXMLFragment.getCodiceProdotto(), acquistoNuovoXMLFragment.getQuantita()); acquistoNuovoServiceImpl.controllaTesseraFidelizzazione( acquistoNuovoXMLFragment.getCodiceTesseraFidelizzazione(), codicePrenotazione); String codiceAutorizzazioneCarta = acquistoNuovoServiceImpl.eseguiPagamento( codicePrenotazione, pagamentoNuovoXMLFragment.getNumeroCarta(), pagamentoNuovoXMLFragment.getScadenza(), pagamentoNuovoXMLFragment.getIntestazione()); String codiceAcquisto = acquistoNuovoServiceImpl.processaOrdine( codicePrenotazione, indirizzoNuovoXMLFragment.getNome().concat(" ").concat(indirizzoNuovoXMLFragment.getCognome()), indirizzoNuovoXMLFragment.getIndirizzo(), indirizzoNuovoXMLFragment.getCap(), indirizzoNuovoXMLFragment.getCitta(), indirizzoNuovoXMLFragment.getNazione() ); String codiceTrackAndTrace = acquistoNuovoServiceImpl.getTrackAndTraceTicket(codiceAcquisto); AcquistoNuovoRispostaType risposta = new AcquistoNuovoRispostaType(); risposta.setCodiceAcquisto(codiceAcquisto); risposta.setCodiceOutorizzazioneCarta(codiceAutorizzazioneCarta); risposta.setDataAcquisto(acquistoNuovoXMLFragment.getDataAcquisto()); risposta.setCodiceSpedizioneTT(codiceTrackAndTrace);
Ed ecco il diagramma di sequenza tra endpoint e metodi della classe di implementazione.
Figura 7 – Sequence diagram tra endpoint e metodi della classe di implementazione del servizio.
Conclusioni
Nella prima e nella seconda parte abbiamo descritto un semplice esempio di implementazione di un web service attraverso Spring-WS.
In questo terzo articolo abbiamo messo in luce i benefici derivanti dal pattern di sviluppo che questo framework introduce. Lo scarso accoppiamento tra l’implementazione dell’endpoint e della logica applicativa del servizio rende più flessibile l’adeguamento dell’interfaccia e/o della logica applicativa.
La codifica isolata delle nuove implementazioni rispetto agli sviluppi in esercizio aggiunge ulteriore robustezza: per il rilascio del nuovo servizio il collaudo sarà circoscritto alle sole nuove funzionalità. Chiaramente resta a carico dello sviluppatore l’effort relativo allo sviluppo dell’endpoint e del servizio.
Riferimenti
[1] Blog “Shared Experience”
http://demirm.blogspot.com/
[2] Best practices for interoperable web service applications
www.frotscher.com/download/JUG-ContractFirst.pdf
[3] Apache Muse – Conflicting Version of WSDL4J in WebSphere Deployments
http://ws.apache.org/muse/docs/2.2.0/manual/troubleshooting/wsdl4j-version-on-websphere.html
[4] Web Services Description Language (WSDL 1.1)
http://www.w3.org/TR/wsdl
[5] Web Services Description Language (WSDL 2.0)
http://www.w3.org/TR/2007/REC-wsdl20-primer-20070626/
[6] Metro Web Services for the Java Platform
http://java.sun.com/webservices/index.jsp
[7] The Web Services Interoperability Organization
http://www.ws-i.org/
[8] Spring Framework
http://static.springsource.org/spring-ws/sites/1.5/reference/html/tutorial.html
[9] IBM sulla scelta del WSDL
http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
[10] IBM sui web service “document style”
http://www.ibm.com/developerworks/webservices/library/ws-docstyle.html
[11] IBM sul mapping da WSDL a SOAP
http://www.ibm.com/developerworks/webservices/library/ws-tip-namespace.html
[12] Arjen Poutsma, Rick Evans, Tareq Abed Rabbo, “Spring Web Services. Reference Documentation”