JAXB and the root element

Recently I helped a friend to implement the client of a web service using Axis2 and Tomcat, developing the client first and the jsp after. After testing the web service with SoapUI we started to develop the client with Eclipse.

The problem with this web service is that the body of the method is an entire xml string contained in a CDATA element, not only for for the request but also for the answer, of course this creates problem to generate the java objects from the wsdl file since the element is not defined as XML.

Luckily we received the xsd files so we generated the java classes with JAXB data binding which is implemented, and it can be executed, through the application xjc that you can find inside the bin folder of the Java Virtual Machine. Note that JAXB is the default databinding of Apache Cxf.

JAXB worked nicely but we had the problem to extract from the xml string the node container which needed to be declared as root element, in other words you need to use the @XMLRootElement annotation otherwise you can have the exception:

unexpected element (…) , Expected elements are (none).

when you unmarshal (from string to java object) the element.

 

Advertisements

Web Services: stili, overloading e databinding

Nei precedenti post avevo già segnalato il fatto che per mantenere l’interoperabilità dei web services, partendo da un file wsdl, occorre rispettare il cosiddetto Basic Profile 1.1. Il Basic Profile non fa altro che far applicare delle restrizioni sulla scrittura del file wsdl in modo tale da garantire una certa interoperabilità.

L’interoperabilità non significa che tutto puo’ funzionare come vogliamo noi e difatti uno dei problemi di cui vi sto accennando nell’articolo è il problema dell’overloading dei metodi.

Occorre dire che ci sono principalmente 2 modi per descrivere un file wsdl compatibile con il Basic Profile e questi sono RPC/literal e Document/literal (per maggiori dettagli vedere il seguente articolo). Fatto sta che tra le 2 quella più usata è Document/literal in versione “wrapped”.

Questa versione è usata in pratica da .NET di default mentre la versione RPC no, tra l’altro Microsoft fa parte del consorzio WS-I, di consequenza scegliere per scegliere uno stile conviene adottare questo in modo da essere interoperabili con .NET (non me ne vogliano i puristi ma io lavoro con web services in java e questi devono comunicare in web services in .NET).

Secondo l’articolo che vi ho linkato un esempio di file wsdl in stile Document/literal wrapped è il seguente:

<types>
    <schema>
        <element name="myMethod">
            <complexType>
                <sequence>
                    <element name="x" type="xsd:int"/>
                    <element name="y" type="xsd:float"/>
                </sequence>
            </complexType>
        </element>
        <element name="myMethodResponse">
            <complexType/>
        </element>
    </schema>
</types>
<message name="myMethodRequest">
    <part name="parameters" element="myMethod"/>
</message>
<message name="empty">
    <part name="parameters" element="myMethodResponse"/>
</message>

<portType name="PT">
    <operation name="myMethod">
        <input message="myMethodRequest"/>
        <output message="empty"/>
    </operation>
</portType>

Come vedete la sezione message contiene solo una “part” per input/output. La parte che contiene l’input ha l’elemento myMethod, nome che deve essere uguale al nome dell’operazione. L’elemento myMethod è quindi un tipo complesso definito da una sequenza di elementi.

Uno dei problemi messi in evidenza è l’impossibilità di fare overloading dei metodi perchè se il metodo myMethod  con i 2 parametri corrisponde all’elemento myMethod non è possibile aggiungere in xml un secondo elemento dal nome myMethod con un solo parametro per via dell’XML stesso.

Tuttavia il problema diciamo non si pone poichè solo con file WSDL 1.1 è possibile l’overloading mentre con file WSDL 2.0 no anche se l’adozione di quest’ultimo non trova piena applicazione.

A riguardo l’uso dello stile wrapped vi suggerisco un articolo tratto dal blog di  Anne Thomas Annes, esperta in web services, che ha collaborato con WS-I ed una interessante spiegazione in questa mailling list (vedere ore 13:43)

Il tutto ovviamente si ricollega al databinding perchè, stile a parte,  occorre scegliere il databinding, e il fatto che ADB e Jibx supportano lo stile unwrapped e wrapped mentre Xmlbeans solo wrapped  (vedi articolo) viene meno se scegliamo lo stile wrapped.

