Services Web (SOAP)

publicité
INSA - ASI
InfoRep : WebServices
Informatique Répartie
Web Services
Alexandre Pauchet
INSA Rouen - Département ASI
BO.B.RC.18, [email protected]
1/43
INSA - ASI
InfoRep : WebServices
Plan
1
Introduction
2
SOAP
3
WSDL
4
Implémentation avec JBoss
5
Passage d’objets et exceptions
6
Alternative : Axis
7
Références
2/43
INSA - ASI
InfoRep : WebServices
Introduction
3/43
(1/4)
Objectif
Limitations de Corba et RMI
Impossibilité de faire transiter des informations à travers un pare-feu
Solution
Le protocole internet (Http) comme protocole de transport
XML pour le formatage des données
Mode RPC sur Internet
INSA - ASI
InfoRep : WebServices
Introduction
(2/4)
Vocabulaire
Service Web : composant logiciel distribué qui utilise le protocole
internet pour le transport des requêtes (HTTP ou SMTP) et XML
pour le formatage des données
UDDI (Universal Description, Discovery and Integration) :
annuaire des services web
WSDL (Web Service Description Language) : langage reposant
sur XML qui permet de décrire un service web
XML-RPC : protocole de Service Web sans état (développé par
Dave Winer de Frontier et Userland)
SOAP (Simple Object Access Protocol) : protocole de Service
Web avec état (développé par Microsoft, DevelopMentor et
UserlanSoftware)
4/43
INSA - ASI
InfoRep : WebServices
Introduction
(3/4)
XML-RPC versus SOAP
“XML-RPC est une spécification et un ensemble d’implémentations
permettant de faire du RPC avec http et le langage XML, exactement de la
même façon que SOAP. En fait, les histoires de XML-RPC et de SOAP
sont intimement liées. À l’origine XML-RPC était appelé informellement
SOAP par ces concepteurs dont l’instigateur était Dave Winer. Les premiers
développement étaient fait en collaboration entre les équipes de UserLand,
DevelopMentor et Microsoft. Mais déçu par la tournure des choses, Dave
Winer décide de séparer sa spécification de celle de Microsoft. Cela aboutit
à XML-RPC. Rapidement Microsoft va jouer le standard de fait, en
introduisant son SOAP dans un groupe de travail du W3C. Aujourd’hui
SOAP supporte plus de fonctionnalités que XML-RPC (pas toujours
utiles ?) et c’est une spécification en devenir alors que XML-RPC est figé.”
Jean-Marc Pierson
http://www.if.insa-lyon.fr/chercheurs/jmpierson/Reseau4IF/
Projets/ProgrammationDistribuee/soap/soap.htm
5/43
INSA - ASI
InfoRep : WebServices
Introduction
(4/4)
Acteurs
Nombreux acteurs
Microsoft .Net
Apache : Axis (2), CXF
Sun : JAX-WS et Metro
JBoss
Autres implémentations open-source
etc.
Interopérabilité
Services des uns utilisables par les autres
WS-I.org : Web Service Interoperability organization
6/43
INSA - ASI
SOAP
InfoRep : WebServices
(1/5)
Organisation d’un message SOAP
Requête HTTP
En-tête HTTP
POST /soap
Contenu/longueur
Message HTTP
Enveloppe SOAP
En-tête
Corps
7/43
INSA - ASI
SOAP
InfoRep : WebServices
(2/5)
Exemple de requête Http contenant un message SOAP
POST /axis/HelloService.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.0
Host: localhost:5555
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 403
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<sayHello soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<arg0 xsi:type="xsd:string">Toto</arg0>
</sayHello>
</soapenv:Body>
</soapenv:Envelope>
8/43
INSA - ASI
SOAP
InfoRep : WebServices
(3/5)
Réponse SOAP à une requête SOAP
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=A71CF66D85AD77975999A0F8A4B71BA5; Path=/axis
Content-Type: text/xml; charset=utf-8
Date: Wed, 09 Apr 2003 10:10:06 GMT
Server: Apache Coyote/1.0
Connection: close
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<sayHelloResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<sayHelloReturn xsi:type="xsd:string">Hello, Toto</sayHelloReturn>
</sayHelloResponse>
</soapenv:Body>
</soapenv:Envelope>
9/43
INSA - ASI
InfoRep : WebServices
SOAP
(4/5)
Sérialisation des données
SOAP utilise les types définis dans XML Schema :
Cf. http://www.w3.org/TR/xmlschema-2/
Cf. Cours de Document
On a donc la possibilité de sérialiser :
des types simples (près d’une quarantaine)
des structures (xs:complexType)
On a aussi la possibilité de sérialiser des tableaux en utilisant un
XML Schema qui définit l’élément Array et l’attribut arrayType :
http://www.w3.org/2001/09/soap-encoding
10/43
INSA - ASI
SOAP
InfoRep : WebServices
(5/5)
11/43
INSA - ASI
InfoRep : WebServices
WSDL
(1/4)
Description
Fichier XML décrivant un service web
Opérations (services) disponibles
Accession (adresse, protocole du Service Web, etc.)
Format des messages échangés entre client et serveur
Pour invoquer le service
Pour interpréter un résultat
Rien sur sa sémantique (ce qu’il fait)
12/43
INSA - ASI
WSDL
InfoRep : WebServices
13/43
(2/4)
Interface/Implémentation
Description WSDL
Des types sont utilisés dans des messages, associés dans des portTypes,
reliés à un protocole par des bindings formant des Services Web.
INSA - ASI
InfoRep : WebServices
WSDL
(3/4)
Contenu
types : contient les définitions de types utilisant un système de
typage donné (comme XSD)
message : décrit les noms et types d’un ensemble de champs à
transmettre (paramètres d’invocation, valeur du retour, etc.)
portType : décrit un ensemble d’opérations. Chaque opération a 0
ou 1 message en entrée, 0 ou plusieurs messages en sortie
binding : spécifie une liaison d’un <porttype> à un protocole
concret (SOAP1.1, etc.). Un <porttype> peut avoir plusieurs
liaisons !
port : spécifie un point d’entrée (endpoint) comme la combinaison
d’un <binding> et d’une adresse réseau
service : une collection de points d’entrée (endpoint) relatifs
14/43
INSA - ASI
InfoRep : WebServices
WSDL
(4/4)
Outils
Générateur WSDL à partir de déploiements SOAP ou EJB,
Générateur de proxy SOAP à partir de WSDL
Toolkits (wsdl2java / java2wsdl, etc.)
Propriétaires (non normalisés)
Ex (Axis) : <PATH-TO-AXIS2>/bin/wsdl2java.sh
Ex (JBoss) : <PATH-TO-JBOSS>/bin/wsconsume.sh
2 approches
Approche Top-Down : WSDL =⇒ code (à remplir) + stubs.
Approche identique à Sun RPC, Corba, etc.
Approche Bottom-up : Web Service =⇒ WSDL
15/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(1/14)
Serveur/Client avec JBoss
Approche Bottom-up
1
Développer une interface (Description du service)
2
Développer une implémentation de cette interface
(POJO : Plain Old Java Object)
3
Développer le Service Web
(POJO + web.xml → archive.war)
4
Déployer le Service Web sur un serveur JBoss
5
Télécharger le fichier wsdl
6
Générer le Stub client
7
Développer le client
16/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
17/43
(2/14)
Annotations Java
Intégrées au JDK 1.5, elles permettent d’ajouter des Méta-informations au code
(i.e. marquer des éléments Java afin de leur ajouter une propriété)
Peuvent être utilisées sur n’importe quel type d’élément Java (package, class,
attribut, méthode, paramètre, etc.)
Plusieurs annotations peuvent être utilisées sur un même élément
Non prises en compte par la JVM (mais présente dans le .class) : il faut écrire
du code ou des outils qui utilise ces informations
Utilisées à la compilation ou à l’exécution
Utilisation : @ suivi du mot-clef correspondant à l’annotation
L’API Java 5.0 propose de base 3 annotations : @Deprecated, @Override et
@SuppressWarnings
Déclaration et création de nouvelles annotations : comme une interface en
utilisant le mot-clef @interface (java.lang.annotation.Annotation)
Possibilité de passer des informations à une annotation : nom=valeur
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(3/14)
Exemple d’annotations Java
Exemple
public @interface MaNouvelleAnnotation {
}
Exemple
@MaNouvelleAnnotation
@SuppressWarnings("deprecation")
public class maClasse {
@UneAutreAnnotation(champ="type")
public String texte = "Texte";
@Override
@SuppressWarnings({"deprecation","unckeked"})
public String toString() {
return this.texte;
}
}
18/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
19/43
(4/14)
Services Web JBoss et annotations
Les outils intégrés à JBoss pour générer du WSDL à partir de code Java
utilisent les annotations pour simplifier le code à produire :
Moins de code à écrire
Génération automatique des descripteurs de déploiement
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(5/14)
Interface
helloWebServices.HelloWorldWS.java
package helloWebService;
import
import
import
import
javax.jws.WebService;
javax.jws.WebMethod;
javax.jws.WebParam;
javax.jws.soap.SOAPBinding;
@WebService(name="HelloWorldWS") // PortType
@SOAPBinding(style=SOAPBinding.Style.RPC) // Binding
public interface HelloWorldWS {
@WebMethod(action="sayHello") // Operation
public String sayHello(@WebParam(name = "name") String name);
}
20/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(6/14)
Implémentation POJO du service
helloWebServices.HelloWorldWSImpl.java
package helloWebService;
import javax.jws.WebService;
@WebService(endpointInterface="helloWebService.HelloWorldWS")
// Port (EndPoint : lien vers une Servlet)
public class HelloWorldWSImpl implements HelloWorldWS {
@Override
public String sayHello(String name) {
return "Hello " + name + " !";
}
}
21/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(7/14)
Déclaration du service
META-INF/web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>HelloWorldWS</servlet-name>
<servlet-class>helloWebService.HelloWorldWSImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldWS</servlet-name>
<url-pattern>/HelloWorldWS</url-pattern>
</servlet-mapping>
</web-app>
22/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(8/14)
Archivage et déploiement
Archivage : jar -cf HelloWorldWebService.war WEB-INF
Fichier HelloWorldWebService.war :
HelloWorldWebService.war
|_ WEB-INF
|
|_ web.xml
|
|_ classes
|
|_ helloWebServices
|
|_ HelloWorldWS.class
|
|_ HelloWorldWSImpl.class
|_ META-INF
|_ MANIFEST.MF
Déploiement de HelloWorldWebService.war dans deploy
23/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
Récupération du WSDL :
(9/14)
http://localhost:8080/HelloWorldWebService/HelloWorldWS?wsdl
24/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
25/43
(10/14)
Stub client
Récupération du stub client
$JBOSS_HOME/bin/wsconsume.sh
http://localhost:8080/HelloWorldWebService/HelloWorldWS?wsdl
Permet de télécharger le fichier wsdl de description du service et de
générer et compiler à la volée les fichiers suivants :
HelloWorldWS.java
HelloWorldWSImplService.java
L’option -k permet de conserver les fichiers .java temporaires
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(11/14)
Fichiers générés à la volée
hellowebservices.HelloWorldWS.java
package hellowebservice;
import
import
import
import
import
javax.jws.WebMethod;
javax.jws.WebParam;
javax.jws.WebResult;
javax.jws.WebService;
javax.jws.soap.SOAPBinding;
/**
* This class was generated by Apache CXF 2.4.6
* 2014-03-19T15:59:37.109+01:00
* Generated source version: 2.4.6
*
*/
@WebService(targetNamespace = "http://helloWebService/", name = "HelloWorldWS")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface HelloWorldWS {
@WebResult(name = "return", targetNamespace = "http://helloWebService/", partName = "return")
@WebMethod(action = "sayHello")
public java.lang.String sayHello(
@WebParam(partName = "name", name = "name")
java.lang.String name
);
}
26/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(12/14)
Fichiers générés à la volée
hellowebservices.HelloWorldWSImplService.java
package hellowebservice;
import
import
import
import
import
import
import
java.net.MalformedURLException;
java.net.URL;
javax.xml.namespace.QName;
javax.xml.ws.WebEndpoint;
javax.xml.ws.WebServiceClient;
javax.xml.ws.WebServiceFeature;
javax.xml.ws.Service;
/**
* This class was generated by Apache CXF 2.4.6
* 2014-03-19T15:59:37.138+01:00
* Generated source version: 2.4.6
*
*/
@WebServiceClient(name = "HelloWorldWSImplService",
wsdlLocation = "http://localhost:8080/HelloWorldWebService/HelloWorldWS?wsdl",
targetNamespace = "http://helloWebService/")
public class HelloWorldWSImplService extends Service {
...
27/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(13/14)
Fichiers générés à la volée
hellowebservices.HelloWorldWSImplService.java
...
public HelloWorldWSImplService() {
super(WSDL_LOCATION, SERVICE);
}
...
/**
*
* @return
*
returns HelloWorldWS
*/
@WebEndpoint(name = "HelloWorldWSImplPort")
public HelloWorldWS getHelloWorldWSImplPort() {
return super.getPort(HelloWorldWSImplPort, HelloWorldWS.class);
}
...
28/43
INSA - ASI
InfoRep : WebServices
Implémentation avec JBoss
(14/14)
Client
client.Client.java
import hellowebservice.HelloWorldWS;
import hellowebservice.HelloWorldWSImplService;
public class Client {
public static void main(String[] args) throws Exception {
HelloWorldWS hello = (new HelloWorldWSImplService()).getHelloWorldWSImplPort();
System.out.println(hello.sayHello(args[0]));
}
}
29/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(1/9)
Utilisation de javabeans
Contrainte sur les passages d’objet : javabeans
Par valeur uniquement, en argument comme en valeur en retour
Constructeur sans argument
Accesseurs et modifieurs sur les attributs (get et set sur chacun
des attributs)
À l’aide de wsconsume, génération de :
ObjectFactory : pour créer des objets côté client
Une classe par Objet transmis
Gestion des exceptions
Totalement transparente pour l’utilisateur
30/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(2/9)
Interface
institute.Secretariat.java
package institute;
import
import
import
import
javax.jws.WebService;
javax.jws.WebMethod;
javax.jws.WebParam;
javax.jws.soap.SOAPBinding;
@WebService(name="Secretariat")
@SOAPBinding(style=SOAPBinding.Style.RPC)
public interface Secretariat {
@WebMethod(action="register")
public Student register(@WebParam(name="candidate") Candidate candidate,
@WebParam(name="testValue") int testValue) throws ChaineVide;
}
31/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(3/9)
Implémentation POJO du service
institute.SecretariatWS.java
package institute;
import javax.jws.WebService;
@WebService(endpointInterface="institute.Secretariat")
public class SecretariatWS implements Secretariat {
@Override
public Student register(Candidate candidate, int testValue) throws ChaineVide {
if(candidate.getName().length()==0)
throw new ChaineVide();
return new Student(candidate.getName(), 10/testValue);
}
}
32/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(4/9)
Passage de javabeans
institute.Candidate.java
institute.Student.java
package institute;
package institute;
public class Candidate {
private String name;
public class Student {
private String name;
private int testValue;
public Candidate ()
{ this.name = ""; }
public Student()
{ this.name = ""; this.testValue = 0; }
public Candidate (String name)
{ this.name = name; }
public Student(String name, int testValue)
{ this.name = name; this.testValue = testValue; }
public void setName(String name)
{ this.name = name; }
public void setName(String name)
{ this.name = name; }
public String getName()
{ return this.name; }
public void setTestValue(int testValue)
{ this.testValue = testValue; }
}
public String getName()
{ return this.name; }
public int getTestValue()
{ return this.testValue; }
}
33/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
Exception déclarée
institute.ChaineVide.java
package institute;
public class ChaineVide extends Exception {
public ChaineVide(){
super("String vide !");
}
}
(5/9)
34/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(6/9)
Déclaration et déploiement du service
META-INF/web.xml
University.war
University.war
<?xml version="1.0" encoding="ISO-8859-1"?>
|_ WEB-INF
<!DOCTYPE web-app PUBLIC
|
|_ web.xml
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
|_ classes
"http://java.sun.com/dtd/web-app_2_3.dtd">
|
|_ institute
<web-app>
|
|_ Secretariat.class
<servlet>
|
|_ SecretariatWS.class
<servlet-name>UniversityWS</servlet-name>
|
|_ Candidate.class
<servlet-class>institute.SecretariatWS</servlet-class>
|
|_ Student.class
</servlet>
|
|_ ChaineVide.class
<servlet-mapping>
|_ META-INF
<servlet-name>UniversityWS</servlet-name>
|_
MANIFEST.MF
<url-pattern>/UniversityWS</url-pattern>
</servlet-mapping>
</web-app>
35/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(7/9)
Récupération du Stub client
$JBOSS_HOME/bin/wsconsume.sh
http://localhost:8080/University/UniversityWS?wsdl
Génération à la volée des fichiers :
ObjectFactory.java
package-info.java
Candidate.java
Student.java
ChaineVide.java
ChaineVide Exception.java
Secretariat.java
SecretariatWS.java
Remarque
Seule la partie correspondant à un javabean est générée !
36/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(8/9)
Classe Candidate générée
institute.Candidate.java (généré)
package institute;
* Sets the value of the name property.
*
* @param value
*
allowed object is
*
{@link String }
*
*/
public void setName(String value) {
this.name = value;
}
...
@XmlType(name = "candidate", propOrder = {
"name"
})
public class Candidate {
}
protected String name;
/**
* Gets the value of the name property.
*
* @return
*
possible object is
*
{@link String }
*
*/
public String getName() {
return name;
}
37/43
INSA - ASI
InfoRep : WebServices
Passage d’objets et exceptions
(9/9)
Client
client.Client.java
import institute.*;
public class Client {
public static void main(String[] args) throws java.lang.Exception {
Secretariat secretariat = (new institute.SecretariatWSService()).getSecretariatWSPort();
Candidate candidate = new Candidate();
if(args.length == 2)
candidate.setName(args[0]);
Student student = secretariat.register(candidate, Integer.parseInt(args[args.length-1]));
System.out.println(student.getName() + " est inscrit. Valeur de test : " + student.getTestValue());
}
}
38/43
INSA - ASI
InfoRep : WebServices
Alternative : Axis
Description d’Apache Axis
Développé par la fondation Apache
Contribution d’HP, IBM, Macromédia, etc.
Open-source
Java, donc multi-plateformes
Conforme aux dernières évolutions de SOAP
Peut être utilisé avec tout serveur Web J2EE
http://ws.apache.org/axis2
axis2.war : utilisation conjointe avec tomcat
(Attention : incompatible avec les dernières versions de JBoss qui
utilisent leur propre système de Web Services)
serveur autonome
39/43
INSA - ASI
InfoRep : WebServices
Alternative : Axis
Développement avec Axis2
Méthode
1
Développer un service POJO
2
Développer le Service Web (services.xml + POJO → archive)
3
Déployer le Service Web
4
Télécharger le fichier wsdl
5
Générer le Stub client
6
Implémenter le client
40/43
INSA - ASI
InfoRep : WebServices
Alternative : Axis
Stub client
Récupération du stub client
sh <PATH-TO-AXIS2>/bin/wsdl2java.sh
-uri http://localhost:8080/axis2/services/XXX?wsdl
-p client.stubs -d adb
Permet de télécharger le fichier wsdl de description du service et de
générer à la volée les fichiers suivants :
XXXStub.java
XXXCallbackHandler.java
À la compilation du client : -extdirs <PATH-TO-AXIS2>/lib/
À l’exécution du client :
-Djava.ext.dirs=<PATH-TO-AXIS2>/lib/
Nécessite la version de développement d’Axis2
41/43
INSA - ASI
InfoRep : WebServices
42/43
Alternative : Axis
Arguments
Paramètres multiples
Il faut initialiser les paramètres un par un (setParam0, setParam1)
Contraintes sur les passages d’objet
En argument comme en valeur en retour
Nécessité d’avoir des accesseurs et modifieurs sur les attributs (get et
set sur chacun des attributs)
Utilisation de la classe XXXStub.ObjetTransmis, mais transtypage
(cast) impossible
⇒ création d’un nouvel objet à la réception
INSA - ASI
InfoRep : WebServices
Références
Services Web open Source :
D. Ayala, C. Browne, V. Chopra, P. Sarang, K. Asphangar, T. McAllister
Campus Press - ISBN : 2-7440-1507-5
Java Web Services :
D. A. Chappell, T. Jewel
O’Reilly - ISBN : 0-596-00269-6
http://community.jboss.org/wiki/jbossws-userguide
43/43
Téléchargement