0% ont trouvé ce document utile (0 vote)
266 vues80 pages

Développement de services web JAX-WS

Ce document décrit JAX-WS, une spécification Java pour développer des services web SOAP. Il présente les concepts généraux de JAX-WS, les différentes approches de développement côté serveur et client, et les annotations utilisées.

Transféré par

Aida
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
266 vues80 pages

Développement de services web JAX-WS

Ce document décrit JAX-WS, une spécification Java pour développer des services web SOAP. Il présente les concepts généraux de JAX-WS, les différentes approches de développement côté serveur et client, et les annotations utilisées.

Transféré par

Aida
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

SOA – Services web étendus

Développer services web étendus


avec Java : JAX-WS
Mickaël BARON – 2010 (Rev. Janvier 2019)
mailto:[email protected] ou mailto:[email protected]
@mickaelbaron
Licence

Creative Commons
Contrat Paternité
Partage des Conditions Initiales à l'Identique
2.0 France
@mickaelbaron
keulkeul.blogspot.com

http://creativecommons.org/licenses/by-sa/2.0/fr

JAX-WS - M. Baron - Page 2


À propos de l’auteur …

† Mickaël BARON

† Ingénieur de Recherche au LIAS


@mickaelbaron
† https://www.lias-lab.fr

† Equipe : Ingénierie des Données et des Modèles

† Responsable des plateformes logicielles, « coach » technique

† Responsable Rubriques Java de Developpez.com


@mickaelbaron

† Communauté Francophone dédiée au développement informatique

† https://java.developpez.com
keulkeul.blogspot.com

† 4 millions de visiteurs uniques et 12 millions de pages vues par mois

† 750 00 membres, 2 000 forums et jusqu'à 5 000 messages par jour


JAX-WS - M. Baron - Page 3
Plan du cours

† Généralités JAX-WS

† Développement serveur
† Bottom -> Up

† Top -> Down

† Développement client
@mickaelbaron

† Annotations
keulkeul.blogspot.com

† Handler

† Déploiement
JAX-WS - M. Baron - Page 4
Déroulement du cours

† Pédagogie du cours
† Illustration avec de nombreux exemples qui sont disponibles à
l’adresse http://mbaron.developpez.com/soa/jaxws/
† Des bulles d’aide tout au long du cours
† Survol des principaux concepts en évitant une présentation
exhaustive

† Logiciels utilisés
@mickaelbaron

† Navigateur Web, Java et Maven

† Pré-requis
keulkeul.blogspot.com

† Schema XML, WSDL, SOAP, JAXB

† Exemples
† https://github.com/mickaelbaron/jaxws-examples
JAX-WS - M. Baron - Page 5
Ressources

† Billets issus de Blog


† blogs.sun.com/alexismp/entry/metro_boulot_dodo
† www.dotmyself.net/documentation/5.html
† jee-bpel-soa.blogspot.com/search/label/jax-ws
† Articles
† wiki.apache.org/ws/StackComparison
† www.ibm.com/developerworks/webservices/library/ws-jsrart
@mickaelbaron

† java.sun.com/developer/technicalArticles/J2SE/jax_ws_2/
† www.jroller.com/gmazza/entry/adding_jax_ws_handlers_to
† blog.vinodsingh.com/2008/09/using-jax-ws-handlers_25.html
keulkeul.blogspot.com

† Cours
† java.sun.com/webservices/docs/1.6/tutorial/doc/index.html
† www.javapassion.com/webservices/jaxwsbasics.pdf
JAX-WS - M. Baron - Page 6
Ressources : bibliothèque

† Java SOA Cookbook


† Auteur : Eben Hewitt
† Éditeur : Oreilly
† Edition : Mars 2009 - 752 pages - ISBN : 0596520727

† Java Web Services : Up and Running


† Auteur : Martin Kalin
† Éditeur : Oreilly
@mickaelbaron

† Edition : Février 2009 - 316 pages - ISBN : 059652112X

† Les Cahiers du Programmeur : Java EE 5


keulkeul.blogspot.com

† Auteur : Antonio Goncalves


† Éditeur : Eyrolles
† Edition : Août 2008 - 351 pages - ISBN : 2212123639
JAX-WS - M. Baron - Page 7
@mickaelbaron
keulkeul.blogspot.com Version Java supportée par ce support de cours

q Pas de gestion des modules dans les exemples (utilisation du classpath)


q Utilisation des outils wsimport et wsgen depuis le JDK
JAX-WS - M. Baron - Page 8
Généralités : développement de services web SOAP

† Ce cours s’intéresse au développement des services web de


type SOAP ou étendus
† Côté Serveur : code pour le traitement du service web
† Côté Client : code qui permet d’appeler un service web
† La majorité des langages de programmation orientés web
supportent le développement de services web
† Java, PHP, C#, C++, …
@mickaelbaron

† Ce cours se limite au langage Java


† Différents frameworks de développement de services web
† JAX-WS Specification (javaee.github.io/metro-jax-ws)
keulkeul.blogspot.com

† AXIS 1 et 2 Apache (ws.apache.org/axis et ws.apache.org/axis2)


† CXF Apache (cxf.apache.org)
† JBossWS (jbossws.github.io/) JAX-WS - M. Baron - Page 9
Généralités JAX-WS

† JAX-WS est l’acronyme Java API for XML Web Services


† JAX-WS est à la fois un standard et une implémentation

† La version courante est JAX-WS 2.3.1, précédemment


JAX-WS s’appelait JAX-RPC

† Code source API : github.com/eclipse-ee4j/jax-ws-api

† JAX-WS s’appuie sur un ensemble de JSR


@mickaelbaron

† JSR 224 : JAX-WS

† JSR 109 : Web Services


keulkeul.blogspot.com

† JSR 181 : Web Services Metadata

† JSR 222 : JAXB

† JSR 250 : Common Annotations JAX-WS - M. Baron - Page 10


Généralités JAX-WS : implémentation

† L’implémentation de référence est fournie par METRO


appelée également JAX-WS RI (Reference Implementation)
† Site projet Metro : javaee.github.io/metro-jax-ws
† Code source : github.com/eclipse-ee4j/metro-jax-ws
† Version actuelle : 2.3.1

† WSIT (Web Services Interoperability Technologies) est un


complément pour gérer les services web avancés (WS-*)
@mickaelbaron

† Site projet WSIT : javaee.github.io/metro

† L’implémentation JAX-WS est intégrée nativement à la JRE


keulkeul.blogspot.com

depuis la version 6 jusqu’à la version 10


† Possibilité de développer des services web sans serveur
d’application (étudié à la fin)
JAX-WS - M. Baron - Page 11
Généralités JAX-WS : dépendances Maven

† À partir de Java 11, il faudra ajouter explicitement les


dépendances

<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>2.3.1</version>
</dependency>

† Pour les versions antérieures à 2.3.1, il faudra ajouter une


@mickaelbaron

dépendance manquante

<dependency>
keulkeul.blogspot.com

<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

JAX-WS - M. Baron - Page 12


Généralités JAX-WS : fonctionnement

Développement de
clients dans des Description

Approche Top / Down


langages différents du service
web
Document WSDL

WSDL
JAVA

Servlet JAX-WS
PHP SOAP
@mickaelbaron

Approche Bottom / Up
.NET Serveur
Web Conteneur Java
Classes JAVA annotées
implémentant le
keulkeul.blogspot.com

service web

Utilisation du service
web par envoi /
réception de messages
Couche Cliente Couche Serveur
SOAP
JAX-WS - M. Baron - Page 13
Généralités JAX-WS : fonctionnement