Personalmente uso Xmlbeans per una serie di metodi utili forniti dall’interfaccia che ogni oggetto xml implementa. Per alcuni dettagli sulla storia e struttura di xmlbeans suggerisco questo articolo (oltre che il sito ufficiale) di David Bau uno dei creatori di Xmlbeans.

Nota a parte: ADB e Xmlbeans sono databinding della Apache foundation. Xmlbeans in particolare è stato donato da Bea System (nel settembre 2003), una delle società fondatrici della WS-I, da sempre coinvolta nel campo dei web services con il suo Esb, e di recente (aprile 2008) comprata da Oracle altra società fondatrice e leadership della WS-I.

Non penso di rompervi più con il Basic Profile :-)

WSO2 Esb, WSAS e Xmlbeans

Piccola nota per quanti seguano le mie avvenure con questi software.

In pratica, poichè mi piace usare Xmlbeans come databinding invece di usare Adb, ho scoperto che quelli di WSO2 non hanno aggiornate alcune librerie.

Se in pratica avete usato Xmlbeans 2.3.0 (lo vedete tra le librerie dei vostri plugin di Axis2 per Eclipse) per la generazione dei vostri webservices e ne avete fatto il deploy su Esb o WSAS avrete la seguente eccezione:

org.apache.xmlbeans.SchemaTypeLoaderException: XML-Beans compiled schemas: Incompatible minor version – expecting up to 23, got 24

Questo in pratica accade perchè Xmlbeans si appoggia su Xbean e guarda caso nell’esb si trova Xbean 2.2.0 mentre in WSAS addirittura la versione 2.1.0 quando in entrambi c’è Xmlbeans 2.3.0.

Occorre quindi aggiornare Xbean che potete trovare a questo link:

http://www.eviware.com/repository/maven2/xmlbeans/xbean/2.3.0/

Ho fatto riferimento a WSO2 Esb 1.7.1 e WSO2 WSAS 2.3

Osservazioni su esb, web service framework e application server

Attualmente sono coinvolto in un progetto dove si lavora con web services e bpel. Nel tempo ho scoperto che la proliferazione di software open source benchè sia una ottima cosa deve fare i conti con gli standard che sono quelli a cui bisogna attenersi se si vuole cercare di raggiungere una certà interoperabilità.

In un precedente articolo avevo già accennato ai problemi di interoperabilità per quanto riguarda i file wsdl e che il consorzio WS-I propone degli strumenti per ridurre i rischi di interoperabilità. La leadership di WS-I è guidata da Michael Bechauf vicepresidente di SAP AG e partecipante alla board di Eclipse. Tra le altre compagnie figurano Microsoft, Fujitsu, HP, Sun, IBM, Intel, Oracle.

Ma i web services si appoggiano ai Web services framework e normalmente sono instradati da Esb e poi avrete bisogno di application server. Quali scegliere ? La risposta a questa domanda fa perdere molto tempo ed una guida è di sicuro è capire quali standard esistono e quali sono i software che si attengono.

Nel campo java questi standard si ottengono dalle implementazioni delle JSR. Per quanto riguarda i web service framework la JSR più importante è la JSR 224 che descrive JAX-WS un modo per realizzare data binding tra file wsdl e le classi java che realizzano i servizi.

JAX-WS è adottato da Apache CXF e Metro di Sun. Axis2 ha il supporto ma è venuto dopo nel tempo.

Nel campo degli esb le JSR importanti sono JSR 208 e JSR 312 che esprimono il concetto di JBI. JBI è uno standard imposto poichè in un bus possono essere attaccati diversi software che usano ad esempio JMS, eventi BPEL ecc. In questo ambito ritroviamo praticamente Apache ServiceMix e OpenESB di Sun. In pratica si appoggiano alla JSR 208 inseguendo la 312 che apporta le migliorie allo standard JBI.

