Transcript

JAX-WSJAX-WS

Java API for Java API for XML Web ServicesXML Web Services

Massimo Martinelli

Consiglio Nazionale delle Ricerche - CNRIstituto di Scienza e Tecnologie della Informazione - ISTI

[email protected]

29/05/2010, Area Ricerca CNR, Pisa

Il corso di Java Web Services in 1 Minuto!

import ...

public class MioWebService {

public String ciao(String nome) {

return “Ciao “+ nome; }

}

@WebService

@WebMethod

Scriviamo una classe Java con un metodo

Aggiungiamo metainformazioni

Finito! ...

JAX-WSJAX-WS

Java API for Java API for XML Web ServicesXML Web Services

Massimo Martinelli

Consiglio Nazionale delle Ricerche - CNRIstituto di Scienza e Tecnologie della Informazione - ISTI

[email protected]

RIPARTIAMO :-)RIPARTIAMO :-)

Sommario Cosa è JAX-WS?

Implementazione di Web Service e di Client

Tipi di dato supportati da JAX-WS

JAXB

Esercizi da svolgere durante il corso

Secondo il W3C ...Un Web Service è un sistema software designato a supportare interazioni interoperabili macchina-macchina su una rete.

Ha una interfaccia descritta in un formato elaborabile da una macchina (specificamente WSDL).Altri sistemi interagiscono con il Web Service in un modo prescritto dalla sua descrizione usando messaggi SOAP, tipicamente convogliati usando HTTP con una serializzazione XML insieme ad altri standard Web.

Cosa è JAX-WS acronimo di

“Java API for XML Web Services” Tecnologia per realizzare Web Service e

client in Java che comunicano utilizzando messaggi SOAP-XML

L’implementazione di riferimento (JAX-WS for Reference Implementation) è un progetto open source e fa parte del progetto GlassFish, un application server Java EE.

Fa parte della distribuzione “Metro”

Web Services semplificati

Da Java 5 (Java 1.5) introdotte le annotazioni

ovvero dei Metadati sul codice Java

Esempio di annotazione:

@Annotazione

Annotazioni:

– Possono essere trattate a livello di compilazione

– Possono essere trattate anche tempo di esecuzione

Annotazioni nei Web Service

Per sviluppare un Web Service con JAX-WS è necessario utilizzare l'annotazione javax.jws.WebService

Ovvero: la classe che implementa il Web Service deve essere annotata con la annotazione javax.jws.WebService (o con javax.jws.WebServiceProvider)

Service Endpoint Interface (SEI) Una interfaccia service endpoint (SEI) è una interfaccia Java

che dichiara i metodi che un client può invocare sul servizio

SEI non necessaria quando si implementa un endpoint JAX-WS: la classe di implementazione del Web Service (SIB Service Implementation Bean) definisce implicitamente una SEI

può riferire esplicitamente una SEI tramite l’elemento endpointInterface dell’annotazione @Webservice

Preparazione agli esercizi

Creare una directory LINUX ~home/java-pgm/

C:/java-pgm/

dove installeremo i programmi che seguono...

Strumenti che utilizzeremo: Java SE 6

Java Standard Development Kit versione 6

(Se non è già installata eseguire da terminale il comando java –version )

Scaricare da http://java.sun.com/javase/downloads/index.jsp

Netbeans è un ambiente di sviluppo realizzato da SUN

◦ Scaricare da http://netbeans.org/downloads/index.html

(versione “Java” o “All”)

Strumenti che utilizzeremo: Netbeans

Strumenti che utilizzeremo: Glassfish

Application server open source realizzato da Sun di riferimento per Java EE 5/6.

Incluso con NetBeans

Supporta: EJB 3.1 JPA 2 JAXB 2.x JAX-WS 2.x

Per utilizzare con Tomcat

scaricare ant da http://ant.apache.org/ scaricare metro da http://metro.dev.java.net/

java -jar metro*.jar

ant -Dtomcat.home=<DirectorydiTomcat> -f metro-on-tomcat.xml install

V

A partire da:

una classe Javaun documento WSDL

Implementazione di un Web Service

Implementazione di un Web Service (classe Java): Passi Base

1. Codificare la classe che implementa il servizio

2. Compilare tale classe

3. Dispiegare (deploy) il file WAR

4. Codificare la classe per il client

5. Utilizzare wsimport per generare e compilare gli artefatti

6. Compilare la classe client