† Le développement de services web avec JAX-WS est basé


sur des POJO (Plain Old Java Object)

† Les fonctionnalités de base pour le développement de


services web avec JAX-WS requiert simplement l’utilisation
d’annotations Java

† Par conséquent aucun fichier de déploiement n’est requis


@mickaelbaron

† Toutefois, les fonctionnalités avancées (appels asynchrones)


nécessitent d’utiliser une API
keulkeul.blogspot.com

† JAX-WS permet d’assurer l’indépendance du protocole


(SOAP) et du transport (HTTP) JAX-WS - M. Baron - Page 14
Plan du cours

† Généralités JAX-WS

† Développement serveur
† Bottom -> Up

† Top -> Down

† Développement client
@mickaelbaron

† Annotations
keulkeul.blogspot.com

† Handler

† Déploiement
JAX-WS - M. Baron - Page 15
Développement Serveur : généralités

† Deux façons pour développer un service web avec JAX-WS

† Approche Top / Down (à partir d’un document WSDL)


† Génération des différentes classes Java (JAXB et squelette du service
web) en utilisant l’outil wsimport

† Compléter le squelette de classe de l’implémentation

† Compiler, déployer et tester


@mickaelbaron

† Approche Bottom / Up (à partir d’un POJO)


† Créer et annoter un POJO
keulkeul.blogspot.com

† Compiler, déployer et tester

† Le document WSDL est automatiquement généré


JAX-WS - M. Baron - Page 16
Développement Serveur : Bottom / Up

WSDL 1
UnMarshall

Servlet JAXB
Marshall
SOAP

Serveur
Web
1
Classes Java décrivant
Request / Response
@mickaelbaron

Approche Bottom / Up
JAX-WS
Conteneur Java

Classes JAVA annotées


implémentant le
keulkeul.blogspot.com

service web

Légende

Générer implicitement Couche Serveur


1
par l’outil WSGEN
JAX-WS - M. Baron - Page 17
Développement Serveur : Bottom / Up

† L’approche Bottom / Up consiste à démarrer le développe-


ment à partir d’une classe Java (POJO)

† Ajouter l’annotation @WebService

† Déployer l’application

† Le document WSDL est généré automatiquement en


respectant les valeurs par défaut
@mickaelbaron

† URL du WSDL : http://monserveur/app/Service?WSDL

† Toutes les méthodes du POJO sont des opérations du


keulkeul.blogspot.com

service web

† La surcharge de méthodes n’est pas supportée


JAX-WS - M. Baron - Page 18
Développement Serveur : Bottom / Up

† Exemple : implémentation du service web HelloWorld


Le package doit être ajouté via
une dépendance

Deux opérations sont définies


package fr.mickaelbaron.helloworldquietwebservice;
dans la classe HelloWorldService
import javax.jws.WebService;

@WebService
public class HelloWorldService {
L’opération makeHelloWorld
public String makeHelloWorld(String value) { contenant un message input et
@mickaelbaron

return "Hello World to " + value;


} un message output
public String simpleHelloWorld() {
return "Hello World to everybody";
}
}
keulkeul.blogspot.com

L’opération simpleHelloWorld
contenant un message output
uniquement
HelloWorldService.java du projet
jaxws-helloworldquietwebservice
JAX-WS - M. Baron - Page 19
Développement Serveur : Bottom / Up

† Exemple (suite) : implémentation du service web HelloWorld


@mickaelbaron

Document WSDL du
service web développé
keulkeul.blogspot.com

JAX-WS - M. Baron - Page 20


Développement Serveur : Bottom / Up

† Exemple : paramétrer le service web HelloWorld


package fr.mickaelbaron.helloworldwebservice;

@WebService(name="HelloWorld",targetNamespace="http://helloworldwebservice.mickaelbaron.fr/")
@SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface HelloWorldService { Utilisation d’une interface pour
définir les paramètres du
@WebMethod(operationName="makeHelloWorld")
@WebResult(name="helloWorldResult")
service web
String makeHelloWorld(
@WebParam(name = "value")String value);

@WebMethod(operationName="simpleHelloWorld")
@WebResult(name="helloWorldResult")
HelloWorldService.java du projet
String simpleHelloWorld(); jaxws-helloworldwebservice
}
package fr.mickaelbaron.helloworldwebservice;
@mickaelbaron

@WebService(endpointInterface="fr.mickaelbaron.helloworldwebservice.HelloWorldService",
serviceName="HelloWorldService", portName="HelloWorldPort")
public class HelloWorldServiceImpl implements HelloWorldService {

public String makeHelloWorld(String value) {


return "Hello World to " + value;
}
keulkeul.blogspot.com

public String simpleHelloWorld() {

}
return "Hello World to everybody";
Classe qui fournit
} l’implémentation du service web
HelloWorldServiceImpl.java du projet
jaxws-helloworldwebservice JAX-WS - M. Baron - Page 21
Développement Serveur : Bottom / Up

† Exemple (bis) : paramétrer le service web HelloWorld


package fr.mickaelbaron.helloworldwebservice;

@WebService(name="HelloWorld",targetNamespace="http://helloworldwebservice.mickaelbaron.fr/")
@SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface HelloWorldService { Utilisation d’une interface pour
définir les paramètres du
@WebMethod(operationName="makeHelloWorld")
@WebResult(name="helloWorldResult")
service web
String makeHelloWorld(
@WebParam(name = "value")String value);

@WebMethod(operationName="simpleHelloWorld")
@WebResult(name="helloWorldResult")
HelloWorldService.java du projet
String simpleHelloWorld(); jaxws-helloworldwebservice
}
package fr.mickaelbaron.helloworldwebservice;
@mickaelbaron

