home >> mb148
di

Luigi Bennardis

Nella stessa sezione>
gxt-1
mobileapps-1
ice-3
cloud-1
ws_spring-2
webbeans-9
osgi_fw-1
Allegati>
springwsdemo.z...
Nella stessa serie
ws_spring-1
ws_spring-2
ws_spring-3
ws_spring-4
ws_spring-5
News on Feed


Bookmarking
bookmark on Delicious bookmark on Digg bookmark on Furl bookmark on Reddit bookmark on Slashdot bookmark on Technorati
 
 


MokaByte 148 - Febbraio 2010

Realizziamo un Web Service con Spring-WS

II parte: Sviluppo e pubblicazione del Web Service

Continuiamo con lo sviluppo del Web Service iniziato nel numero precedente. Dopo aver visto lo schema, e percorso i primi passi, procediamo con l'implementazione attraverso l'ambiente di sviluppo IBM RSA.

Descriviamo di seguito l’implementazione, attraverso l’ambiente di sviluppo IBM RSA, del Web Service descritto dallo schema presentato precedentemente. Iniziamo dalla definizione del runtime di RSA-RAD 7.

Definizione delle librerie di runtime

Rispetto alla distribuzione di spring-ws-1.5.7 è stato necessario integrare il runtime dell’ambiente di sviluppo RSA-RAD 7 con le seguenti librerie:

  1. Jaxen (Jaxen1.1-beta-5.jar), quale motore Java XPath. Si tratta di un object model walker universale, capace di risolvere espressioni XPath su modelli multipli.
  2. Jdom (Jdom-1.0.jar), è la libreria Java che dispone delle API di parsing, creazione, modifica e serializzazione di documenti XML.
  3. JSR 173 (JSR173_api.jar), contiene le nuove API di streaming XML basate su tecnologia StAX: API Java per il pull-parsing dell’XML.
  4. Spring (Spring.jar), runtime del framework in versione 2.0.8.
  5. Wsdl4J (Wsdl4j-1.6.2.jar), è il toolkit del WSDL per Java, necessario alla creazione, rappresentazione e modifica dei documenti WSDL in base alla specifica JSR 110.

Figura 1 - Librerie di run time per RSA-RAD 7.

 

Configurazione dell’ambiente di sviluppo

Nella configurazione dell’ambiente di sviluppo, ci siamo accorti che la libreria WSDL4J distribuita in versione 1.4 con in binari di WebSphere Application Server 6.0 e 6.1 non è compatibile con il runtime di Spring WS. Abbiamo quindi distribuito la versione 1.6.1 di WSDL4J nella cartella  /WEB-INF/lib della Web Application e definito nel descrittore di distribuzione del progetto EAR la politica di class loading a PARENT_LAST.
È stato così possibile aggirare il problema, configurando il server in modo che questo usi il classloader dell’applicazione prima di quello del contenitore o delle classi di sistema. Questo ci assicura che le classi di WSDL4J distribuite nella cartella  /WEB-INF/lib dell’applicazione vengano caricate prima di quelle distribuite in  $WAS_HOME/lib.
Questi cambiamenti non avranno effetto sulle eventuali altre applicazioni distribuite nello stesso container Java EE che, non avendo nel proprio bundle di distribuzione nessuna libreria WSDL4J, utilizzeranno quelle che il server risolve sulla catena dei classloader. Tipicamente il classloader del contenitore troverà la libreria WSDL4J in $WAS_HOME/lib.

Figura 2 - Politiche di class loading per un’applicazione Java EE.

 

Realizzazione del servizio

Passiamo ora ai passi di definizione del Web Service. Prenderemo spunto da un progetto dimostrativo pubblicato nel bundle di Spring-WS caratterizzato da una configurazione standard che pubblica il Web Service in una Web Application Java EE.  

Descrittore di distribuzione Java EE della web application.