Apache Synapse per quello che ho capito sta stringendo una collaborazione con quelli di ServiceMix per essere aiutati a raggiungere lo standard JBI.

Nel panorama degli application server si nota che ServiceMix ha un ottima integrazione con Apache Geronimo (completamente aderente a Java EE 5) mentre OpenESb e Metro si integrano facilmente con Glassfish che ovviamente Sun publicizza.

Tomcat è un semplice servlet container che si presta anche ed ha il vantaggio che rispetto agli altri, per la sua semplicità, risulta più veloce. Spesse volte quelli di Netbeans spiegano come usare Tomcat alternativamente a Glassfish.

Merita un discorso a parte JBoss. Per quelli di Jboss il loro stack è rappresentato da Jboss Native, Metro e CXF quindi una combinazione dei precedenti. Tuttavia loro rilasciano il loro esb e il loro application server. Vi faccio notare che Hibernate è condotto da quelli di Jboss.

Quindi fino a qui abbiamo visto Apache, Sun e Jboss con un piccolo zampino di IBM che fornisce supporto ad Apache Geronimo e ad Eclipse (CXF ha qualche plugin per Eclipse). Manca il tassello di BPEL.

Lo standard BPEL è stato sottomesso all’OASIS ed è denominato WS-BPEL. I più attivi questo campo sono stati Microsoft, IBM e BEA e SAP. Da quelli di Apache la risposta è Apache ODE sul cui sito è spiegato come usarlo con Tomcat e un JBI container, a caso, ServiceMix anche se dicono di avere dei problemi con quest’ultimo in quanto non proprio aderente allo standard JBI.

Con software come Intalio che si appoggiano su Apache ODE potete progettare i processi BPEL. Faccio notare che quelli di Intalio mostrano nel loro sito la collaborazione con quelli di ServiceMix e Mule Esb un esb che può essere usato con un web container come Tomcat o un application server come Geronimo e fa uso di un application framework come Apache CXF (qui un articolo sull’integrazione).

Quelli di Sun invece inglobano il BPEL service engine direttamente nel loro esb OpenEsb e potete progettare i vostri processi BPEL direttamente da Netbeans.

Eclipse ha poi il suo plugin STP che permette di progettare BPEL.

In tutto questo panorama si scorge l’esb Petals che insieme ad OpenEsb è certificato dai tool TCK. Petals è sponsorizzato dal consorzio OW2 che vede tra i suoi membri strategici RedHat, Thales ma anche IONA e Linagora. Per il bpel c’è poi Orchestra che offre integrazione con Petals, guardacaso Orchestra è sponsorizzato dal consorzio OW2 e la sua guida è scritta da quelli di Bull che ne fanno parte.

Vi siete persi ? Spero di no, non vi posso suggerire qual è meglio quale no, vi faccio solo notare che ci sono degli standard e ci sono grosse aziende che forniscono un pò tutti questi prodotti.

A mio avviso siccome la struttura delle vostre applicazioni probabilmente spazierà tra application server, esb e web service framework soffermatevi sui software che fanno parte della stessa azienda perchè avrete sicuramente necessità di integrarli (e magari meno sono gli strumenti che usate e meglio è).

I riferimenti sono così tanti che non ho voglia di metterli vi consiglio di partire dalla pagina di wikipedia di JBI e quella di BPEL.

Web Services con Eclipse 3.4, Tomcat 6.0.16 e Axis2 1.4

Per un progetto in azienda sto lavorando con i web services, usiamo pero’ vecchie versioni di eclipse e axis2 poichè il progetto è iniziato con quelle versioni e non si può cambiare strumento durante lo sviluppo, come è giusto che sia. Per i fatti miei però ho sperimentato la generazione di web services dapprima con Netbeans 6.1 e poi con Eclipse 3.4.

Introduzione

Come da titolo dovete scaricare Eclipse, Tomcat e Axis2. Io ho scaricato Eclipse 3.4 per Java EE, Tomcat Core e Axis2 il file war ma anche la standard binary distributition perchè essa contiene dei comandi che il war file non ha.