@WebService(endpointInterface="fr.mickaelbaron.helloworldwebservice.HelloWorldService",
serviceName="HelloWorldService", portName="HelloWorldPort")
public class HelloWorldServiceImpl {
Pas nécessaire d’indiquer
public String makeHelloWorld(String value) {
return "Hello World to " + value; l’implémentation puisqu’elle
est précisée dans l’annotation
keulkeul.blogspot.com

public String simpleHelloWorld() { (vérification à l’exécution)


return "Hello World to everybody";
}
} Classe qui fournit
HelloWorldServiceImpl.java du projet l’implémentation du service web
jaxws-helloworldwebservice JAX-WS - M. Baron - Page 22
Développement Serveur : Bottom / Up

† Comme indiqué précédemment, du JDK 6 à 10 des API et des


outils sont fournis pour manipuler des services web
† L’outil wsgen génère des artifacts (JAXB, WSDL) à partir de
classes Java annotées via JAX-WS
† L’utilisation de cet outil n’est pas obligatoire puisque cette
génération est implicite lors de l’exécution
† Exemples d’utilisation
@mickaelbaron

wsgen -cp . fr.mickaelbaron.helloworldwebservice.HelloWorldServiceImpl –keep

Génère les classes Java annotées JAXB


(marshall et unmarshall)
keulkeul.blogspot.com

wsgen -cp . fr.mickaelbaron.helloworldwebservice.HelloWorldServiceImpl –keep -wsdl

Génère également le document WSDL


JAX-WS - M. Baron - Page 23
Développement Serveur : Bottom / Up

† Exemple : wsgen avec Maven


<project ...>
... Plug-in à utiliser pour la
<build> génération des artifacts
<plugins>
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
<executions>
<execution> Demande génération des
<goals>
<goal>wsgen</goal>
ressources par rapport à la
</goals> classeHelloWorldService
</execution>
</executions>
@mickaelbaron

<configuration>
<sei>fr.mickaelbaron.helloworldwebservice.HelloWorldServiceImpl</sei>
<genWsdl>true</genWsdl>
<keep>true</keep>
<executable>${java.home}/bin/wsgen</executable>
</configuration>
</plugin>
keulkeul.blogspot.com

</plugins>
</build> Nécessaire pour fonctionner avec la
</project>
version 9 et 10 de Java (Sous OS Win
remplacer par wsgen.exe)

pom.xml du projet
jaxws-helloworldwebservice JAX-WS - M. Baron - Page 24
Développement Serveur : Top / Down

Document WSDL
décrivant le service web

Approche Top / Down


à implémenter

2
Classes Java décrivant
Request / Response

~ Proxy du
WSDL 1 service web
UnMarshall
@mickaelbaron

2
Interface Java
Servlet JAXB du PortType
Marshall
SOAP
JAX-WS
Conteneur Java
keulkeul.blogspot.com

Serveur
Web
Classes JAVA
Cette classe décrit le
Légende annotées
traitement du service web
implémentant le
1 Générer implicitement service web
par l’outil WSGEN
2 Générer explicitement
par l’outil WSIMPORT Couche Serveur JAX-WS - M. Baron - Page 25
Développement Serveur : Top / Down

† L’approche Top / Down consiste à démarrer le développe-


ment à partir d’un document WSDL
† Le document WSDL est accessible via une URL ou via un
fichier physique
† Utilisation explicite de l’outil wsimport pour la génération du
squelette du service web
† Génération des classes liées à JAXB
@mickaelbaron

† Génération des interfaces WS (interface décrivant le PortType)


† Création d’un POJO annotée @WebService en précisant
l’emplacement de l’interface du portType (Proxy)
keulkeul.blogspot.com

† Déployer l’application sur un serveur d’application


† Le reste du processus de développement est identique à
celui de l’approche Bottom / Up JAX-WS - M. Baron - Page 26
Développement Serveur : Top / Down

† Exemple : développer le service web Notebook à partir


du document WSDL
<?xml version="1.0" encoding="UTF-8"?>
<definitions ...>
<types>...</types>
<portType name="NotebookService">
<operation name="addPersonWithComplexType">
<input message="tns:addPersonWithComplexType"/>
<output message="tns:addPersonWithComplexTypeResponse"/>
</operation>
<operation name="getPersonByName">
<input message="tns:getPersonByName"/>
<output message="tns:getPersonByNameResponse"/>
</operation>
<operation name="getPersons">
@mickaelbaron

<input message="tns:getPersons"/> WSDL utilisé pour


<output message="tns:getPersonsResponse"/>
</operation> générer le squelette
<operation name="addPersonWithSimpleType">
<input message="tns:addPersonWithSimpleType"/>
du service web
</operation>
</portType>
<binding name="NotebookPortBinding" type="tns:NotebookService">...</binding>
keulkeul.blogspot.com

<service name="NotebookService">...</service>
</definitions>

Document WSDL issu


du service web Notebook
(Projet jaxws-notebookwebservice)
JAX-WS - M. Baron - Page 27
Développement Serveur : Top / Down

† Exemple (suite) : développer le service web Notebook à


partir du document WSDL
Pour chaque type défini dans le
WSDL une classe Java (JAXB) est
générée
Classes Java
Générées

L’interface NotebookService
définit la classe Java
annotée avec JAX-WS
@mickaelbaron

@WebService(name = "NotebookService", targetNamespace = "http://notebookwebservice.mickaelbaron.fr/")


...
public interface NotebookService {

@WebMethod
@WebResult(name = "addPersonWithComplexTypeResult", targetNamespace = "")
keulkeul.blogspot.com

@RequestWrapper(localName = "addPersonWithComplexType", targetNamespace = "http://notebookwebservice.mickaelbaron.fr/",


className = "fr.mickaelbaron.notebookwebservicefromwsdl.AddPersonWithComplexType")
@ResponseWrapper(localName = "addPersonWithComplexTypeResponse", targetNamespace = "http://notebookwebservice.mickaelbaron.fr/",
className = "fr.mickaelbaron.notebookwebservicefromwsdl.AddPersonWithComplexTypeResponse")
public boolean addPersonWithComplexType(
@WebParam(name = "newPerson", targetNamespace = "")Person newPerson);

...
} Interface NotebookService.java du projet
jaxws-notebookwebservicefromwsdl
JAX-WS - M. Baron - Page 28
Développement Serveur : Top / Down

† Exemple (suite) : développer le service web Notebook à


partir du document WSDL
@WebService(endpointInterface = "fr.mickaelbaron.notebookwebservicefromwsdl.NotebookService")
public class NotebookServiceImpl {
public boolean addPersonWithComplexType(Person newPerson) {
... L’utilisation du mot clé implémentation
}
return true;
n’est pas obligatoire, l’annotation se
public Person getPersonByName(String name) {
charge d’effectuer cette relation
Person current = new Person();
current.setName(name);
current.setBirthyear("1976");
current.setAddress("17 Square Mickael BARON");
return current;
}

public List<Person> getPersons() { Implémentation du traitement


Person first = new Person();
du service web (Non généré à
@mickaelbaron

first.setName("Ken BLOCK");
first.setBirthyear("1967");
first.setAddress("United States");
développer)
Person second = new Person();
second.setName("Colin MCRAE");
second.setBirthyear("1968");
second.setAddress("Scotland");

List<Person> tabPerson = new ArrayList<Person>();


keulkeul.blogspot.com

tabPerson.add(first);
tabPerson.add(second);
return tabPerson;
NotebookServiceImpl.java du projet
} jaxws-notebookwebservicefromwsdl
public void addPersonWithSimpleType(String name, String address, String birthyear) {
System.out.println("Name : " + name + " Address : " + address + " birthyear : " + birthyear);
}
}

JAX-WS - M. Baron - Page 29


Développement Serveur : Top / Down

† Exemple : wsimport avec Maven (wsdl à partir d’un fichier)

<project ...>
... Plug-in à utiliser pour la
<build>
<plugins> génération des classes Java
<plugin>
<groupId>org.codehaust.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version>
Le document WSDL
<executions> disponible depuis un fichier
<execution>
<goals><goal>wsimport</goal></goals>
</execution>
</executions>
<configuration>
<wsdlDirectory>${project.basedir}/src/wsdl</wsdlDirectory>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
@mickaelbaron

<keep>true</keep>
<executable>${java.home}/bin/wsimport</executable>
<packageName>fr.mickaelbaron.notebookwebservicefromwsdl</packageName>
</configuration>
</plugin>
</plugins> Package par défaut des
</build>
</project> classes générées
keulkeul.blogspot.com

pom.xml du projet
jaxws-notebookwebservicefromwsdl

JAX-WS - M. Baron - Page 30


Développement Serveur : Top / Down

† Exemple : wsimport avec Maven (wsdl à partir d’une URL)

<project ...>
... Plug-in à utiliser pour la
<build>
<plugins> génération des classes Java
<plugin>
<groupId>org.codehaust.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version> Le document WSDL
<executions>
<execution>
disponible depuis une URL
<goals><goal>wsimport</goal></goals>
</execution>
</executions>
<configuration>
<wsdlUrls>
<wsdlUrl>http://localhost:8080/notebookwebservice/notebook?wsdl</wsdlUrl>
@mickaelbaron

</wsdlUrls>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
<keep>true</keep>
<executable>${java.home}/bin/wsimport</executable>
<packageName>fr.mickaelbaron.notebookwebservicefromwsdl</packageName>
</configuration>
</plugin>
</plugins> Package par défaut des
classes générées
</build>
</project>
keulkeul.blogspot.com

pom.xml du projet
jaxws-notebookwebservicefromwsdl

JAX-WS - M. Baron - Page 31


Plan du cours

† Généralités JAX-WS

† Développement serveur
† Bottom -> Up

† Top -> Down

† Développement client
@mickaelbaron

† Annotations
keulkeul.blogspot.com

† Handler

† Déploiement
JAX-WS - M. Baron - Page 32
Développement Client Java

JVM Java Client Description


du service
web
1
Classes Java
décrivant JAXB
Request / Response
WSDL

UnMarshall Marshall Servlet


1
Interface Java Classe Java du SOAP
du PortType Service
1
JAX-WS Serveur
@mickaelbaron

Web Conteneur Java

Cette classe s’occupe


d’effectuer la transformation Utilisation du service web
objet / xml et d’envoyer les par envoie / réception de
paquets SOAP messages SOAP
keulkeul.blogspot.com

Cette classe décrit le


Légende programme qui appel le
service web

1 Générer explicitement Couche Cliente Couche Serveur


par l’outil WSIMPORT
JAX-WS - M. Baron - Page 33
Développement Client Java

† Le développement du client consiste à appeler des opérations


du service web à partir d’un programme Java

† Le client peut être une application développée

† Java SE (JavaFX, Swing, Eclipse RCP)

† Jakarta EE avec les EJB (voir section EJB)


@mickaelbaron

† Possibilité de générer des appels aux services web de

manière synchrone et asynchrone


keulkeul.blogspot.com

† Le développeur ne manipule que du code Java, le code XML

est caché (JAXB) JAX-WS - M. Baron - Page 34


Développement Client Java

† Le développement du client suit une procédure similaire à


l’approche Top / Down où le point de départ est le document
WSDL (via une URL ou via un fichier physique)

† Utilisation explicite de l’outil wsimport pour la génération du


squelette du service web
† Génération des classes liées à JAXB
@mickaelbaron

† Génération de classes service web (PortType et Service)

† Création d’une instance de la classe Service


keulkeul.blogspot.com

† Récupération d’un port via get<ServiceName>Port()

† Invocation des opérations JAX-WS - M. Baron - Page 35


Développement Client Java

† Exemple : développer un client Java (Synchrone) pour le


service web Notebook

Pour chaque type défini dans le


WSDL une classe Java (JAXB) est
générée
Classes Java
Générées

La classe *_Service s’occupe de


gérer les appels distants au service
web
@mickaelbaron
keulkeul.blogspot.com

Le résultat de la génération est identique à la


génération effectuée pour l’approche
Top / Down
JAX-WS - M. Baron - Page 36
Développement Client Java

† Exemple (suite) : développer un client Java (Synchrone)


pour le service web Notebook Création d’une instance de la
classe Service
public class NotebookServiceClient {
public static void main(String[] args) {
NotebookService_Service notebookService = new NotebookService_Service();
NotebookService notebookPort = notebookService.getNotebookPort();
Récupération d’un
Person refPerson = new Person();
refPerson.setName("Baron Mickael");
port via
refPerson.setAddress("Poitiers"); getNotebookPort()
refPerson.setBirthyear("1976");

boolean addPersonWithComplexType = notebookPort.addPersonWithComplexType(refPerson);

System.out.println(addPersonWithComplexType);
@mickaelbaron

}
}

NotebookServiceClient.java du projet Appel de l’opération du service web


jaxws-notebookwebserviceclient
keulkeul.blogspot.com

Déployer le service web du projet


jaxws-notebookwebservice avant
l’exécution de ce projet
JAX-WS - M. Baron - Page 37
Développement Client Java

† Exemple (suite) : développer un client Java (Synchrone)


pour le service web Notebook
@WebService(endpointInterface = "fr.mickaelbaron.notebookwebservice.NotebookService")
public class NotebookServiceImpl {
public boolean addPersonWithComplexType(Person newPerson) {
System.out.println("Starting process ...");
Le traitement du service
try {
Thread.sleep(5000);
web peut prendre un
} catch (InterruptedException e) { certain temps
e.printStackTrace();
}

System.out.println("Name: " + newPerson.getName() + " Address: " + newPerson.getAddress() +


@mickaelbaron

" birthyear: " + newPerson.getBirthyear());

return true;
}
...
}
keulkeul.blogspot.com

Dans le cas où le temps de


NotebookServiceImpl.java du projet réponse d’un service web est
jaxws-notebookwebservice particulièrement long, prévoir
un appel asynchrone

JAX-WS - M. Baron - Page 38


Développement Client Java

† Si le temps de réponse de l’appel à une opération d’un


service web est long, prévoir un appel asynchrone

† JAX-WS permet d’appeler des services web en mode


asynchrone si l’information est précisée dans le binding

† Lors de la génération des fichiers classes (via wsimport)


@mickaelbaron

fournir un fichier binding suivant


<?xml version="1.0" encoding="ISO-8859-1"?>
<bindings wsdlLocation="http://localhost:8080/NotebookWebService/notebook?wsdl"
xmlns="http://java.sun.com/xml/ns/jaxws">
keulkeul.blogspot.com

<enableAsyncMapping>true</enableAsyncMapping>
</bindings>

binding.xml du projet
jaxws-notebookwebserviceasyncclient
JAX-WS - M. Baron - Page 39
Développement Client Java

† Exemple : développer un client Java (Asynchrone) pour le


service web Notebook
<project ...>
... Plug-in à utiliser pour la
<build>
<plugins> génération des classes Java
<plugin>
<groupId>org.codehaust.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.5</version> Le document WSDL
<executions>
<execution>
disponible depuis une URL
<goals><goal>wsimport</goal></goals>
</execution>
</executions>
<configuration>
<wsdlUrls>
<wsdlUrl>http://localhost:8080/notebookwebservice/notebook?wsdl</wsdlUrl>
@mickaelbaron

</wsdlUrls>
<sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
<keep>true</keep>
<executable>${java.home}/bin/wsimport</executable>
<packageName>fr.mickaelbaron.notebookwebserviceasyncclient</packageName>
<bindingFiles>
<bindingFile>
${basedir}/src/jaxws/binding.xml
</bindingFile>
</bindingFiles>
keulkeul.blogspot.com

</configuration>
</plugin>
</plugins>
</build>
Permet de spécifier le
</project> fichier binding.xml

pom.xml du projet
jaxws-notebookwebserviceasyncclient JAX-WS - M. Baron - Page 40
Développement Client Java

† Exemple (suite) : développer un client Java (Asynchrone)


pour le service web Notebook
public class NotebookServiceAsyncClient {
public static void main(String[] args) throws InterruptedException {
Notebook_Service notebook_Service = new Notebook_Service();

Des méthodes spécifiques au mode


Notebook noteBookPort = notebook_Service.getNoteBookPort();

Person refPerson = new Person();


refPerson.setName("Baron Mickael"); asynchrone sont générées
refPerson.setAddress("Poitiers");
refPerson.setBirthyear("1976");

noteBookPort.addPersonWithComplexTypeAsync(refPerson, new AsyncHandler<AddPersonWithComplexTypeResponse>() {


public void handleResponse(Response<AddPersonWithComplexTypeResponse> res) {
if (!res.isCancelled() && res.isDone()) {
try {
AddPersonWithComplexTypeResponse value = res.get();
System.out.println(value.isAddPersonWithComplexTypeResult());
@mickaelbaron

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

Déclenché quand le traitement


}
}

}
}
de l’opération sera terminé
);

Pour éviter de terminer le


Thread.sleep(10000);
System.out.println("Terminé");
}
programme
keulkeul.blogspot.com

Déployer le service web du projet


jaxws-notebookwebservice avant
NotebookAsyncClient.java du projet
l’exécution de ce projet
jaxws-notebookwebserviceasyncclient
JAX-WS - M. Baron - Page 41
Plan du cours

† Généralités JAX-WS

† Développement serveur
† Bottom -> Up

† Top -> Down

† Développement client
@mickaelbaron

† Annotations
keulkeul.blogspot.com

† Handler

† Déploiement
JAX-WS - M. Baron - Page 42
Annotations : généralités

† JAX-WS repose sur l’utilisation massive d’annotations pour


la configuration d’un service web
† JSR utilisées (JSR 224, 222, 181 et 250)
† Les principales annotations sont les suivantes
† @WebService : POJO implémentant un service web
† @WebMethod : Paramétrer une opération
† @WebParam : Paramétrer un message
@mickaelbaron

† @WebResult : Paramétrer un message de sortie


† @WebFault : Paramétrer un message fault
† À noter que seule l’utilisation de l’annotation @WebService
keulkeul.blogspot.com

est nécessaire (utilisation de valeurs par défaut)


† Nous détaillerons chacune des annotations de manière à
découvrir les paramètres disponibles JAX-WS - M. Baron - Page 43
Annotations : @WebService

† Annote une classe Java pour définir l’implémentation du


service web
† Annote une interface Java pour définir la description du
service web
† Attributs de l’annotation @WebService
† String name : nom du service web
@mickaelbaron

† String endpointInterface : nom de l’interface décrivant le service web


† String portName : nom du port
† String serviceName : nom du service du service web
keulkeul.blogspot.com

† String targetNamespace : le namespace du service web


† String wsdlLocation : l’emplacement du WSDL décrivant le Service
Web JAX-WS - M. Baron - Page 44
Annotations : @WebMethod

† Annote une méthode d’une classe Java exposée comme une

opération du service web

† Attributs de l’annotation : @WebMethod

† String action : l’action de l’opération. Dans le cas d’un binding SOAP,

cela détermine la valeur de l’action SOAP


@mickaelbaron

† boolean exclude : précise que la méthode ne doit pas être exposée

comme une opération. Ne pas utiliser dans une interface Java


keulkeul.blogspot.com

† String operationName : précise le nom de l’attribut name défini dans

l’élément operation du document WSDL


JAX-WS - M. Baron - Page 45
Annotations : @WebParam

† Décrit la relation entre un paramètre d’entrée d’une métho-


de et un message part d’une opération

† Attributs de l’annotation

† boolean header : précise si le paramètre doit être transmis dans


l’en-tête du message (true) ou dans le corps (false)
@mickaelbaron

† WebParam.Mode mode : précise le type d’accès au paramètre (IN,


OUT ou INOUT)

† String name : nom du paramètre


keulkeul.blogspot.com

† String partName : le nom du wsdl:part représentant ce paramètre

† String targetNamespace : l’espace de nommage de ce paramètre


JAX-WS - M. Baron - Page 46
Annotations : @WebResult

† Décrit la relation entre le paramètre de sortie d’une métho-

de et un message part d’une opération

† Attributs de l’annotation

† boolean header : précise si le paramètre de sortie doit être transmis

dans l’en-tête du message (true) ou dans le corps (false)


@mickaelbaron

† String name : nom du paramètre de sortie

† String partName : le nom du wsdl:part représentant ce paramètre de


keulkeul.blogspot.com

sortie

† String targetNamespace : l’espace de nommage de ce paramètre de

sortie
JAX-WS - M. Baron - Page 47
Plan du cours

† Généralités JAX-WS

† Développement serveur
† Bottom -> Up

† Top -> Down

† Développement client
@mickaelbaron

† Annotations
keulkeul.blogspot.com

† Handler

† Déploiement
JAX-WS - M. Baron - Page 48
Handler : généralités

† Les « handlers » sont des intercepteurs permettant de


réaliser des traitements lors de la réception et l’émission de
messages
† Lors de la réception ils sont déclenchés avant l’appel à une opération
† Lors de l’émission ils sont déclenchés après l’appel à une opération
† Un « handler » est disponible dans la couche JAX-WS et par
conséquent autant sur la partie cliente que celle du serveur
† Quand l’utiliser ?
@mickaelbaron

† Pour filtrer les appels aux opérations d’un service web


† Pour l’écriture des logs
keulkeul.blogspot.com

† Deux types de « handlers »


† Handlers liés au protocole de transport (ex : SOAP)
† Handlers liés au contenu transféré appelé logical handlers qui est
indépendant du protocole JAX-WS - M. Baron - Page 49
Handler : généralités

† JAX-WS définit l’interface Handler contenant les principales


méthodes
† boolean handleMessage(C context) : invoquée lors des messages
entrants et sortants. Si false est retourné le processus est arrêté
† boolean handleFault(C context) : invoquée lors des messages en
erreur (fault)

† Le type générique C hérite de MessageContext qui est une


Map contenant un ensemble de propriétés
@mickaelbaron

† MESSAGE_OUTBOUND_PROPERTY : pour savoir s’il s’agit de messages


entrants ou sortants
keulkeul.blogspot.com

† HTTP_REQUEST_HEADERS : pour récupérer l’en-tête HTTP de la


réquête
† WSDL_OPERATION : nom de l’opération WSDL
† WSDL_SERVICE : nom du service WSDL JAX-WS - M. Baron - Page 50
Handler : généralités

† Deux sous interfaces à handler sont proposées pour décrire


chaque type de « handler »
† SOAPHandler a un accès sur l’intégralité du message
SOAP incluant les en-têtes
† LogicalHandler pour une indépendance du protocole de
transport et un accès sur le contenu du message
@mickaelbaron

SOAP En-tête SOAP


MessageContext (header facultatif)
Logical
SOAP Message
MessageContext
keulkeul.blogspot.com

Corps du message SOAP


(body) Logical Message

Enveloppe SOAP

JAX-WS - M. Baron - Page 51


Handler : côté serveur

† Développement d’une classe Java qui implémente soit


l’interface SOAPHandler soit LogicalHandler

† Définir un fichier de correspondance (handlers.xml) qui


précise les classes implémentant les handlers

<?xml version="1.0" encoding="UTF-8"?>


@mickaelbaron

<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
<handler-chain>
<handler>
<handler-name>NOM DU HANDLER</handler-name>
<handler-class>CLASSE DU HANDLER</handler-class>
</handler>
</handler-chain>
</handler-chains>
keulkeul.blogspot.com

† Ajouter l’annotation @HandlerChain sur le POJO du service


web
JAX-WS - M. Baron - Page 52
Handler : côté serveur

† Exemple : ajouter un handler de type SOAPHandler sur le


service web Notebook
public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {

private static PrintStream out = System.out;

public Set<QName> getHeaders() { return null; }


public void close(MessageContext context) { }

public boolean handleMessage(SOAPMessageContext smc) {


logToSystemOut(smc);
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
logToSystemOut(smc);
return true;
}
@mickaelbaron

private void logToSystemOut(SOAPMessageContext smc) {


Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
out.println("\nOutgoing message from web service provider:");
} else {
out.println("\nIncoming message to web service provider:");
}
SOAPMessage message = smc.getMessage();
try {
message.writeTo(out);
keulkeul.blogspot.com

out.println("");
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
}

SOAPLoggingHandler.java du projet
jaxws-notebookwebservicewithsoaphandler JAX-WS - M. Baron - Page 53
Handler : côté serveur

† Exemple (suite) : ajouter un handler de type SOAPHandler


sur le service web Notebook handlers.xml

<?xml version="1.0" encoding="UTF-8"?>


<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
<handler-chain>
<handler>
<handler-name>fr.mickaelbaron.notebookwebservicewithsoaphandler.SOAPLoggingHandler</handler-name>
<handler-class>fr.mickaelbaron.notebookwebservicewithsoaphandler.SOAPLoggingHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>

@WebService(endpointInterface = "fr.mickaelbaron.notebookwebservicefromwsdl.Notebook")
@HandlerChain(file = "handlers.xml")
public class NotebookServiceImpl {
@mickaelbaron

public boolean addPersonWithComplexType(Person newPerson) {


...
}

public Person getPersonByName(String name) {


...
}

public List<Person> getPersons() {


keulkeul.blogspot.com

...
}

public void addPersonWithSimpleType(String name, String address, String birthyear) {


...
}
}

NotebookServiceImpl.java du projet
jaxws-notebookwebservicewithsoaphandler JAX-WS - M. Baron - Page 54
Handler : côté serveur

† Exemple (suite) : ajouter un handler de type SOAPHandler


sur le service web Notebook
@mickaelbaron
keulkeul.blogspot.com

Les messages entrants et sortants


sont affichés avec la structure de
l’enveloppe SOAP
JAX-WS - M. Baron - Page 55
Handler : côté client

† Exemple : ajouter un handler de type SOAPHandler sur le


client du service web Notebook
public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {

private static PrintStream out = System.out;

public Set<QName> getHeaders() { return null; }


public void close(MessageContext context) { }

public boolean handleMessage(SOAPMessageContext smc) {


logToSystemOut(smc);
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
logToSystemOut(smc);
return true;
}
private void logToSystemOut(SOAPMessageContext smc) {
@mickaelbaron

Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);


if (outboundProperty.booleanValue()) {
out.println("\nIncoming message from web service client:");
} else {
out.println("\nOutgoing message to web service client:");
}
SOAPMessage message = smc.getMessage();
try {
message.writeTo(out);
out.println("");
keulkeul.blogspot.com

} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
}

SOAPLoggingHandler.java du projet
jaxws-notebookwebserviceclientwithsoaphandler JAX-WS - M. Baron - Page 56
Handler : côté client

† Exemple (suite) : ajouter un handler de type SOAPHandler


sur le client du service web Notebook
public class NotebookServiceAsyncClient {
public static void main(String[] args) {
NotebookService_Service notebookService = new NotebookService_Service();
NotebookService noteBookPort = notebookService.getNotebookPort();

List<Handler> myHandler = new ArrayList<Handler>();


myHandler.add(new SOAPLoggingHandler());

((BindingProvider)noteBookPort).getBinding().setHandlerChain(myHandler);

Person refPerson = new Person();


refPerson.setName("Baron Mickael");
refPerson.setAddress("Poitiers");
refPerson.setBirthyear("1976");
@mickaelbaron

boolean addPersonWithComplexType = noteBookPort.addPersonWithComplexType(refPerson);


System.out.println(addPersonWithComplexType);
}
}

NotebookClient.java du projet
jaxws-notebookwebserviceclientwithsoaphandler
keulkeul.blogspot.com

JAX-WS - M. Baron - Page 57


Plan du cours

† Généralités JAX-WS

† Développement serveur
† Bottom -> Up

† Top -> Down

† Développement client
@mickaelbaron

† Annotations
keulkeul.blogspot.com

† Handler

† Déploiement
JAX-WS - M. Baron - Page 58
Déploiement

† Trois formes de déploiement pour exécuter votre service web

† Déploiement pour les tests (mode bac à sable)

† Déploiement sur un serveur d’application Java

† Avant l’arrivée des microservices

† Nécessite l’installation d’un serveur (Jetty, Glassfish…)


@mickaelbaron

† Déploiement comme une application Java classique


keulkeul.blogspot.com

† Populaire depuis l’arrivée des microservices

† Serveur d’application est intégré (embedded)


JAX-WS - M. Baron - Page 59
Déploiement pour les tests

† Le développement serveur est possible à partir d’une


application Java classique puisque l’API JAX-WS intègre un
serveur web embarqué
† Pas de dépendance supplémentaire (Tomcat, Jetty, Glassfish)

† Le déploiement est immédiat

† Les deux approches (Top / Down et Bottom / Up) sont


@mickaelbaron

applicables à ce mode de développement

† Usages
keulkeul.blogspot.com

† Pour les tests fonctionnels, fournir des Mock de services web

† Fournir des services web à une application type client lourd


JAX-WS - M. Baron - Page 60
Déploiement pour les tests

† Développer une classe Java implémentant le service web


(ou à partir d’un WSDL et en utilisant wsimport)
† Ajouter l’annotation @WebService
† Créer explicitement une instance du POJO
† Publier le service web par l’intermédiaire de la méthode
Endpoint Endpoint.publish(String adresse, Object implementor)
@mickaelbaron

† Le document WSDL est généré automatiquement à


l’exécution de l’application
keulkeul.blogspot.com

† URL du WSDL : http://monserveur/service?WSDL


† Toutes les méthodes du POJO sont des opérations du
service web JAX-WS - M. Baron - Page 61
Déploiement pour les tests

† La méthode publish est utilisée pour démarrer la publication

du service web

† String adresse : adresse de déploiement du service web depuis le

serveur Web embarqué (http://localhost:8080/ws)

† Object implementor : instance de l’implémentation du service web


@mickaelbaron

† Différentes méthodes proposées par la classe Endpoint

(type de retour de la méthode publish)


keulkeul.blogspot.com

† boolean isPublished() : vérifie si le service est en publication

† void stop() : arrête la publication du service web


JAX-WS - M. Baron - Page 62
Déploiement pour les tests

† Exemple : publier le service web Notebook


@WebService(name="NotebookService",targetNamespace="http://notebookwebservice.mickaelbaron.fr/")
public interface NotebookService {
@WebMethod(operationName="addPersonWithComplexType")
@WebResult(name="addPersonWithComplexTypeResult")
boolean addPersonWithComplexType(
@WebParam(name = "newPerson")Person newPerson);
...
}

Interface NotebookService.java du projet


jaxws-notebookwebservice
@mickaelbaron

@WebService( endpointInterface="fr.mickaelbaron.notebookwebservice.NotebookService",
serviceName="NotebookService",
portName="NotebookPort")
public class NotebookServiceImpl implements NotebookService {
@Override
public boolean addPersonWithComplexType(Person newPerson) { ... }
@Override
public Person getPersonByName(String name) { ... }
keulkeul.blogspot.com

@Override
public Person[] getPersons() { ... }
@Override
public void addPersonWithSimpleType(String name, String address, String birthyear) { ... }
}

Classe NotebookServiceImpl.java du projet


jaxws-notebookwebservice
JAX-WS - M. Baron - Page 63
Déploiement pour les tests

† Exemple (suite) : publier le service web


public class NotebookServicePublish extends JFrame {
private Endpoint publish;
public NotebookServicePublish() {
final JButton startPublish = new JButton();
startPublish.setText("Start Publish");
final JButton stopPublish = new JButton();
stopPublish.setText("Stop Publish");

startPublish.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
NotebookService current = new NotebookServiceImpl();
publish = Endpoint.publish("http://localhost:8080/notebookwebservice/notebook", current);
startPublish.setEnabled(false);
stopPublish.setEnabled(true);
}
});
Utilisée pour publier le
@mickaelbaron

stopPublish.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
service web
publish.stop();
stopPublish.setEnabled(false);
startPublish.setEnabled(true);
}
});
Utilisée arrêter la publication
keulkeul.blogspot.com