7. Eseguire il client

Codifica della classe SIB (1/2)

package serviziociao;

import javax.jws.WebService;

@WebServicepublic class Ciao {

private String messaggio = new String("Ciao, ");

public void Ciao() {}

@WebMethodpublic String saluto(String nome) {

return messaggio + nome + ".";}

}

Codifica della classe SIB (2/2)

• La classe implementata, Ciao, è annotata come web service utilizzando l'annotazione @WebService

• Ciao dichiara un singolo metodo chiamato saluto, annotato con l'annotazione @WebMethod

• La classe implementata deve anche definire un costruttore di default public senza argomenti

JAX-WS Endpoint I metodi della classe che implementa il Web Service devono essere public, e non devono essere dichiarati ne static ne final

I metodi di Business esposti ai client dei Web service devono:

essere annotati con javax.jws.WebMethod

avere tipi di parametri compatibili con JAX-B

Le classi che implementano i Web Service

Non devono essere dichiarate abstract

Devono avere un costruttore di default public

Non devono definire il metodo finalize

Possono usare le annotazioni javax.annotation.PostConstruct o javax.annotation.PreDestroy sui propri metodi per gestire il loro ciclo di vita

Il medoto @PostConstruct è chiamato dal container prima che la classe di implementazione inizi a rispondere ai client del Web Service

Il metodo @PreDestroy è chiamato dal container prima che l'endpoint sia rimosso dall'operazione

Esercizio (Guidato)

• Realizzare un Web Service che fa la somma di due numeri interi

• Da Netbeans creare un nuovo progetto Web

• Creare un nuovo Web service

• Dispiegare, eseguire e provare (Test)

Non vi avevo detto che bisognava importare anche ...

package serviziociao.endpoint;

import javax.jws.WebService;import javax.jws.WebMethod;

@WebService()public class Ciao {

private String messaggio = new String("Ciao, ");

public void Ciao() {}

@WebMethod()public String saluto(String nome) {

return messaggio + nome + ".";}

}

@WebServiceAttributi● name: nome del wsdl:portType (per difetto il nome della classe Java senza package)

● portName: nome del wsdl:portName (per difetto è il nome del WebService concatenato a Port)

● serviceName: nome del servizio (wsdl:service) (per difetto il nome della classe concatenato alla Stringa “Service”)

● endpointInterface: (es. endpointInterface = "package.MioWebServiceInterface") specifica il nome completo della SEI (per difetto la classe java,comprensiva del package, concatenata alla Stringa “ServicePortType”)

● targetNamespace: namespace di riferimento per il WSDL e gli XML generati (per difetto è il nome del package java)

● wsdlLocation: l'indirizzo documento WSDL del Web Service. L'indirizzo può essere relativo o assoluto.

[email protected] (serviceName = "NomeServizio", endpointInterface = "it.cnr.NomeServizioServicePortType", targetNamespace="http://..../", portName="NomeServizioServicePort")

V

@WebMethodPer difetto tutti i metodi public di una classe annotata con @WebService vengono esposti nel Web ServicePer personalizzare un metodo esposto come operazione WS si utilizza @WebMethodAttributi

− action definisce l'azione per l'operazione. (per difetto = al nome del metodo )− exclude specifica se il metodo va escluso dalla pubblicazione del Web Service.

(per difetto=”false”) (Booleano)− operationName specifica il nome di wsdl:operation per il metodo (per difetto =

nome del metodo)

@WebMethod(action="somma")public int somma(@WebParam(name = "i") int i,

@WebParam(name = "j") int j) { int k = i + j; return k;

}

V

@WebParam e @WebResult

personalizzazione dei parametri di input(@WebParam) e di output(@WebResult) di un metodo del Web Service

Attributi● header: Specifica se il parametro si trova in un'intestazione di messaggio anziché nel corpo. Per difetto è false. (Booleano)

● mode: WebParam.mode.IN parametro, WebParam.mode.OUT, WebParam.mode.INOUT che rappresentano parametri in input, in output e parametri ripetuti sia in input che in output

● name: nome del parametro.

● targetNamespace:spazio dei nomi XML dell'elemento XML per il parametro

V

@SOAPBinding

In caso i metodi del Web Service utilizzino tipi semplici come String o int è possibile utilizzare

la seguente annotazione@SOAPBinding(style=Style.RPC)