Nel descrittore di distribuzione (/WEB-INF/web.xml) della web application che pubblica il Web Service viene definita la MessageDispatcherServlet. Si tratta di una estensione della DispatcherServlet di Spring che ha la funzione di semplificare il dispatch dei messaggi di un Web Service separando le istanze delle classi WebServiceMessageReceiverHandlerAdapter, MessageDispatcher e WsdlDefinitionHandlerAdapter. In questo modo vengono combinate le funzionalità di gestione del flusso di request (MessageDispatcher) con la pubblicazione del Web-Service (DispatcherServlet). La WsdlDefinitionHandlerAdapter abilita la pubblicazione del WSDL verso i client. Come nelle configurazioni standard Java EE il marcatore di url-pattern definisce le richieste HTTP che dovranno essere indirizzate verso questa servlet. Nell’esempio illustrato di seguito indichiamo il descrittore di distribuzione della Web Application riportato dalla documentazione di Spring-WS, dove tutte le richieste (<url-pattern>/*</url-pattern>) vengono indirizzate verso la MessageDispatcherServlet. Ecco quindi il descrittore di distribuzione della Web Application:

<!-- DEFINIZIONE DELLA MessageDispatcherServlet di SPRING-WS -->
<servlet>
    <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet
    </servlet-class>
    <init-param>
    <!—TRASFORMAZIONE DEGLI ATTRIBUTI DI LOCALIZZAZIONE DEI WSDL -->
        <param-name>transformWsdlLocations</param-name>
    <param-value>false</param-value><!-- true -->
    </init-param>
</servlet>
<!-- TUTTE LE RICHIESTE VENGONO INDIRIZZATE SU QUESTA SERVLET -->
<servlet-mapping>
    <servlet-name>spring-ws</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

Vedremo più avanti come, nel contesto applicativo di Spring-WS, definito dal file /WEB-INF/[servlet-name]-servlet.xml, la MessageDispatcherServlet rileva le definizioni delle classi che definiscono il Web Service: si tratta dei bean WsdlDefinition (l’"acquisto" del nostro esempio), EndpointAdapters, EndpointMappings, e l’eventuale EndpointExceptionResolvers.

Configurazione dei bean componenti Spring-WS

La MessageDispatcherServlet, in quanto derivata dalla DispatcherServlet di Spring, alla sua inizializzazione esegue una look up del file /WEB-INF/[servlet-name]-servlet.xml (nel nostro caso: /WEB-INF/spring-ws-servlet.xml), dove si dovranno definire i bean che definiscono il Web Service. Il nome del WSDL che viene pubblicato viene definito dal bean che definisce la classe DefaultWsdl11Definition. La DefaultWsdl11Definition, la prima volta che ne viene fatta richiesta, genera il WSDL del servizio a partire dallo schema pubblicato quale contratto del servizio. Questa classe esegue una iterazione su tutti gli element definiti nello schema creandone un message per ciascuno. A questo punto crea una WSDL operation per tutti i message denominandola con il suffisso definito per la request e la response.
Per default i suffissi di request e response sono "Request" e "Response", ma si possono cambiare attraverso le proprietà requestSuffix and responseSuffix. Sulla base di queste operazioni la stessa classe crea anche una portType, un binding e un service basato su queste operazioni. In questo bean troviamo il riferimento ("schema") al bean del contratto del servizio.
Attraverso la classe CommonsXsdSchemaCollection sarà anche possibile utilizzare schema multipli come riportato in un altro esempio distribuito con Spring-WS. Ecco di seguito l’esempio per la configurazione di Spring-WS con schema multipli.

<bean id="schemaCollection" 
class="org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection">
<description>
This bean wrap the messages.xsd (which imports types.xsd), and inlines them as a one.
</description>
<property name="xsds">
<list>
<value>/WEB-INF/xsds/Orders.xsd</value>
<value>/WEB-INF/xsds/Customers.xsd</value>
</list>
</property>
<property name="inline" value="true"/>
</bean>

Se la proprietà inline è abilitata allora vengono risolte e incluse tutti gli import e gli XSD dichiarati inline nel WSDL (vengono quindi considerati come uno solo). Questo semplifica lo sviluppo degli schema, e rende possibile separare la loro modifica. All’URL http://localhost:<HTTP_PORT>/ECommSpringWS/acquisto.wsdl sarà pubblicato il WSDL; il segnaposto <HTTP_PORT> indica la porta di ascolto dell’HTTP Server che, nel nostro caso, vale 9081.

Figura 3 - Rappresentazione UML del WSDL.

 


Ecco quindi il Contesto Spring-WS, spring-ws-servlet.xml:

<!-- DEFINISCE LA CLASSE DI IMPLEMENTAZIONE DELL’END POINT -->
<bean id="acquistoEndpoint"
    class="it.luigibennardis.Ecommerce.Acquisto.ws.AcquistoEndPoint">
    <constructor-arg ref="ecommService"/>
</bean>
<!-- DEFINISCE LA CLASSE DI IMPLEMENTAZIONE DEL SERVICE -->
<bean id="ecommService" class="it.luigibennardis.Ecommerce.Acquisto.ws.service.AcquistoImpl"/>
<!-- DEFINISCE IL MAPPING TRA LA REQUEST E L’END-POINT -->
<bean class="org.springframework.ws.server.endpoint.mapping
        .PayloadRootQNameEndpointMapping">
    <property name="mappings">
        <props>
            <prop
            key= _
            "{http://www.luigibennardis.it/spring-ws
            /Ecomm/Acquisto/types}
            AcquistoOnLineRequest">acquistoEndpoint
            </prop>
        </props>
    </property>
    <property name="interceptors">
        <bean class= _
        "org.springframework.ws.server.endpoint.interceptor
        .PayloadLoggingInterceptor"/>
    </property>
</bean>
<bean id="acquisto" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
    <property name="schema" ref="schema"/>
    <property name="portTypeName" value="Ecommerce"/>
    <property name="locationUri" value="/acquistoService/"/>
    <property name="targetNamespace" value="http://www.luigibennardis.it/ecomm/definitions"/>
</bean>
<!-- DEFINIZIONE DELLO SCHEMA -->
<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
    <property name="xsd" value="/WEB-INF/xsd/EcommerceAcquistoTypes.xsd"/>
</bean>

Ecco poi il listato del WSDL del servizio.

<wsdl:message name="AcquistoOnLineRequest">
    <wsdl:part name="AcquistoOnLineRequest" element="sch:AcquistoOnLineRequest">
    </wsdl:part>
</wsdl:message>
<wsdl:message name="AcquistoOnLineResponse">
    <wsdl:part name="AcquistoOnLineResponse" element="sch:AcquistoOnLineResponse">
    </wsdl:part>
</wsdl:message>
<wsdl:portType name="Ecommerce">
    <wsdl:operation name="AcquistoOnLine">
        <wsdl:input name="AcquistoOnLineRequest"
                message="tns:AcquistoOnLineRequest">
        </wsdl:input>
        <wsdl:output name="AcquistoOnLineResponse"
                message="tns:AcquistoOnLineResponse">
        </wsdl:output>
    </wsdl:operation>
</wsdl:portType>
<wsdl:binding name="EcommerceSoap11" type="tns:Ecommerce">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="AcquistoOnLine">
        <soap:operation soapAction=""/>
        <wsdl:input name="AcquistoOnLineRequest">
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output name="AcquistoOnLineResponse">
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>
<wsdl:service name="EcommerceService">
    <wsdl:port name="EcommerceSoap11" binding="tns:EcommerceSoap11">
        <soap:address location="/acquistoService/"/>
    </wsdl:port>
</wsdl:service>

E di seguito, riportiamo il codice di una request di esempio.

<soapenv:Envelope
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:typ="http://www.luigibennardis.it/spring-ws/Ecomm/Acquisto/types">
    <soapenv:Header/>
    <soapenv:Body>
        <typ:AcquistoOnLineRequest>
            <typ:Acquisto>
                <typ:DataAcquisto>2009-06-25</typ:DataAcquisto>
                <typ:CodiceProdotto>AB00001</typ:CodiceProdotto>
                <typ:Quantita>125</typ:Quantita>
                <typ:PrezzoUnitario>1.05</typ:PrezzoUnitario>
                <typ:PrezzoTotale>1234.98</typ:PrezzoTotale>
            </typ:Acquisto>
            <typ:Indirizzo>
                <typ:Nome>Luigi</typ:Nome>
                <typ:Cognome>Bennardis</typ:Cognome>
                <typ:Indirizzo>Salita di San Sebastianello, 1</typ:Indirizzo>
                <typ:Cap>00100</typ:Cap>
                <typ:Citta>Roma</typ:Citta>
            </typ:Indirizzo>
            <typ:Pagamento>
                <typ:TipoCarta>VISA</typ:TipoCarta>
                <typ:NumeroCarta>4563786554365463</typ:NumeroCarta>
                <typ:Intestazione>Luigi Bennardis</typ:Intestazione>
                <typ:Scadenza>0110</typ:Scadenza>
            </typ:Pagamento>
        </typ:AcquistoOnLineRequest>
    </soapenv:Body>
</soapenv:Envelope>

Per il nostro esempio abbiamo utilizzato la classe di mapping "PayloadRootQNameEndpointMapping".
Questa stabilisce che il mapping tra la classe che implementa l’endpoint (nel nostro esempio il bean id=acquistoEndpoint) e la request sia risolto in base alla ricerca del nome qualificato del root element del payload XML in request. Questo, ottenuto dalla concatenazione del "namespace URI" e della "localPart", dovrà essere univoco nel contesto di mapping. Con la definizione di questo mapping tutte le richieste che hanno un payload root element definito dal namespace "http://www.luigibennardis.it/spring-ws/Ecomm/Acquisto/types" e da una localPart "acquistoOnLineRequest" vengono indirizzate verso l’endpoint "acquistoEndpoint". Vedremo come, nell’implementazione dell’endpoint, la variabile di firma acquistoRequest del metodo invokeInternal,  conterrà il payload XML inviato dal client.

Figura 4 - Mapping tra la request e la classe di implementazione dell’endpoint.

 

Implementazione del servizio

Ultimata la definizione del file di configurazione passiamo all’implementazione dell’endpoint e del servizio. Di seguito riportiamo il fragment del file di configurazione dove viene definita l’injection della classe di implementazione del servizio nell’endpoint.

Figura 5 - Endpoint  e classe di implementazione del WS.



La classe che implementa il servizio viene sintetizzata dal seguente class diagram.

Figura 6 - Class diagram dell’endpoint.



Poiche’ l’endpoint estende la classe astratta AbstractDomPayloadEndpoint (necessaria alla gestione del payload XML in request e response) sarà necessario implementare l’override del metodo invokeInternal. In questo metodo il programmatore codificherà la logica di parsing del payload XML della request e l’eventuale codifica della response, che dovrà essere aderente all’interfaccia del WSDL. In questo esempio sono state utilizzate le classi Document, Element e NodeList della libreria org.w3c.dom.
Oltre alla classe AbstractDomPayloadEndpoint che utilizza le API del W3C DOM, ci sono altre classi base che utilizzano API DOM alternative. Spring-WS supporta molte API DOM, quali l’AbstractJDomPayloadEndpoint che permette di usare JDM, mentre AbstractXomPayloadEndpoint usa XOM. Tutte queste classi base per l’implementazione di endpoint dispongono di un metodo invokeInternal analogo a quello implementato nel nostro esempio.
Da ciò deriva che Spring-WS utilizza un approccio "message driven" incentrato sull’XML, realizza cioè un layer distinto, in un modello assimilabile a un pattern Model View Controller, a cui viene demandata la gestione della request che viene inviata dal client, e della response restituita.
Nel modello di sviluppo basato su JAX-RPC la ServletEndpoint utilizza invece un meccanismo di chiamata a procedura remota, caratterizzato dal fatto che lo sviluppatore può esporre logica applicativa senza dover codificare la conversione di oggetti da e verso l’XML, realizzando un modello incentrato sull’implementazione del servizio.

Dettagli di codifica dell’endpoint

Diamo adesso evidenza di alcuni dettagli di codifica dell’endpoint. Rimandiamo il lettore all’allegato (menu in alto a sinistra) dove potrà esaminare nella loro completezza i sorgenti del workspace.
Di seguito la codifica di controllo della corrispondenza del namespace della busta SOAP, definita nel file XSD, alla request inviata all’endpoint

Assert.isTrue(NAMESPACE_URI.equals(
        acquistoRequest.getNamespaceURI()),
        "Il Namespace della request non è valido");
Assert.isTrue(GET_ACQUISTO_REQUEST.equals(
        acquistoRequest.getLocalName()),
        "La request definita nel payload XML non è valida");

La serializzazione nel JavaBean del tipo complesso definito nel payload XML viene codificata attraverso le API Document Object Model. Per leggibilità riportiamo il codice relativo alla de-serializzazione di uno dei tipi complessi.

//*** TIPO COMPLESSO ACQUISTO
AcquistoType acquistoXMLFragment = new AcquistoType();
NodeList nodoDataAcquisto
    = acquistoRequest.getElementsByTagName("typ:DataAcquisto");
Element elementDataAcquisto
    = (Element)nodoDataAcquisto.item(0);
DateFormat formatter ;
Date date ;
formatter = new SimpleDateFormat("yyyy-MM-dd");
date = (Date)formatter.parse(
    elementDataAcquisto.getFirstChild().getNodeValue());
Calendar cal=Calendar.getInstance();
cal.setTime(date);
acquistoXMLFragment.setDataAcquisto(cal);
NodeList nodoCodiceProdotto
    = acquistoRequest.getElementsByTagName("typ:CodiceProdotto");
Element elementCodiceProdotto
    = (Element)nodoCodiceProdotto.item(0);
acquistoXMLFragment.setCodiceProdotto(
    elementCodiceProdotto.getFirstChild().getNodeValue());
NodeList nodoQuantita
    = acquistoRequest.getElementsByTagName("typ:Quantita");
Element elementQuantita
    = (Element)nodoQuantita.item(0);
BigInteger quantita
    = new BigInteger(elementQuantita.getFirstChild().getNodeValue());
acquistoXMLFragment.setQuantita(quantita);
NodeList nodoPrezzoUnitario
    = acquistoRequest.getElementsByTagName("typ:PrezzoUnitario");
Element elementPrezzoUnitario
    = (Element)nodoPrezzoUnitario.item(0);
Double prezzoUnitario
    = new Double(elementPrezzoUnitario.getFirstChild().getNodeValue());
acquistoXMLFragment.setPrezzoUnitario(prezzoUnitario);
NodeList nodoPrezzoTotale
    = acquistoRequest.getElementsByTagName("typ:PrezzoTotale");
Element elementPrezzoTotale
    = (Element)nodoPrezzoTotale.item(0);
Double prezzoTotale
    = new Double(elementPrezzoTotale.getFirstChild().getNodeValue());
acquistoXMLFragment.setPrezzoUnitario(prezzoTotale);

Ecco poi la chiamata alla classe di implementazione del servizio definita dall’injection di Spring nel file di configurazione. Come potremo esaminare dai sorgenti, si tratta di una classe Java standard che non ha nessuna relazione diretta all’implementazione di un Web Service o di qualsiasi altra tecnologia.

public AcquistoEndPoint(AcquistoImpl acquistoImpl)
    throws JDOMException {
Assert.notNull(acquistoImpl, "acquistoImpl must not be null");
    //     IMPOSTO LA CLASSE DI IMPLEMENTAZIONE
    this.acquistoServiceImpl = acquistoImpl;
}
//*** INVOCAZIONE DELLA LOGICA DEL SERVIZIO
String codicePrenotazione = acquistoServiceImpl.verificaDisponibilitaProdotti(
    acquistoXMLFragment.getCodiceProdotto(), acquistoXMLFragment.getQuantita());
String codiceAutorizzazioneCarta
    = acquistoServiceImpl.eseguiPagamento(codicePrenotazione,
                pagamentoXMLFragment.getNumeroCarta(),
                pagamentoXMLFragment.getScadenza(),
                pagamentoXMLFragment.getIntestazione());
String codiceAcquisto
    = acquistoServiceImpl.processaOrdine(codicePrenotazione,
                indirizzoXMLFragment.getNome().concat("
                ").concat(indirizzoXMLFragment.getCognome()),
                indirizzoXMLFragment.getIndirizzo(),
                indirizzoXMLFragment.getCap(),
                indirizzoXMLFragment.getCitta() );

Riportiamo qui la codifica del bean che serializza i dati necessari alla creazione della response e invio di questa al client.

AcquistoRispostaType risposta = new AcquistoRispostaType();
risposta.setCodiceAcquisto(codiceAcquisto);
risposta.setCodiceOutorizzazioneCarta(codiceAutorizzazioneCarta);
risposta.setDataAcquisto(acquistoXMLFragment.getDataAcquisto());
//*** CREAZIONE DELLA RESPONSE
org.w3c.dom.Element response
    = responseDocument.createElementNS(NAMESPACE_MESSAGES,
                GET_ACQUISTO_RESPONSE);
Element elAcquistoRisposta = responseDocument.createElement("AcquistoRisposta");
Element elDataAcquisto = responseDocument.createElement("DataAcquisto");
Element elCodiceAcquisto = responseDocument.createElement("CodiceAcquisto");
Element elCodiceOutorizzazioneCarta
    = responseDocument.createElement("CodiceAutorizzazioneCarta");
elDataAcquisto.appendChild(
        responseDocument.createTextNode(risposta.getDataAcquisto().toString()));
elCodiceAcquisto.appendChild(
        responseDocument.createTextNode(risposta.getCodiceAcquisto()));
elCodiceOutorizzazioneCarta.appendChild(
        responseDocument.createTextNode(risposta.getCodiceOutorizzazioneCarta()));
elAcquistoRisposta.appendChild(elDataAcquisto);
elAcquistoRisposta.appendChild(elCodiceAcquisto);
elAcquistoRisposta.appendChild(elCodiceOutorizzazioneCarta);
response.appendChild(elAcquistoRisposta);
/* INVIA LA RESPONSE AL CLIENT */
return response;

 

Figura 7 - Sequence diagram tra endpoint e metodi della classe di implementazione del servizio. 



Il codice seguente riporta invece un esempio di response inviata al client

<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Header/>
    <soapenv:Body>
        <AcquistoOnLineResponse>
            <AcquistoRisposta>
                <DataAcquisto>2009/09/02</DataAcquisto>
                <CodiceAcquisto>ABGH56002</CodiceAcquisto>
                <CodiceAutorizzazioneCarta>
                    13423345366
                </CodiceAutorizzazioneCarta>
            </AcquistoRisposta>
        </AcquistoOnLineResponse>
    </soapenv:Body>
</soapenv:Envelope

Infine riportiamo il log di WAS dove troviamo i riscontri dell’inizializzazione di Spring-WS alla prima chiamata al WSDL del servizio pubblicato.

[03/07/09 11.45.10:790 CEST] 0000000a WsServerImpl  A   WSVR0001I:
            Server server1 aperto per e-business
[03/07/09 11.49.34:000 CEST] 00000023 WebApp        A   SRVE0180I:
            [ECommSpringWS_EAR#ECommSpringWS.war] [/ECommSpringWS] [Servlet.LOG]
: Initializing Spring FrameworkServlet ’spring-ws’
[03/07/09 11.49.34:031 CEST] 00000023 MessageDispat I
            org.springframework.web.servlet.FrameworkServlet initServletBean
            FrameworkServlet ’spring-ws’: initialization started
[03/07/09 11.49.34:047 CEST] 00000023 XmlWebApplica I
            org.springframework.context.support.AbstractApplicationContext
            prepareRefresh Refreshing org.springframework.web.context.support
            .XmlWebApplicationContext@640a640a
            : display name [WebApplicationContext for namespace ’spring-ws-servlet’];
            startup date [Fri Jul 03 11:49:34 CEST 2009]; root of context hierarchy
[03/07/09 11.49.34:187 CEST] 00000023 XmlBeanDefini I
            org.springframework.beans.factory.xml.XmlBeanDefinitionReader
            loadBeanDefinitions
            Loading XML bean definitions from ServletContext resource
            [/WEB-INF/spring-ws-servlet.xml]
[03/07/09 11.49.34:312 CEST] 00000023 XmlWebApplica I
            org.springframework.context.support.AbstractApplicationContext
            obtainFreshBeanFactory Bean factory for application context
            [org.springframework.web.context.support.
            XmlWebApplicationContext@640a640a]
            : org.springframework.beans.factory.support
            .DefaultListableBeanFactory@7100710
[03/07/09 11.49.34:359 CEST] 00000023 DefaultListab I
            org.springframework.beans.factory.support.DefaultListableBeanFactory
            preInstantiateSingletons Pre-instantiating singletons in
            org.springframework.beans.factory.support
            .DefaultListableBeanFactory@7100710: defining beans
            [acquistoEndpoint,ecommService,
            org.springframework.ws.server.endpoint.mapping
            .PayloadRootQNameEndpointMapping,
            acquisto, schema]; root of factory hierarchy
[03/07/09 11.52.22:807 CEST] 00000023 SaajSoapMessa I
            org.springframework.ws.soap.saaj.SaajSoapMessageFactory
            afterPropertiesSet Creating SAAJ 1.2 MessageFactory
[03/07/09 11.52.22:901 CEST] 00000023 MessageDispat I
            org.springframework.web.servlet.FrameworkServlet initServletBean
            FrameworkServlet ’spring-ws’: initialization completed in 168854 ms
[03/07/09 11.52.22:916 CEST] 00000023 ServletWrappe I   SRVE0242I:
            [ECommSpringWS_EAR] [/ECommSpringWS] [spring-ws]
            : Inizializzazione riuscita.

Conclusioni

Attraverso Spring-WS  abbiamo descritto l’implementazione di un semplice Web Service con un approccio "document-first". Questo framework , preservando il principio di interoperabilità, agevola l’applicazione di questo approccio in quanto risparmia allo sviluppatore la codifica del WSDL. Allo stesso tempo Spring-WS realizza un modello di sviluppo che disaccoppia, in stile MVC, l’implementazione dell’endpoint da quella della logica funzionale, che lo sviluppatore dovrà in ogni caso codificare.

Nel prossimo articolo illustreremo come i benefici derivanti da questo scarso accoppiamento trovano la loro naturale applicazione durante il ciclo di vita del servizio: mostreremo quanto sia più flessibile gestire la modifica dell’interfaccia e dell’implementazione.

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"

Invia un messaggio alla redazione su questo articolo

Mittente (facoltativo - immetti una email valida se desideri ricevere una risposta)

Come hai trovato questo articolo?

 

Mi sono addormentato

Interessante con il giusto taglio

Argomento non interessante

Molto interessante

Argomento interessante, ma non approfondito

Efficace, ha risolto i miei problemi

Interessante

Mi sono commosso

 

Lascia un commento su questo articolo