...
} du service web
public static void main(String[] args) {
new NotebookServicePublish();
}
}

Classe NotebookServiceSOAPPublishUI.java du
projet jaxws-notebookwebservice JAX-WS - M. Baron - Page 64
Déploiement sur un serveur d’application Java

† Un service web est déployé dans une application web (un


service web par application web)
† Différentes catégories de serveur d’application pour gérer les
services web avec JAX-WS
† Conteneur respectant JSR 109 (Implementing Entreprise Web Services)
† La gestion du service web est transparente et maintenue par le
serveur d’application
† Exemple : Glassfish
@mickaelbaron

† http://jcp.org/en/jsr/summary?id=109
† Conteneur nécessitant une gestion par Servlet
† Nécessite une configuration explicite du service web
keulkeul.blogspot.com

† Exemple : Tomcat
† Note : un composant additionnel se propose de fournir le support
JSR 109 (http://tomcat.apache.org/tomcat-6.0-doc/extras.html)
JAX-WS - M. Baron - Page 65
Déploiement sur un serveur d’application Java

† Dans le cas d’un conteneur dont la gestion du service web est


gérée par une Servlet
† web.xml : précise la Servlet assurant la gestion
† sun-jaxws.xml : utilisé pour effectuer une relation entre le contexte de
l’application et la classe du service web
† Structure d’une application web fournissant un service web
*.html, *.jsp, ... Respecter scrupuleusement la
hiérarchie des répertoires et
@mickaelbaron

le nom des fichiers


web.xml
WEB-INF
sun-jaxws.xml
Fichiers pour la présentation

Fichiers de configuration
keulkeul.blogspot.com

classes *.class

Classes des services web


lib *.jar, *.class
Bibliothèques tiers
JAX-WS - M. Baron - Page 66
Déploiement sur un serveur d’application Java

† Exemple : Tomcat et le fichier de configuration web.xml


<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<description>HelloWorld</description>
<display-name>HelloWorld</display-name>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet> Servlet assurant la gestion du
<description>JAX-WS endpoint - helloworld</description>
<display-name>helloworld</display-name> service web
<servlet-name>helloworld</servlet-name>
@mickaelbaron

<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>helloworld</servlet-name>
<url-pattern>/helloworld</url-pattern>
</servlet-mapping>
<session-config>
keulkeul.blogspot.com

<session-timeout>60</session-timeout> La Servlet est accessible


</session-config>
</web-app> via cette URL

web.xml du projet
jaxws-helloworldwebService JAX-WS - M. Baron - Page 67
Déploiement sur un serveur d’application Java

† Exemple : Tomcat et le fichier de configuration sun-jaxws.xml

<?xml version="1.0" encoding="UTF-8"?>

<endpoints xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime' version='2.0'>


<endpoint
name='helloworld'
implementation='fr.mickaelbaron.helloworldwebservice.HelloWorldServiceImpl'
url-pattern='/helloworld'/>
</endpoints>

sun-jaxws.xml du projet Relation entre la classe


jaxws-helloworldwebservice implémentant le service web et
@mickaelbaron

la Servlet assurant sa gestion


keulkeul.blogspot.com

Le fichier sun-jaxws.xml est également


utilisé pour ajouter des informations
supplémentaires (wsdl, binding…)

JAX-WS - M. Baron - Page 68


Déploiement sur un serveur d’application Java

† Exemple : générer un JAR et un WAR via Maven


<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.mickaelbaron</groupId>
<artifactId>jaxws-helloworldwebservice</artifactId>
<packaging>${project.packaging}</packaging>

<profiles>
<profile>
Utilisation d’une variable pour
<id>jar</id> définir la valeur du packaging
<activation>
<activeByDefault>true</activeByDefault> (JAR ou WAR)
</activation>
<properties>
<project.packaging>jar</project.packaging>
@mickaelbaron

</properties>
</profile>
<profile>
<id>war</id>
<build>
<finalName>helloworldwebservice</finalName>
</build>
<properties> En fonction du profil choisi la
keulkeul.blogspot.com

<project.packaging>war</project.packaging>
</properties>
variable ${project.packaging}
</profile> est modifié en jar ou war
</profiles>
</project>

pom.xml du projet
jaxws-helloworldwebservice JAX-WS - M. Baron - Page 69
Déploiement sur un serveur d’application Java

† Exemple : déployer un service web (packagé war) dans une


instance Tomcat via Docker

$ mvn clean package –P war # Compile et build le projet JAXWS-HelloWorldWebService en invoquant le profil war
=> Fichier helloworldwebservice.war disponible dans le répertoire target/

$ docker pull tomcat:9.0.12-jre10-slim # Télécharge la version 9 de Tomcat avec une JRE 10


=> Image Docker disponible

$ docker run --rm --name helloworldservice-tomcat -v $(pwd)/target/helloworldwebservice.war:/usr/


local/tomcat/webapps/helloworldwebservice.war -it -p 8080:8080 tomcat:9.0.12-jre10-slim
=> Service web disponible à l’adresse http://localhost:8080/helloworldwebservice/helloworld
@mickaelbaron
keulkeul.blogspot.com

JAX-WS - M. Baron - Page 70


Service web avec les EJB : généralités

† À partir d’un EJB Session, il est possible de définir le POJO


associé comme étant un service web
† Pour rappel, l’appel à un EJB Session passe obligatoirement
par un client écrit en Java
† Les avantages à transformer en EJB Session en service web
† Caractéristiques des EJBs (transactions, sécurité, scalabilité, …)
@mickaelbaron

† Plus grande hétérogénéité, le client n’est pas forcément écrit en Java


† Réutilisabilité du code
† Modularité (avec les annotations JAX-WS possibilité de masquer les
keulkeul.blogspot.com

méthodes qui ne doivent pas être découvertes)

† Nécessite d’avoir un conteneur EJB pour le déploiement


† Glassfish, TomEE… JAX-WS - M. Baron - Page 71
Service web avec les EJB : serveur

† Partir d’une classe Java définissant un EJB Session (statefull


ou stateless)
† Ajouter l’annotation @WebService
† Déployer l’application sur un serveur d’application ayant le
support EJB (Glassfish par exemple)
† Le conteneur EJB s’occupe de la gestion du service web,
@mickaelbaron

aucune Servlet n’est nécessaire


† Le document WSDL est généré automatiquement en
respectant les valeurs par défauts
keulkeul.blogspot.com

† URL du WSDL : http://monserveur/app/Service?WSDL

† Toutes les méthodes de l’EJB sont par défaut des opérations


du service web JAX-WS - M. Baron - Page 72
Service web avec les EJB : serveur

† Exemple : définir un EJB Stateless comme étant un service


web Seule l’annotation @Stateless a été ajoutée
@Stateless
@WebService(endpointInterface = "fr.mickaelbaron.notebookwebservicefromejb.NotebookService")
public class NotebookServiceImpl {
public boolean addPersonWithComplexType(Person newPerson) {
...
return true;
}

public Person getPersonByName(String name) {


Person current = new Person();
current.setName(name);
current.setBirthyear("1976");
current.setAddress("17 Square Mickael BARON");
return current;
} Le reste du code est le même
@mickaelbaron

public List<Person> getPersons() { que dans les exemples


Person first = new Person();
... précédents
Person second = new Person();
...

List<Person> tabPerson = new ArrayList<Person>();


tabPerson.add(first);
tabPerson.add(second);
keulkeul.blogspot.com

return tabPerson;
}

public void addPersonWithSimpleType(String name, String address, String birthyear) {


System.out.println("Name : " + name + " Address : " + address + " birthyear : " + birthyear);
}
}

JAX-WS - M. Baron - Page 73


Service web avec les EJB : client

† Le développement du client est similaire au client développé


précédemment où le point de départ est le document
WSDL (via une URL ou via un fichier physique)

† Utilisation explicite de l’outil wsimport pour la génération du


squelette du service web
† Génération des classes liées à JAXB
@mickaelbaron

† Génération de classes service web (PortType et Service)

† Injecter un @WebServiceReference pour récupérer une


instance du Service à partir du conteneur EJB
keulkeul.blogspot.com

† Récupération d’un port via get<ServiceName>Port()

† Invocation des opérations JAX-WS - M. Baron - Page 74


Service web avec les EJB : client

† Exemple : appel d’un service web à partir d’une Servlet


public class NotebookWebServiceFromEJBClientServlet extends HttpServlet {

@WebServiceRef(wsdlLocation = "http://localhost:8080/NotebookWebServiceFromEJB/Notebook?wsdl")
private Notebook_Service service;

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

La référence à
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
try {
out.println("<html>"); Notebook_Service est donnée
out.println("<head>");
par le conteneur EJB
out.println("<title>Servlet NotebookWebServiceFromEJBClientServlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>Servlet NotebookWebServiceFromEJBClientServlet at " + request.getContextPath() + "</h1>");

try {
@mickaelbaron

Notebook port = service.getNoteBookPort();


Person newPerson = new Person();
newPerson.setName("BARON Mickael");
newPerson.setAddress("Poitiers");
newPerson.setBirthyear("1976");
boolean result = port.addPersonWithComplexType(newPerson);
out.println("<div>Result = " + result + "</div>");
} catch (Exception ex) {
ex.printStackTrace();
keulkeul.blogspot.com

}
out.println("</body>");
out.println("</html>");
} finally {
out.close();
}
}
}