In caso di utilizzo di tipi complessi lo stile da utilizzare corrisponde a quello di default:

@SOAPBinding(style=Style.DOCUMENT)

Nel secondo caso vedremo più avanti come utilizzare il mapping (da oggetti Java in XML e

viceversa) con JAXB

@SOAPBinding specifica come avviene il mapping a livello SOAP

Attributi– style

stile di codifica per messaggi inviati e ricevuti. Valori: DOCUMENT (default), RPC.

– useformattazione per messaggi inviati e ricevuti. Valori LITERAL(default). ENCODED (non WS-I standard)

– parameterStylevalori Wrapped (default) o BARE (utilizzabile solo in stile DOCUMENT)

Esempio:@WebService(targetNamespace = "http://.....", name = "MioServizio")

@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL)

@SOAPBindingIndipendenza dal Protocollo e dal Trasporto

Personalizzazione tramite Annotazioni

@WebService(name=”SistemaInformativoService”, targetNamespace=”http://esempio.it”)

public class SistemaInformativo {

...

@WebMethod(operationName=”getPersona”)

public Persona getPersona(@WebParam(name=”codicefiscale”) String codicefiscale) {

// ... codice di implementazione ...

}

}

Implementazione del Servizio(da classe Java)

Al momento dell'esecuzione Netbeans genera automaticamente gli artefatti, compila tutte le classi, dispiega il servizio e attiva l’application server

Dietro le quinte il Web Service (endpoint) viene generato dal tool wsgen

wsgen cp ./build -keep -s ./src -d ./build package.Class

Artefatti

Il tool “wsimport” a partire dal WSDL crea le classi di supporto (artefatti):• Service Endpoint Interface (SEI)• Service• Exception class a partire da wsdl:fault• Oggetti generati a partire dagli schemi XML (JAXB...)

Per invocare una operazione WS è necessario istanziare la classe service ed ottenere il proxy mediante chiamata al metodo:

get<ServiceName>PortCalculatorService svc = new CalculatorService();Calculatorproxy = svc.getCalculatorPort( ) ;int answer = proxy.somma(35, 7);

wsimport

Parametri: wsdl: percorso del file wsdl (es: /home/massimo/servizio.wsdl, http://www..../servizio.wsdl, ...) destdir: destinazione dei compilati generati sourcedestdir: destinazione dei sorgenti generati keep: se indicata mantiene i sorgenti generati verbose: dettaglio verboso delle operazioni svolte binding: specifica il tipo di collegamento package: nome del package per le classi generate

Prova del Servizio ...senza un Client

• Aprire Admin Console collegandosi col browser all'indirizzo http://localhost:4848/

• Fornire utente e password per effetturare il login

• Cliccare su “Web Services” nel panello a sinistra

• Cliccare Hello

• Cliccare Test(http://localhost:8080/EsempioWSCiao/CiaoService?Tester)

Prova del metodo “sayHello”

•in “Methods”, scrivere un nome come parametro per il metodo “sayHello”•Cliccare il pulsante “sayHello”

Analisi dei Messaggi SOAP

Client a partire da un WSDL

Implementazione di un servizioa partire da un WSDL

Netbeans genera un Web Service (bozza) a partire da un WSDL

Dietro le quinte esegue per noi il comando wsimport

wsimport -keep –s <directory_sorgenti> -d <classi_generate_compilate> <percorso_documento_WSDL>

-keep non cancella i file sorgenti generati

Il comando genera eventuali artefatti JAXB per gestire tipi non di base

Codifica del Client1. Utilizzare l’annotazione

javax.xml.ws.WebServiceRef per riferire un Web Service

• L’attributo wsdlLocation specifica l’ URI del documento WSDL@WebServiceRef{wsdlLocation=“http://localhost:8080/EsempioWSCiao/CiaoService?wsdl}

2. Invocare il metodo del Web Service utilizzando il proxy (port) del service

Hello port = service.getCiaoPort();

3. Invocare il metodo (saluto ) del proxy (port)

ClientCiao package simpleclient;

import javax.xml.ws.WebServiceRef;import helloservice.endpoint.HelloService;import serviziociao.endpoint.Ciao;

public class ClientCiao {@WebServiceRef(wsdlLocation="http://localhost:8080/EsempioWSCiao/CiaoService?wsdl") static CiaoService service = new CiaoService();public static void main(String[] args) {

try {ClientCiao client = new ClientCiao();client.doTest(args);

} catch(Exception e) {e.printStackTrace();

}}public void doTest(String[] args) {

try {System.out.println(“Recupero il proxy (port) dal servizio: " + service);Ciao port = service.getCiaoPort();System.out.println("Invoco l’operazione saluto sul proxy (port)");String name;if (args.length > 0) {

nome= args[0];} else {

nome = “Nessun nome";}String response = port.saluto(nome);System.out.println(response);

} catch(Exception e) {e.printStackTrace();

}}

Esercizio

• Preparare un client che chiami il metodo “registraNome” del Web Service “WSnominativo” descritto dal WSDL che trovate all’indirizzo

• http://.......:8080/EsercizioWSserver/WSnominativoService?wsdl

• il metodo richiede in input un parametro di tipo String

• Test: http://....:8080/EsercizioWSserver/WSnominativoService?Tester

• Controllo accessi: http://.....:8080/EsercizioWSserver/

Tipi Supportati da JAX-WS• Per essere indipendenti dal linguaggio i tipi supportati sono

limitati a quelli descritti nelle specifiche:

• tipi atomici (es. int, boolean, ecc.)

• String

• array e List

• semplici JavaBean usati come strutture (con costruttore public)

JAX-WS delega a JAXB il collegamento tra tipi Java e XML (e viceversa).

Sviluppatori non devono preoccuparsi del collegamento (in generale)

JAXB

Java API XML BindingLibrerie che consentono di collegare (binding) oggetti Java a documenti XMLA partire da un documento XML schema si può creare una classe Java corrispondente le cui istanze possono leggere/scrivere documenti XMLe viceversa

Marshalling / Serializzazione

Il procedimento detto marshalling si riferisce alla possibilità di serializzare (..trasformare..) oggetti Java in documenti XML.

A partire da un oggetto Java, schemagen crea un documento XML corrispondente

schemagen [-opzioni ...] [sorgenti_java]

Le istanze di queste classi possono essere collegate ai relativi documenti XML

Unmarshalling / Deserializzazione

Il procedimento detto unmarshalling si riferisce alla possibilità di deserializzare (..trasformare..) documenti XML (schema) in oggetti Java.

A partire da un documento XML Schema xjc crea un oggetto Java corrispondente

xjc [-opzioni ...] <schema>xjc biblioteca.xsd

Le istanze di questa classe possono essere collegate a documenti XML

Esempio @XMLRootElementpublic class Persona () { private String nominativo; private String identificatore;

public Persona() { }

public void getNominativo(){return nominativo;

}

public void setNominativo(String nominativo){this.nominativo=nominativo;

}

public int getIdentificativo() { return identificativo; } @XmlAttribute // identificatore attributo dell'elemento radice public void setId(int identificatore) { this.identificatore = identificatore; }}

JAXB Serializzare e Deserializzare// Serializzare un oggetto in XMLPersona persona= new Persona();persona.setNominativo("Salvo Montalbano");persona.setIdentificatore(“slvmnt);

// creiamo il contesto JAXB e un marshaller (serializzatore)JAXBContext contesto = JAXBContext.newInstance(Persona.class);Marshaller serializzatore = contesto.createMarshaller();// Impostiamo un formato “pretty” serializzatore.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);// serializzaimoserializzatore.marshal(persona, new File("/output.xml"));

// Deserializzare (Ottenere l'oggetto dall'XML// creiamo il contesto JAXB e un unmarshaller (deserializzatore)JAXBContext contesto = JAXBContext.newInstance(Persona.class);Unmarshaller deserializzatore = contesto.createUnmarshaller();// otteniamo l'oggettoMessage msg = (Persona)deserializzatore.unmarshal(new File("/persona.xml"));

Personalizzazione

@XMLTypepublic class Persona () { private String nominativo; private String identificatore;

....}

@XMLRootElementpublic Dipendente() { }

Persona persona; }

}

Esempio public class Persona () { private String nominativo; private String identificatore;

@XMLRootElement public Persona() { }

public void getNominativo(){return nominativo;

}

public void setNominativo(String nominativo){this.nominativo=nominativo;

}

public int getIdentificativo() { return identificativo; } @XmlAttribute // identificatore attributo dell'elemento radice public void setId(int identificatore) { this.identificatore = identificatore; }}

Gestire gli allegati (attachment): Server

@MTOM(threshold = 4096)@WebServicepublic class WSUpload {

public void fileUpload(String nomeFile, @XmlMimeType("application/octet-stream") DataHandler data) { try { DataHandler dh = data; File file = new File(nomeFile); FileOutputStream outputStream = new FileOutputStream(file); dh.writeTo(outputStream);

} catch (Exception e) { throw new WebServiceException(e); } }

}

Gestire gli allegati (attachment): Client

WSUploadService service = new WSUploadService(); // classe generataMTOMFeature feature = new MTOMFeature();WSUpload port = service.getWSUploadPort(feature); //classe generata

URL url = new URL("file:///home/massimo/prova.png");DataHandler dh = new DataHandler(url);String nomefile = "prova.png";port.fileUpload(nomefile, dh);

Esercizio

• Preparare un client che chiami il metodo YYYYY del Web Service XXXX descritto dal WSDL che trovate all’indirizzo

• http://......:8080/EsempioWSUpload/WSUploadService?wsdl

• il metodo richiede in input un parametro di tipo String e un parametro file corrispondente ad una immagine jpg o gif o png che avete sul vostro disco

Novità introdotta con in Java SE 6//pubblicazione di un POJO (Plain Ordinary Java Object) @WebService public class Calcolatore { @Resource WebServiceContext context; // ottiene dal server il contesto dei WS public int somma(int a, int b) { return a+b; } }

// crea e pubblica un endpointCalcolator calculatore = new Calcolatore();Endpoint endpoint=Endpoint.publish(“http://localhost/calcolatore”,Calcolatore);

// WSDL creato e pubblicato al volo: http://localhost/calcolatore?WSDL

// assegnazione di protocollo (per difetto è HTTP)// Endpoint endpoint=Endpoint.create(SOAPBinding.SOAP12HTTP_BINDING,calcolatore);//endpoint.publish(“http://localhost/calcolatore”);

Client Asincroni (nonblocking)

class AmazonAsyncClient { public static void main(String[ ] args) { // Usage if (args.length != 1) { System.err.println("Usage: java AmazonAsyncClient <access key>"); return; } final String access_key = args[0]; // Create service and get portType reference. AWSECommerceService service = new AWSECommerceService(); AWSECommerceServicePortType port = service.getAWSECommerceServicePort(); // Create request. ItemSearchRequest request = new ItemSearchRequest(); // Add details to request. request.setSearchIndex("Books"); request.setKeywords("quantum gravity"); ItemSearch item_search= new ItemSearch(); item_search.setAWSAccessKeyId(access_key); item_search.getRequest().add(request); port.itemSearchAsync(item_search, new MyHandler()); // In this case, just sleep to give the search process time. // In a production application, other useful tasks could be // performed and the application could run indefinitely. try { Thread.sleep(400); } catch(InterruptedException e) { System.err.println(e); } }

// The handler class implements handleResponse, which executes // if and when there's a response. static class MyHandler implements AsyncHandler<ItemSearchResponse> { public void handleResponse(Response<ItemSearchResponse> future) { try { ItemSearchResponse response = future.get(); List<Items> item_list = response.getItems(); for (Items next : item_list) for (Item item : next.getItem()) System.out.println(item.getItemAttributes().getTitle()); } catch(InterruptedException e) { System.err.println(e); } catch(ExecutionException e) { System.err.println(e); } } }}

• Metro User Guide https://metro.dev.java.net/guide/index.html• Java Web Services Developer Pack 2.0•http://java.sun.com/webservices/downloads/webservicespack.html•Java EE 5 Developing using Glassfish Application Server. David R. Heffelfinger - Packt Publishing•Create stand-alone Web services applications with Eclipse and Java SE 6. Fiona Lam, John Robertson, IBM developerWorks•Documentazione di WebSphere Application Server http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=/com.ibm.websphere.wsfep.multiplatform.doc/info/ae/ae/rwbs_jaxwsannotations.html•RESTful Web services: The basics. Alex Rodriguez - IBM developerWorks•Web Services con Java5. MokaByte 127, 128 - Marzo Aprile 2008 (http://www.mokabyte.it/)•Java & XML. Brett McLaughlin – O'Reilly•Java Web Services Up adn Running – O'Reilly•Corso Comune Livorno “Web Services”. M.Martinelli•Corso Comune Livorno “AXIS 2.1”. M.Martinelli•Corso Comune Livorno “Java e XML”. M.Martinelli

Bibliografia

Grazie !