Tomcat è un application server e dovrà lanciare Axis2 che funge da contenitore per i vostri web services e vi permette anche di gestirli. Con Eclipse dovrete creare le classi java per il client e il server.

Iniziamo

Una volta estratta la standard binary distribution, create la variabile di ambiente AXIS2_HOME in modo che punti ad essa e poi copiate il file war nella cartella /webapps di Tomcat. Ora, se volete, potete far partire tomcat lanciandolo dalla sua cartella /bin e con il vostro browser andare all’url:

http://localhost:8080

8080 è in genere la porta su cui Tomcat gira. Dovreste vedere la pagina di Tomcat, se cliccate a sinistra su Tomcat manager vedete la lista di applicazioni tra cui c’è Axis2. Cliccateci sopra e vi compare la pagina di Axis2. Come primo link c’è “Services” che indica gli attuali web services che stanno girando tra cui ci sarà anche il nostro.

Come vi ho già detto nella standard binary distribution ci sono dei comandi che nel war non sono presenti e sono java2wsdl e wsdl2java (vedere qui per tutti i parametri)

Se siete nuovi nel mondo dei web services dovete sapere che i file wsdl sono dei file xml che descrivono i web services percio’ prima di proseguire vi consiglio di studiarvi XML, i file xml schema e i file wsdl in generale (potete dare una occhiata al sito w3schools). Occorre saperlo perchè grazie al comando wsdl2java potete creare, a partire dal file wsdl, ciò che sta sotto la comunicazione tra client e webservice ovvero stub e skeleton.

Stub e skeleton sono delle classi java che fungono da proxy ovvero il vostro client chiamerà lo stub per la comunicazione mentre il webservice userà lo skeleton per ricevere, ed eventualmente trasmettere, i dati.

In un precedente articolo ho spiegato come potete validare i vostri file wsdl in modo da diminuire i rischi di interoperabilità, pensate ad esempio ad un client (stub) realizzato in java ed un web service (skeleton) realizzato sotto .NET.

Il comando java2wsdl potete immaginare cosa fa.

Questi comandi, come descritto nella reference di Axis2 sono molto semplici da usare ma una interfaccia grafica non dispiace.

Il servizio andrà poi impacchettato in un archivio axis (file aar) e deployato (in altre parole copiato e spacchettato, lasciatemi passare il termine) nella cartella di Axis2 sotto Tomcat.

Ho dapprima provato il plugin di Netbeans ma personalmente credo che andrebbe migliorato perchè è possibile selezionare poche cose e, inoltre, obbliga alla all’inserimento di parametri (-g) a linea di comando (da dentro l’interfaccia!) per la generazione del client, in quanto, in automatico, lui crea lo skeleton e l’unico modo per creare lo stub è aggiungere il parametro; per il resto il plugin si comporta bene. Il tutorial che ho seguito è questo. Tuttavia ho poi proseguito per Eclipse anche se poi ho scoperto che il plugin è buggato ma ho trovato rimedio.

I plugin di Axis2 sono a mio avviso più completi e si scaricano dal sito di Axis2 e precisamente sono il Service Archive Wizard 1.4 e il Code Generator Wizard 1.4 che come vedete nella tabella richiedono Axis 1.4.

Il primo serve per creare l’archivio axis da copiare in Tomcat il secondo come interfaccia per i comandi java2wsdl e wsdl2java.

Non dovete fare altro che scaricare i plugin ed estrarli nella cartella plugins di Eclipse e correggere qualche bug :-) .

In pratica nella cartella del Code Generator c’è un file che si chiama plugin.xml, in questo file sono descritte le librerie di cui il plugin si serve, tra queste notate che c’è l’archivio jar stax-api-1.0.1.jar ma questo non si trova nella cartella lib del plugin e dovete scaricarlo dalla rete (vedete qui). C’è poi un pacchetto che manca proprio e che è backport-util-concurrent-3.1.jar (lo trovate nella cartella /lib di Axis2) che dovete aggiungere nella cartella lib e nel file plugin.xml (in pratica tutto cio’ serve per risolvere l’eccezione java.lang.reflect.invocationTargetException che si manifesta all’ultimo passaggio del wizard).