JAX-WS - M. Baron - Page 75


JAX-WS « in actions » : services web eBay

† eBay fournit via eBay Developers Program un accès à


certains services via des services web étendus (legacy)
† http://developer.ebay.com/
† https://developer.ebay.com/Devzone/finding/Concepts/FindingAPIGuide.html
† https://developer.ebay.com/Devzone/shopping/docs/Concepts/ShoppingAPIGuide.html
† ...

† L’utilisation de ces services web est soumis à une inscription


pour obtenir une clé d’autorisation
@mickaelbaron

† https://developer.ebay.com/DevZone/account/

† Nous montrons à partir de JAX-WS comment générer un


client d’accès au service de recherche d’eBay (Finding API)
keulkeul.blogspot.com

† Le code du client est fortement inspiré de


† https://github.com/eBayDeveloper/eBay_APICall_CodeSamples
JAX-WS - M. Baron - Page 76
JAX-WS « in actions » : services web eBay

† Utilisation de l’outil wsimport via Maven


† http://developer.ebay.com/webservices/finding/latest/FindingService.wsdl

† Génération des artifacts du service web


† Génération des classes liées à JAXB (72 classes)
† Génération de classes service web (2 classes)

† Création d’une instance de la classe FindingService


@mickaelbaron

† Récupération d’un port getFindingServiceSOAPPort()