Nel caso in futuro avete degli errori lanciate Eclipse in debug mode da console in questa maniera:

eclipse -clean -debug

L’opzione debug vi permette di vedere eventuali errori da console, clean pulisce una cache che Eclipse usa quando crea i vostri progetti (per altri parametri vedere qui). Se ancora avete problemi come ultima speranza rimuovete il plugin che vi da fastidio dalla cartella nascosta .metadata/.plugins che si trova nel vostro workspace.

Non fate partire ancora Eclipse perchè voglio segnalarvi un altro plugin che vi permette di lanciare/fermare Tomcat da Eclipse questo plugin lo trovate qui ed è semplice da installare come spiega il sito (in pratica va poi messo nella cartella dropins di Eclipse e occorre configurare il plugin indicando il path di tomcat).

Ok ora siete pronti per lanciare Eclipse, dovrete creare un progetto java e seguire questa guida suddivisa in 2 parti che vi spiega per filo e per segno tutto.

Durante la guida vi ritrovete a creare il codice java per lo stub dal file wsdl, il wizard vi chiede l’inclusione delle librerie del codegen ma questa non va e perciò dovrete farlo a mano agggiungendole direttamente nel vostro Build Path prendendole dalla cartella lib del plugin Codegen. Attenzione potrebbe essere un problema del Mac, ho notato che in debug mode, al momento della creazione del codice eclipse pensa di trovare il plugin nella cartella /eclipse/Contents/MacOS/plugins e non, come dovrebbe essere, in /eclipse/plugins, perciò se siete sotto Mac copiate i 2 plugin anche in quella cartella (da creare) e cosi al momento della generazione pesca correttemente i jar file della cartella lib.

Se non vedete il codige generato provate a fare un refresh del progetto. Volevo farvi notare che quando il wsdl viene caricato il plugin carica anche gli XML schema collegati (se ve ne sono) e quindi fa un controllo sulla validità, potete notare il caricamento se usate Eclipse in debug mode; tra l’altro una volta che avete creato il file wsdl potete validarlo selezionandolo e cliccando sulla voce di validazione dal menu contestuale aperto con il tasto destro del mouse.

Quando vi viene chiesto di compilare fatelo usando il file build.xml (tasto destro ed “esegui” dal menu contestuale) che viene automaticamente generato e conosce tutte le dipendenze.

Quando eseguirete il client avrete una eccezione riguardo il file jar woden API che è mancante questo perchè con Axis 2 1.4 questo package è richiesto; prendetelo dalla cartella lib di Axis2 e aggiungetelo al vostro build path. Ho semplicemente aggiunto solo il jar delle woden API.

Non vi preoccupate del warning su log4j è perchè non trova il suo file di configurazione.

Quando andate a generare lo skeleton che dovete riempire fate caso al fatto che i parametri in ingresso del metodo terminano con un numero.

Notate anche che quando generate lo stub questo ha come sottoclassi le richieste e le risposte mentre quando generate lo skeleton queste sono messe nei rispettivi file.

Nella parte 2 del tutorial vi verrà chiesto di usare il file services.xml che è stato generato nella cartella resources, ebbene in teoria dovreste poterlo selezionare in pratica dovrete inserire il suo path a mano.

Tra l’altro vi faccio notare che, sempre nella parte 2, il file wsdl viene generato nuovamente nella cartella resources, il file è pressocchè identico a quello di partenza anche se è questo che viene usato per la generazione del servizio con il Service Archiver.

Nella parte 2 vi viene chiesto di inserire la parte del client ebbene inserite il codice usato nella parte 1 e non quello proposto.

Se siete arrivati fino alla fine del tutorial complimenti! La strada per connettere e dare più funzionalità ai web services è lunga ma ora avete la basi per poterne creare.

Aggiornamento 1

Se avete avuto occasione di creare da zero wsdl, avete visto la comoda possibilità di includere XML schema dentro in modo da separare la descrizione del servizio dai tipi usati nei messaggi.