† Renseigner dans l’en-tête HTTP les informations de protocole
et d’autorisation
keulkeul.blogspot.com

† Préparer le paramètre de l’opération findItemsAdvanced


† Invocation de l’opération JAX-WS - M. Baron - Page 77
JAX-WS « in actions » : services web eBay

† Exemple : création d’un client pour les Services Web eBay


public class EBAYFindingWebServiceClient {
private static final String CALLNAME = "findItemsAdvanced";
private static final String BASEURL = "http://svcs.ebay.com/services/search/FindingService/v1";
private static final String CATEGORY_ID = "267"; // Categorie pour Livres, BD et revues
private static final String KEYWORDS = "Game of thrones";
private static final String APPID = "TO_COMPLETE";

public static void main(String[] args) { Modifier par votre identifiant


// Initialization
FindingService service = new FindingService(); de sécurité
FindingServicePortType port = service.getFindingServiceSOAPPort();

BindingProvider bp = (BindingProvider) port;


Map<String, Object> requestProperties = bp.getRequestContext();
@mickaelbaron

Map<String, List<String>> httpHeaders = new HashMap<String, List<String>>();


// Set the headers
httpHeaders.put("X-EBAY-SOA-OPERATION-NAME", Collections.singletonList(CALLNAME));
httpHeaders.put("X-EBAY-SOA-SECURITY-APPNAME", Collections.singletonList(APPID));
requestProperties.put(MessageContext.HTTP_REQUEST_HEADERS, httpHeaders);
requestProperties.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, BASEURL);

... Suite dans le prochain transparent


keulkeul.blogspot.com

}
}