In questo ambito ho scoperto che il plugin Service Archiver ha un bug, semplicemente non include l’XML schema usato dal file WSDL dentro l’archivio aar creato e dovete purtroppo farlo a mano, a meno che c’è qualcuno che vuole modificare il codice (dovrebbe essere semplice ma non ho voglia, considerate che c’è la libreria WSDL4J che puo’ aiutarvi). Per modificarlo spacchettare il file aar (una volta rinominato in zip), aggiungete il file e rimpacchettate.

Aggiornamento 2 (uso di Xmlbeans su Eclipse 3.2, Tomcat 6 e Axis2 1.3, da verificare con Axis2 1.4)

Se durante la creazione del web service avete usato Xmlbeans come data binding ovete prestare attenzione a 2 cose in caso di errore:

-) La cartella resources contiene una cartella generata da Xmlbeans che si chiama schemaorg_apache_xmlbeans. Questa cartella contiene la cartella system la quale a sua volta contiene delle cartelle indicate da una combinazione di numeri. In una di queste si deve trovare il file TypeSystemHolder.class, questo file potrebbe esservi richiesto quando lanciate il client. Dovete quindi aggiungere la cartella resources come Class Folder tra le librerie del progetto e non come src folder.

-) In fase di creazione del web service con il Service Archiver Wizard potreste aver bisogno di aggiungere tra le librerie esterne quelle di di Xmlbeans ovvero il file Xbeans-packaged.jar che si trova nella cartella build/lib.

Alla prossima

P.S. Ho usato la java virtual machine 1.5.0_13

Web Services e interoperabilità

Lavorando con i web services sorge il problema dell’interoperabilità, magari qualcuno si chiede “ma come è possibile? I web services garantiscono l’interoperabilità grazie al fatto che espongono servizi sulla rete e poi ho li ho anche validati…”. Ebbene si questo è in parte vero in parte perchè spesse volte si riferiscono a xml schema e quindi strumenti (come Eclipse) ne garantiscono la validità se questi schema vengono rispettati.

Ma ciò non basta. Non basta perchè il modo in cui sono scritti influenza il modo in cui le classi java o C# sono generate e ne sto qui a parlare proprio perchè in azienda abbiamo avuto questo problema. Un’altra azienda ha scritto dei file wsdl da cui ha generato classi java (tramite lo strumento di Axis2 wsdl2java) e su cui poi ha lavorato per un progetto. Questo progetto dovrà poi essere realizzato in C# con piattaforma .NET.

Fatto sta che gli strumenti che generano le classi C# non riescono perchè non trovano valido il file wsdl utilizzato!!! Vi domanderete “come faccio a sapere quali sono gli accorgimenti che devo prendere?”

Attualmente la bibbia di riferimento è il Basic Profile, una sorta di studio che ha portato a definire delle regole per ridurre i rischi derivanti dall’interoperabilità. Il BP è stato realizzato dal Web Service Organisation WS-I una specie di consorzio guidato da SAP, Fujitsu, Microsoft, HP, Sun, IBM, Intel, Oracle ecc

In questo BP si fa cenno a diverse tecnologie per usate per i web services SOAP, WSDL UDDI, XML schema, HTTP e HTTPS vi invito quindi a dare uno sguardo.

Al di là della sola lettura occorrono strumenti di verifica e che ho trovato grazie a questo articolo. In pratica il WS-I ha rilasciato uno strumento chiamato Interoperability Testing Tools (su un accenno a come si usa vedere qui) che è stato poi integrato in altri strumenti come soapUI un software in parte rilasciato open source con licenza GNU Library o Lesser General Public License (LGPL) in parte, la versione Pro, in via commerciale. soapUI è stato realizzato come applicazione stand-alone ma anche come plugin per Eclipse, Netbeans, IntelliJ e Maven.

Esistono altri strumenti che troverete nell’articolo che vi ho indicato e che da oggi ho cominciato a valutare.

Benvenuti nel meraviglioso mondo dell’interoperabilità :-)