Classe EBAYFindingWebServiceClient du projet


jaxws-ebayfindingwebserviceclient
JAX-WS - M. Baron - Page 78
JAX-WS « in actions » : services web eBay

† Exemple (suite) : création d’un client pour service web eBay


public class EBAYFindingWebServiceClient {
public static void main (String[] args) {
...
// Prepare query.
FindItemsAdvancedRequest req = new FindItemsAdvancedRequest();
List<OutputSelectorType> opSelector = req.getOutputSelector();
opSelector.add(OutputSelectorType.SELLER_INFO);

ItemFilter objFilter1 = new ItemFilter(); Création du message d’entrée


objFilter1.setName(ItemFilterType.AVAILABLE_TO);
objFilter1.getValue().add("FR");
à passer à l’opération
... findItemsAdvanced(…)
List<ItemFilter> itemFilter = req.getItemFilter();
itemFilter.add(objFilter1);
@mickaelbaron

itemFilter.add(objFilter2);
itemFilter.add(objFilter3);

List<String> catID = req.getCategoryId();


catID.add(CATEGORY_ID); Appel de l’opération
req.setSortOrder(SortOrderType.END_TIME_SOONEST); permettant de rechercher
req.setKeywords(KEYWORDS);
keulkeul.blogspot.com

FindItemsAdvancedResponse res = port.findItemsAdvanced(req);

// Suite dans le prochain transparent


}
}

JAX-WS - M. Baron - Page 79


JAX-WS « in actions » : services web eBay

† Exemple (suite) : création d’un client pour service web eBay


public class EBAYFindingserviceClient {
public static void main (String[] args) {
...
Récupération
// Extract result. des résultats
SearchResult searchResult = res.getSearchResult();
List<SearchItem> item = searchResult.getItem();
for (SearchItem searchItem : item) {
System.out.println(searchItem.getTitle() + " (" + searchItem.getGalleryURL() + ")");
}
System.out.println("Search Count: " + searchResult.getCount());
}
}
@mickaelbaron

Une liste de
liens d’aperçu
d’image est
générée par
keulkeul.blogspot.com

rapport à la
recherche
effectuée

JAX-WS - M. Baron - Page 80

Vous aimerez peut-être aussi