Plan du cours SOAP en Java

1. outils

Services Web – SOAP en Java
Fabrice Rossi http://apiacoa.org/contact.html. Universit´ Paris-IX Dauphine e

2. programmation d’un client : (a) principe de JAX-RPC (b) exemples (trois types de clients) (c) types Java et types SOAP (d) traduction d’un service complet (e) gestion des erreurs 3. programmation d’un service (avec Axis) : (a) déploiement instantané (b) déploiement adapté (c) EJB

Services Web – SOAP en Java – p.1/71

Services Web – SOAP en Java – p.2/71

Outils utilisés
API Java : JAX-RPC (XML RPC), http://java.sun.com/xml/jaxrpc/, sera intégrée à J2EE 1.4 implémentations : le Java Web Services Developer Pack 1.1 http://java.sun.com/webservices/ AXIS http://ws.apache.org/axis/ implémentation open source du groupe apache descendant de Apache SOAP 2.x et de IBM SOAP4J Dans ce cours : AXIS !

Rôle de JAX-RPC
Rendre les RPC basés sur XML presque aussi simples que RMI : un service web devient une interface héritant de Remote une opération devient une méthode une erreur SOAP (Fault) devient une exception héritant de RemoteException JAX-RPC définit un ensemble de traduction : faire le lien entre les types Java et les types des schémas du W3 représenter informatiquement les concepts de WSDL (service, port, etc.) etc.

Services Web – SOAP en Java – p.3/71

Services Web – SOAP en Java – p.4/71

services.ServiceException.services.org/wsdl/soap/" xmlns:xsd="http://www.xml.lang.net.xmlsoap.RemoteException.org/xml-soap" xmlns:impl="http://localhost:8080/axis/services/Echo" xmlns:intf="http://localhost:8080/axis/services/Echo" xmlns:soapenc="http://schemas.xmlsoap.Echo) : Echo : interface (au sens java) du port EchoService : interface de localisation du port (usine abstraite au sens du design pattern Abstract Factory EchoServiceLocator : implémentation concrète de EchoService EchoSoapBindingStub : stub pour traduire les appels locaux en messages SOAP et vice-versa (implémente l’interface Echo) il ne reste plus qu’à coder le client 1 2 3 4 5 6 Interfaces Echo.Echo.Echo getEcho(java.services.String in0) throws java.apache.org/soap/http"/> <wsdl:operation name="echo"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="echoRequest"> <wsdlsoap:body encodingStyle="http://schemas.apache.w3.String getEchoAddress().java package localhost.Echo. public interface EchoService extends javax.org/2001/XMLSchema"> <wsdl:message name="echoResponse"> <wsdl:part name="echoReturn" type="xsd:string"/> </wsdl:message> <wsdl:message name="echoRequest"> <wsdl:part name="in0" type="xsd:string"/> </wsdl:message> <wsdl:portType name="Echo"> <wsdl:operation name="echo" parameterOrder="in0"> <wsdl:input message="impl:echoRequest" name="echoRequest"/> <wsdl:output message="impl:echoResponse" name="echoResponse"/> </wsdl:operation> </wsdl:portType> Exemple de base (2) 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 Echo.rpc.Echo getEcho() throws javax.wsdl on lance java org.axis.rpc.org/wsdl/" xmlns:apachesoap="http://xml.rmi.Echo. public interface Echo extends java.Echo.lang.wsdl et on obtient 4 classes java (package localhost.axis. } 1 2 3 4 5 6 7 8 9 10 11 Services Web – SOAP en Java – p.axis.wsdl.ServiceException.xmlsoap.8/71 .Exemple de base Service web minimaliste : Echo proposant une opération echo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Echo.axis.xml.URL portAddress) throws javax.services.String echo(java.org/wsdl/" xmlns:wsdlsoap="http://schemas. public localhost.org/soap/encoding/" xmlns:wsdl="http://schemas.6/71 Client magique (AXIS) on récupère Echo.java package localhost.wsdl <wsdl:binding name="EchoSoapBinding" type="impl:Echo"> <wsdlsoap:binding style="rpc" transport="http://schemas.7/71 Services Web – SOAP en Java – p.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/services/Echo" use="encoded"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="EchoService"> <wsdl:port binding="impl:EchoSoapBinding" name="Echo"> <wsdlsoap:address location="http://localhost:8080/axis/services/Echo"/> </wsdl:port> </wsdl:service> </wsdl:definitions> Services Web – SOAP en Java – p.axis.wsdl <?xml version="1.xmlsoap.rmi.axis.rpc.xmlsoap.lang.xmlsoap.5/71 Services Web – SOAP en Java – p. public localhost.services.Service { public java.org/soap/encoding/" namespace="http://localhost:8080/axis/services/Echo" use="encoded"/> </wsdl:input> <wsdl:output name="echoResponse"> <wsdlsoap:body encodingStyle="http://schemas.Remote { public java.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/axis/services/Echo" xmlns="http://schemas.xml. } EchoService.WSDL2Java Echo.

println(port. on obtient une implémentation de EchoService grâce à l’annuaire J2EE Services Web – SOAP en Java – p.xmlsoap.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/Echo"> <echoReturn xsi:type="xsd:string">Essai</echoReturn> </ns1:echoResponse> </soapenv:Body> </soapenv:Envelope> Version plus lourde la solution précédente est statique : il faut engendrer les classes Java puis faire l’appel aspect dynamique : appeler un service web sans le connaître avant le lancement du programme très lourd : pas de gestion des types pas d’interface pas de gestion des espaces de noms etc.xmlsoap. text/* User-Agent: Axis/1.xmlsoap.0 Content-Type: text/xml.xmlsoap.w3.org/soap/envelope/" xmlns:xsd="http://www. multipart/related.11/71 Services Web – SOAP en Java – p.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.echo(args[0])).org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:echo soapenv:encodingStyle="http://schemas. mais pas la classe EchoServiceLocator solution différente dans l’implémentation de Sun (le nom de la classe n’est pas le même) dans un contexte J2EE.9/71 Message reçu 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 echoAnswer HTTP/1. charset=utf-8 Date: Thu.org/2001/XMLSchema" xmlns:xsi="http://www. System.out.12/71 .0 Connection: close <?xml version="1.Le client 1 2 3 4 5 6 7 8 Client. Echo port=service.axis.1 Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 455 <?xml version="1.java import localhost.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:echoResponse soapenv:encodingStyle="http://schemas. application/dime. } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Message envoyé echoRequest POST /axis/services/Echo HTTP/1.10/71 Ce client est (en partie) spécifique AXIS (ligne 4) la norme impose d’engendrer les interfaces EchoService et Echo.org/2001/XMLSchema" xmlns:xsi="http://www. mais on devient spécifique AXIS Services Web – SOAP en Java – p.1 200 OK Content-Type: text/xml.Echo.1RC2 Host: 127.*.w3.0. on peut faire plus simple que la solution du programme qui suit. public class Client { public static void main(String[] args) throws Exception { EchoService service=new EchoServiceLocator().org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/Echo"> <in0 xsi:type="xsd:string">Essai</in0> </ns1:echo> </soapenv:Body> </soapenv:Envelope> Services Web – SOAP en Java – p.w3.org/soap/envelope/" xmlns:xsd="http://www.services.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas. 03 Apr 2003 12:01:01 GMT Server: Apache Coyote/1.0.w3.getEcho(). charset=utf-8 Accept: application/soap+xml.

java localhost.xml. ServiceFactory factory=ServiceFactory."echo"). Call call=service.serviceName).15/71 ."Echo"). System.URL.println(port.rpc. Method method.xml.13/71 Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Mapping types Java vers types W3C Difficulté principale par rapport à RMI Types supportés : les types fondamentaux (par exemple boolean devient xsd:boolean) les chaînes de caractères (String devient xsd:string) les entiers et réels arbitraires (par exemple BigDecimal devient xsd:decimal) les dates (Calendar devient xsd:dateTime) le binaire sous la forme d’un tableau de byte (byte[]) qui devient xsd:base64Binary ou xsd:hexBinary les types tableaux et les JavaBeans construits à partir des types fondamentaux certaines implémentations proposent des traductions d’autres types comme par exemple les Collections. } } un appel à une méthode d’une interface implémentée par un dynamic proxy est transformé en un appel à la méthode invoke JAX-RPC propose d’engendrer dynamiquement un stub à partir du WSDL Services Web – SOAP en Java – p.net.out. Solution intermédiaire Mécanisme de proxy dynamique.org/2001/XMLSchema".XSDString.newInstance(). String endpoint="http://localhost:8080/axis/services/Echo".services.invoke( new String[] { "Essai" } ).newInstance().xml. call.setTargetEndpointAddress(endpoint).namespace.IN).axis. QName portName=new QName(ns. basé sur le système de dynamic proxy introduit par le jdk 1.QName.createCall(portName.namespace. javax."Echo"). QName serviceName=new QName(ns. ServiceFactory factory=ServiceFactory.java javax. } } Services Web – SOAP en Java – p.ServiceFactory. Object[] args). javax.createService(serviceName).Echo.ParameterMode.w3.Call.Echo. call.out. mais on a alors de sérieux problèmes d’inter-opérabilité Services Web – SOAP en Java – p.println(ret). javax. URL wsdlURL=new URL(wsdl). String wsdl="http://localhost:8080/axis/services/Echo?wsdl".rpc.xml.operationName). public class ClientDynamiqueProxy { public static void main(String [] args) throws Exception { String ns="http://localhost:8080/axis/services/Echo".rpc."EchoService").ServiceFactory.getPort(portName. QName serviceName=new QName(ns."EchoService").createService(wsdlURL.setReturnType(XSDString).ParameterMode. javax. javax. } public class ClientDynamique { public static void main(String [] args) throws Exception { String ns="http://localhost:8080/axis/services/Echo". System. QName operationName=new QName(ns. Service service=factory.Service.16/71 import import import import import ClientDynamiqueProxy.lang."string"). Service service=factory.14/71 Totalement portable et dynamique Services Web – SOAP en Java – p. String ret = (String) call.xml. javax. call.QName.3 : un dynamic proxy est une classe qui implémente une ou plusieurs interfaces spécifiées au moment de l’exécution elle implémente l’interface InvocationHandler (package java.class). QName XSDString=new QName("http://www.rpc.addParameter("in0".rpc. Echo port=(Echo)service.Echo.Service.xml.rpc.reflect) : 1 2 3 4 5 public interface InvocationHandler { public Object invoke(Object proxy.echo("Essai")). java. javax. QName portName=new QName(ns.xml.Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import import import import import ClientDynamique.xml.

Person.String last.print(result[i]+" ").lang.services. import localhost.lang.java Exemple de client basique 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 28 29 30 31 32 public void setLast(java.xmlsoap.io. } Services Web – SOAP en Java – p.xmlsoap.out.length. } System.first = first.String getLast() { return last. int[] result=port.org/soap/encoding/" xsi:type="ns2:Person" xmlns:soapenc="http://schemas.axis. } public void setFirst(java.java import PhoneBookWS. PhoneBook port=service.PhoneBookWS.lang.*. private java. public class Person implements java.17/71 Exemple (3) : code engendré par Axis Person.last = last.org/soap/encoding/" xmlns:ns2="urn:PhoneBookWS"> <first xsi:type="xsd:string">John</first> <last xsi:type="xsd:string">Doe</last> </multiRef> Test. c’est-à-dire à une paire : setXxx pour fixer la valeur de propriété getXxx pour obtenir la valeur de la propriété exemple : PhoneBookWS et son opération getPhoneNumber représentation d’une personne : prénom et nom WSDL : PersonType. p. p.String first.setLast("Doe").18/71 Services Web – SOAP en Java – p.println(). } public java.getPhoneBookWS().String last) { this.getPhoneNumber(p). */ package PhoneBookWS.lang. } } Services Web – SOAP en Java – p.lang.i++) { System. } le reste de la classe est très complexe il est spécifique Axis le programmeur n’a pas besoin de le connaître Message SOAP engendré (partie) : 1 2 3 4 5 6 7 8 Exemple <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.Exemple d’une struct une struct SOAP correspond à un JavaBean le nom du bean correspond à celui de la struct chaque champ de la struct correspond à une propriété du bean. public Person() { } public java. for(int i=0.setFirst("John"). Person p=new Person().20/71 .xml 1 2 3 4 5 6 <complexType name="Person"> <sequence> <element name="first" nillable="true" type="xsd:string"/> <element name="last" nillable="true" type="xsd:string"/> </sequence> </complexType> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Exemple (2) : code engendré par Axis Person.String first) { this.java /** * Person.19/71 Services Web – SOAP en Java – p.out.Serializable { private java.lang. public class Test { public static void main(String[] args) throws Exception { PhoneBookService service=new PhoneBookServiceLocator().String getFirst() { return first.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter.i<result.

la moyenne et la variance du tableau paramètre en Java.org/2002/12/soap-encoding" xmlns:soapenc="http://schemas.xmlsoap.1RC2 Host: localhost Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 776 <?xml version="1. un seul paramètre en mode out) inout : mixte.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.xml. inconnu en Java représentation en Java de out et inout : classes Holder déjà définies pour les types standards (par exemple IntHolder et StringHolder) engendrées automatiquement pour les autres types par exemple pour le type Truc : 1 2 3 4 5 6 7 8 TrucHolder.Holder { public Truc value.0 Connection: close <?xml version="1.w3. multipart/related.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas. application/dime.0 Content-Type: text/xml.rpc. charset=utf-8 Date: Wed.w3. 30 Apr 2003 08:13:59 GMT Server: Apache Coyote/1.org/2001/XMLSchema" xmlns:xsi="http://www. } } Exemple un service de calculs proposant le port Calc type de port Arrays opération meanVar : prend comme paramètre in un tableau de double prend comme paramètres inout deux doubles.xmlsoap.org/soap/encoding/"> <item>1</item> <item>2</item> <item>3</item> </getPhoneNumberReturn> </ns1:getPhoneNumberResponse> </soapenv:Body> </soapenv:Envelope> Services Web – SOAP en Java – p.Requête 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Requ^te e POST /axis/services/PhoneBookWS HTTP/1.24/71 .23/71 Services Web – SOAP en Java – p.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:getPhoneNumberResponse soapenv:encodingStyle="http://schemas. text/* User-Agent: Axis/1.holders.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/PhoneBookWS"> <in0 href="#id0"/> </ns1:getPhoneNumber> <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.xmlsoap.22/71 Modes de passage des paramètres trois modes de passage en SOAP/RPC : in : pas de problème en Java out : résultat.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:getPhoneNumber soapenv:encodingStyle="http://schemas.org/2001/XMLSchema" xmlns:xsi="http://www. charset=utf-8 Accept: application/soap+xml.e.w3. public TrucHolder() { } public TrucHolder(Truc value) { this..org/soap/encoding/" xsi:type="ns2:Person" xmlns:soapenc="http://schemas.java public final class TrucHolder implements javax.org/soap/encoding/" xmlns:ns2="urn:PhoneBookWS"> <first xsi:type="xsd:string">John</first> <last xsi:type="xsd:string">Doe</last> </multiRef> </soapenv:Body> </soapenv:Envelope> Services Web – SOAP en Java – p.w3. il n’y a pas vraiment de différences en out et inout Services Web – SOAP en Java – p.w3. i.21/71 Réponse R´ponse e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 HTTP/1.org/soap/envelope/" xmlns:xsd="http://www.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/PhoneBookWS"> <getPhoneNumberReturn xsi:type="soapenc:Array" soapenc:arrayType="xsd:int[3]" xmlns:ns2="http://www.xmlsoap.1 200 OK Content-Type: text/xml.xmlsoap. inconnu en Java (sauf si le résultat est unique.org/soap/envelope/" xmlns:xsd="http://www.value = value.

DoubleHolder.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:meanVarResponse soapenv:encodingStyle="http://schemas.2}..w3. import javax.rpc.0</mean> <var xsi:type="xsd:double">0.28/71 .holders.w3.meanVar(x.. charset=utf-8 Date: Thu.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/Calc"> <mean xsi:type="xsd:double">2.axis. 01 May 2003 10:05:14 GMT Server: Apache Coyote/1.xmlsoap. } } Services Web – SOAP en Java – p..Calc.org/soap/envelope/" xmlns:xsd="http://www.mean.0</mean> <var xsi:type="xsd:double">0..xml.5..5</item> <item>2.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas..println(var.getCalc(). charset=utf-8 Accept: application/soap+xml.2.w3. DoubleHolder var=new DoubleHolder(). --> <wsdl:operation name="meanVar" parameterOrder="x mean var"> <wsdl:input message="impl:meanVarRequest" name="meanVarRequest"/> <wsdl:output message="impl:meanVarResponse" name="meanVarResponse"/> </wsdl:operation> </wsdl:portType> Exemple : code client 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ClientStat. --> <wsdl:message name="meanVarResponse"> <wsdl:part name="mean" type="xsd:double"/> <wsdl:part name="var" type="xsd:double"/> </wsdl:message> <wsdl:portType name="Arrays"> <!-.25</var> </ns1:meanVarResponse> </soapenv:Body> </soapenv:Envelope> Services Web – SOAP en Java – p. text/* User-Agent: Axis/1.Exemple : WSDL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Calc.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas. double[] x={1.xmlsoap.*.org/soap/encoding/"> <item>1.java import localhost. multipart/related.w3.xmlsoap.xmlsoap. application/dime. Arrays port=service.services.27/71 Requête 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 R´ponse e HTTP/1.org/soap/encoding/"/> <complexType name="ArrayOf_xsd_double"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:double[]"/> </restriction> </complexContent> </complexType> </schema> </wsdl:types> <wsdl:message name="meanVarRequest"> <wsdl:part name="x" type="impl:ArrayOf_xsd_double"/> <wsdl:part name="mean" type="xsd:double"/> <wsdl:part name="var" type="xsd:double"/> </wsdl:message> <!-.value).0</var> </ns1:meanVar> </soapenv:Body> </soapenv:Envelope> Services Web – SOAP en Java – p.1RC2 Host: localhost Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 696 <?xml version="1.out.out.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:meanVar soapenv:encodingStyle="http://schemas.0</item> </x> <mean xsi:type="xsd:double">0.0 Connection: close <?xml version="1.w3.xmlsoap.5</item> <item>2. port.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/Calc"> <x xsi:type="soapenc:Array" soapenc:arrayType="xsd:double[3]" xmlns:soapenc="http://schemas.value).var).org/2001/XMLSchema"> <import namespace="http://schemas.xmlsoap.25/71 Services Web – SOAP en Java – p.wsdl <wsdl:types> <schema targetNamespace="http://localhost:8080/axis/services/Calc" xmlns="http://www.println(mean. System.1 200 OK Content-Type: text/xml.org/2001/XMLSchema" xmlns:xsi="http://www. System. DoubleHolder mean=new DoubleHolder().26/71 Requête 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Requ^te e POST /axis/services/Calc HTTP/1.0 Content-Type: text/xml. public class ClientStat { public static void main(String[] args) throws Exception { ArraysService service=new ArraysServiceLocator().org/soap/envelope/" xmlns:xsd="http://www.org/2001/XMLSchema" xmlns:xsi="http://www.5.

rmi.Echo getEcho() throws javax. public interface EchoService extends javax.RemoteException.Echo getEcho(java.ServiceException.axis.services.32/71 Services Web – SOAP en Java – p.Remote { public double[] sum(double[] x. javax.Echo.java 1 2 3 4 5 6 7 8 9 10 package localhost.Echo.services.rpc. double[] y) throws java.rpc.Calc.30/71 Traduction des bindings L’outil de traduction WSDL produit pour chaque binding une classe concrète : de nom name Stub qui implémente l’interface associée au portType qu’incarne le binding qui traduit les appels locaux en messages SOAP et les réponses du serveur (messages SOAP) en réponse locale exemples : CalcSoapBindingStub implémente Arrays EchoSoapBindingStub implémente Echo etc.holders.String getEchoAddress().rmi.axis. public localhost.DoubleHolder var) throws java.rmi.ServiceException.rpc. } une classe : de nom name ServiceLocator spécifique à Axis implémentation de l’interface name Service Services Web – SOAP en Java – p.31/71 .lang.holders.services.xml. } Services Web – SOAP en Java – p.URL portAddress) throws javax.xml. public void meanVar(double[] x. javax.axis.rpc.DoubleHolder mean.axis. la traduction doit donc produire plusieurs packages Traduction des portTypes L’outil de traduction WSDL produit une interface pour chaque portType du WSDL : portant le nom du portType dérivée de Remote proposant une méthode par operation qui représente le “serveur” sur le client exemple : Arrays.Traduction des types L’outil de traduction WSDL vers Java doit engendrer une classe pour chaque élément type défini dans le WSDL (la classe porte le même nom que le type) engendrer une classe Holder pour chaque type spécifique utilisé comme paramètre ou ou inout dans une opération chaque espace de noms défini dans le document WSDL doit être associé à un package Java : si par exemple le document définit plusieurs espaces de noms.java 1 2 3 4 5 6 7 8 9 10 11 package localhost.RemoteException.xml.29/71 Services Web – SOAP en Java – p.Service { public java.services. public localhost.Echo. transparent pour le programmeur (ne s’utilise pas directement) Traduction des services L’outil de traduction WSDL produit pour chaque service : une interface : de nom name Service qui propose une méthode get pour chacun des ports regroupés dans le service exemple : Arrays.net.xml. public interface Arrays extends java.xml.rpc.

xmlsoap.0</item> </in0> <in1 xsi:type="soapenc:Array" soapenc:arrayType="xsd:double[2]" xmlns:soapenc="http://schemas.0</item><item>-2. Arrays port=service.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/Calc"> <in0 xsi:type="soapenc:Array" soapenc:arrayType="xsd:double[3]" xmlns:soapenc="http://schemas.org/soap/encoding/"> <item>1.0</item> </in1> </ns1:sum></soapenv:Body> </soapenv:Envelope> Services Web – SOAP en Java – p. multipart/related.2. } } } Requête 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Requ^te e POST /axis/services/Calc HTTP/1.0 Content-Type: text/xml.xmlsoap. double[] x={1.esynaps.org/soap/envelope/" xmlns:xsd="http://www.org/soap/envelope/" xmlns:xsd="http://www.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server. application/dime.w3.out.-2}.getCalc(). public class Client { public static void main(String[] args) throws Exception { ArraysService service=new ArraysServiceLocator().y).userException</faultcode> <faultstring>java.5.length.33/71 Réponse (Fault) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Requ^te e HTTP/1.axis.println(z[i]).org/soap/encoding/"> <item>1.ArrayIndexOutOfBoundsException: 2</faultstring> <detail/> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope> Un exemple complet Service : requêtes DNS implémenté en .34/71 Services Web – SOAP en Java – p.Calc.w3. double[] z=port.5</item><item>2.services.i++) { System. charset=utf-8 Accept: application/soap+xml. double[] y={1. 01 May 2003 06:37:42 GMT Server: Apache Coyote/1. for(int i=0.xmlsoap.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:sum soapenv:encodingStyle="http://schemas.org/2001/XMLSchema" xmlns:xsi="http://www.NET modèle document (pas RPC) proposé par www.i<z.org/2001/XMLSchema" xmlns:xsi="http://www.xmlsoap.Gestion des erreurs Exemple : un service de calculs proposant le port Calc type de port Arrays opération sum : prend comme paramètre deux tableaux de double renvoie le tableau somme des paramètres client “incorrect” (tableaux de tailles différentes) : 1 2 3 4 5 6 7 8 9 10 11 12 13 Client.w3.5.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.1RC2 Host: localhost Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 789 <?xml version="1.5</item><item>3.0 Connection: close <?xml version="1. charset=utf-8 Date: Thu.36/71 . text/* User-Agent: Axis/1.com WSDL assez complexe : 264 lignes binding POST et GET Le client traduit le Fault en une RemoteException Services Web – SOAP en Java – p.lang.w3.3}.35/71 Services Web – SOAP en Java – p.1 500 Erreur Interne de Servlet Content-Type: text/xml.xmlsoap.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.*.java import localhost.sum(x.

ArrayOfString1 aliases) { this. public org. } public void setIPAddress(java.tempuri.tempuri.rpc.rmi.Serializable { private java.lang.ArrayOfString IPList) { this. public ArrayOfString() { } public java.Serializable { private java.HostInfo getHostInfoByName(java.tempuri. } Types engendrés (fragments) (3) ArrayOfString. public HostInfo() { } public java.java Le port : YourHostSoap.tempuri.rmi. public org.ServiceException.RemoteException. public class ArrayOfString implements java.tempuri. public org.lang.String[] getIPAddress() { return IPAddress.ServiceException.rmi.tempuri.IPList = IPList.lang.tempuri. } Services Web – SOAP en Java – p.rmi.tempuri.lang.tempuri. } public void setIPAddress(int i. public class HostInfo implements java.String getName() { return name.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package org.lang.lang.Code engendré Le service : 1 2 3 4 5 6 7 8 9 package org.tempuri.rpc.tempuri. } public void setIPList(org.java public void setAliases(org.io.lang. } public org.Remote { public org. java. } public org. private java.name = name.tempuri.YourHostSoap getYourHostSoap() throws javax.URL portAddress) throws javax.xml.String name) throws java.rpc.RemoteException.lang. } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package org.String getIPAddress(int i) { return IPAddress[i].lang.39/71 Services Web – SOAP en Java – p.ArrayOfString getIPList() { return IPList. } public java. private org.lang.String[] IPAddress. } public java.xml.aliases = aliases. public org.xml.RemoteException.error = error.YourHostSoap getYourHostSoap(java.lang.IPAddress = IPAddress.40/71 .ArrayOfString IPList.String getYourHostSoapAddress().HostInfo getHostInfoByIP(java.Service { public java.java 1 2 3 4 5 6 7 8 9 10 package org. } Services Web – SOAP en Java – p. private org.IPAddress[i] = value.String error) { this.String name.ArrayOfString1 aliases. public interface YourHost extends javax. } public void setError(java.io.String IPAddress) throws java.tempuri.lang.String[] IPAddress) { this.String name) { this.HostInfo whoAmI() throws java.lang.String value) { this. } YourHost.38/71 Types engendrés (fragments) (2) 26 27 28 29 30 31 32 33 34 HostInfo.java Types engendrés (fragments) HostInfo. } public void setName(java.tempuri.net.37/71 Services Web – SOAP en Java – p.ArrayOfString1 getAliases() { return aliases.String error. public interface YourHostSoap extends java.lang.String getError() { return error.tempuri.

microsoft. charset=utf-8 Accept: application/soap+xml.w3.155 207. public class ArrayOfString1 implements java.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.getAliases().com Cache-Control: no-cache Pragma: no-cache SOAPAction: "http://tempuri.println("n´ant").tempuri.println("Alias :").println("Nom : "+info.41/71 Services Web – SOAP en Java – p.java Client 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Client. ArrayOfString1 aliases=info.249.getYourHostSoap(). } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package org. java.27 207.String value) { this. } } else { System.*.akadns. YourHostSoap port=service.alias[i] = value.String[] getAlias() { return alias.getIPList().out.46.out.lang. e } } public static void main(String[] args) throws Exception { YourHost service=new YourHostLocator().println("Adresse(s) IP :").46.org/2001/XMLSchema" xmlns:xsi="http://www.com</Name> </GetHostInfoByName> </soapenv:Body> </soapenv:Envelope> java Client www.Types engendrés (fragments) (4) ArrayOfString1. application/dime.222 207.i<str.44/71 .lang.org/2001/XMLSchema-instance"> <soapenv:Body> <GetHostInfoByName xmlns="http://tempuri.com Services Web – SOAP en Java – p. HostInfo info=port.java import org.i++) { System. System. } public void setAlias(int i.lang. text/* User-Agent: Axis/1.getAlias()).46. print(aliases.134.getName()).134.lang.getHostInfoByName(args[0]).190 207.w3.asmx HTTP/1. } Services Web – SOAP en Java – p.222 Alias : www.1RC2 Host: www.println(’\t’+str[i]).43/71 Services Web – SOAP en Java – p.46. } public java.microsoft.alias = alias.microsoft.249.out.46. } public void setAlias(java.42/71 Exécution 1 2 3 4 5 6 7 8 9 10 11 12 Requête 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Requ^te e POST /webservices/YourHostInfo.lang.String getAlias(int i) { return alias[i].out.org/"> <Name>www.out.String[] alias) { this.length.org/GetHostInfoByName" Content-Length: 374 <?xml version="1.org/soap/envelope/" xmlns:xsd="http://www. System.com Nom : www. print(ips.io.String[] alias.esynaps. System.134.Serializable { private java.tempuri. ArrayOfString ips=info.net Adresse(s) IP : 207. public class Client { public static void print(String[] str) { if(str != null) { for(int i=0.getIPAddress()). public ArrayOfString1() { } public java.46.190 207.microsoft.xmlsoap. multipart/related.0 Content-Type: text/xml.249.

pas de services de haut niveau.e.jws.org/"> <GetHostInfoByNameResult> <Name>www.util.46.currentTimeMillis())).48/71 .46.0 Date: Wed.46.249.249. etc. le web service est mis à jour automatiquement (recompilation et production du .134.46/71 Solution évoluée Avenir pour l’implémentation en Java : exposer un Entreprise Java Bean en tant que web service limitations : Stateless Session Bean prévu dans J2EE 1. les transactions.w3.setTime(new Date(System. public class Calendrier { public Calendar getDate() { Calendar result = Calendar. return result.org/2001/XMLSchema"> <soap:Body> <GetHostInfoByNameResponse xmlns="http://tempuri.134.jws dans un dossier particulier (cf la doc Axis) le web service est créé : déployé à l’URL http://localhost:8080/axis/Compteur. max-age=0 Content-Type: text/xml.wsdl) Services Web – SOAP en Java – p.microsoft.190</IPAddress> <IPAddress>207. 30 Apr 2003 14:20:06 GMT Cache-Control: private.46. charset=utf-8 Content-Length: 706 <?xml version="1.org/2001/XMLSchema-instance" xmlns:xsd="http://www.46.222</IPAddress> </IPList> <Aliases> <Alias>www.jws?wsdl si on modifie le fichier .190</IPAddress> <IPAddress>207.jws WSDL accessible à l’URL http://localhost:8080/axis/Compteur. } } à recopier sous le nom Calendrier.222</IPAddress> <IPAddress>207.45/71 Services Web – SOAP en Java – p.155</IPAddress> <IPAddress>207.xmlsoap.java import java. result.Calendar.net</Name> <IPList> <IPAddress>207. etc.249.4 (qui n’existe pas encore officiellement !) version basique des services web (problème d’intégration avec les mécanismes de sécurité.getInstance(). 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 HTTP/1. nécessitant plusieurs classes par exemple) Problèmes : très spécifique Axis implémentation basique : pas de persistance. import java.Date.com</Alias> </Aliases> </GetHostInfoByNameResult> </GetHostInfoByNameResponse> </soap:Body> </soap:Envelope> Services Web – SOAP en Java – p.org/soap/envelope/" xmlns:xsi="http://www.microsoft.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.47/71 Services Web – SOAP en Java – p.134.w3.27</IPAddress> <IPAddress>207.util.1 200 OK Server: Microsoft-IIS/5.) avantages : on récupère toute la puissance des EJB possible avec Axis dès maintenant 1 2 3 4 5 6 7 8 9 Exemple d’Instant Deployment programme Java : Calendrier.Réponse R´ponse e Programmation d’un service Avec Axis : Axis est une application web et s’installe donc dans un serveur JSP/Servlet Instant Deployment : mécanisme (spécifique Axis) permettant de se contenter de copier une classe à un emplacement spécifique pour obtenir le service correspondant ! Custom Deployment : mécanisme (spécifique Axis) permettant de réaliser des services plus complexes (i.46.akadns.

xmlsoap.xmlsoap.xmlsoap.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/axis/Calendrier. import java.xmlsoap.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/Calendrier.jws"/> </wsdl:port> </wsdl:service> </wsdl:definitions> Services Web – SOAP en Java – p.WSDL engendré automatiquement 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Calendrier.jws" xmlns:intf="http://localhost:8080/axis/Calendrier.Calendar.*. Calendar now=port.getDate(). Services Web – SOAP en Java – p.xmlsoap.DateFormat. } } Limitations de l’Instant Deployment pas de Java Beans pour le mapping de types évolués code source obligatoire pas de maîtrise du cycle de vie : création de l’objet destruction pas de contrôle fin : sur le fichier WSDL engendré sur les méthodes exportées etc.wsdl <wsdl:binding name="CalendrierSoapBinding" type="impl:Calendrier"> <wsdlsoap:binding style="rpc" transport="http://schemas.jws" xmlns="http://schemas.org/soap/encoding/" xmlns:wsdl="http://schemas.util.getCalendrier().jws" use="encoded"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="CalendrierService"> <wsdl:port binding="impl:CalendrierSoapBinding" name="Calendrier"> <wsdlsoap:address location="http://localhost:8080/axis/Calendrier.org/soap/encoding/" namespace="http://localhost:8080/axis/Calendrier.jws" use="encoded"/> </wsdl:input> <wsdl:output name="getDateResponse"> <wsdlsoap:body encodingStyle="http://schemas. import java. public class Client { public static void main(String[] args) throws Exception { CalendrierService service=new CalendrierServiceLocator().51/71 Services Web – SOAP en Java – p.org/wsdl/soap/" xmlns:xsd="http://www.org/2001/XMLSchema"> <wsdl:message name="getDateRequest"> </wsdl:message> <wsdl:message name="getDateResponse"> <wsdl:part name="getDateReturn" type="xsd:dateTime"/> </wsdl:message> <wsdl:portType name="Calendrier"> <wsdl:operation name="getDate"> <wsdl:input message="impl:getDateRequest" name="getDateRequest"/> <wsdl:output message="impl:getDateResponse" name="getDateResponse"/> </wsdl:operation> </wsdl:portType> 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 WSDL engendré automatiquement (2) Calendrier.axis.52/71 .getTime())).org/soap/http"/> <wsdl:operation name="getDate"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="getDateRequest"> <wsdlsoap:body encodingStyle="http://schemas. Calendrier port=service.Calendrier_jws.jws" xmlns:soapenc="http://schemas.getDateInstance().format(now.Date.49/71 Exemple de client 1 2 3 4 5 6 7 8 9 10 11 12 Client import localhost.apache.org/xml-soap" xmlns:impl="http://localhost:8080/axis/Calendrier.50/71 Services Web – SOAP en Java – p.wsdl <?xml version="1. System.org/wsdl/" xmlns:wsdlsoap="http://schemas. import java.out.util.println(DateFormat.w3.text.

etc.java Services Web – SOAP en Java – p.apache. } public int next() { return compte++.apache.class) à un emplacement spécifique (cf la doc Axis) on fabrique un fichier WSDD : Web Service Deployment Descriptor spécifique Axis exemple : 1 2 3 4 5 6 7 nouvel objet à chaque appel : le compteur est toujours nul ! problèmes : pas de persistance simple gaspillage de ressources (reconnexion à une BD par exemple) Services Web – SOAP en Java – p.54/71 Exemple de Custom Deployment (2) on exécute java org.wsdd <deployment xmlns="http://xml. } public String getLast() { return last.wsdd 1 2 3 <undeployment xmlns="http://xml. } } PhoneBook.Création Avec l’Instant Deployment.client.56/71 .apache.axis.apiacoa.java gestion du cycle de vie : sous-élément de service <parameter name="scope" value="value"/> l’attribut value peut être : request : un objet par requête (par défaut) application : un seul objet par serveur session : un objet par session (extension Axis) Services Web – SOAP en Java – p.java 1 2 3 4 5 6 7 8 9 public class Compteur { private int compte. Services Web – SOAP en Java – p. on utilise un autre fichier WSDD : undeploy. public Compteur() { compte = 0.55/71 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package org. les méthodes à exporter. public void setFirst(String f) { first=f.wsdd le service est déployé : à l’URL http://localhost:8080/axis/services/Compteur WSDL : http://localhost:8080/axis/services/Compteur?wsdl pour supprimer le service.2. } } service : 1 2 3 4 5 6 package org.3}.phonebook. } } Exemple de Custom Deployment on reprend le même programme on copie le fichier compilé (Compteur. } public String getFirst() { return first.apache. public class PhoneBook { public int[] getPhoneNumber(Person p) { return new int[] {1. private String last. l’objet est recréé à chaque invocation : exemple : Compteur.org/axis/wsdd/"> <service name="Compteur"/> </undeployment> Java beans On reprend l’exemple de l’annuaire : type Person : Person.53/71 deploy.org/axis/wsdd/providers/java"> <service name="Compteur" provider="java:RPC"> <parameter name="className" value="Compteur"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> indique la classe principale d’un service. public class Person { private String first.apiacoa. } public void setLast(String f) { last=f.AdminClient deploy.phonebook.org/axis/wsdd/" xmlns:java="http://xml.

signature.org/axis/wsdd/providers/java"> <service name="PhoneBookWS" provider="java:RPC"> <parameter name="className" value="org. permet de préciser certains éléments : traduction package vers namespace emplacement du WS encoding (literal ou encoded) style (document ou RPC) etc.apache. emplacement précisé par l’élément wsdlFile (fils de service) Fonctions avancées mapping XML spécifique : permet de transformer toute classe Java en XML et vice-versa demande la programmation des traductions ( !) Handlers : s’intercale entre le serveur et le client peut modifier les messages SOAP au vol applications : cryptographie.apache.phonebook.phonebook.Java2WSDL . etc.org/2001/XMLSchema"> <import namespace="http://schemas.. compression.axis.apache. transport par messages (à la place de HTTP) basé sur JMS signature sessions (HTTP et header SOAP) attachments Services Web – SOAP en Java – p.w3.org/axis/wsdd/" xmlns:java="http://xml.wsdd <deployment xmlns="http://xml.apiacoa.59/71 Services Web – SOAP en Java – p.Déploiement 1 2 3 4 5 6 7 8 9 10 deploy.wsdl <wsdl:types> <schema targetNamespace="http://localhost:8080/axis/services/PhoneBookWS" xmlns="http://www.Person"/> </service> </deployment> Types engendrés 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 PhoneBookWS.xmlsoap.57/71 Services Web – SOAP en Java – p.. logging.58/71 WSDL engendré automatiquement au déploiement peut être engendré avant : java org.60/71 .org/soap/encoding/"/> <complexType name="Person"> <sequence> <element name="first" nillable="true" type="xsd:string"/> <element name="last" nillable="true" type="xsd:string"/> </sequence> </complexType> <complexType name="ArrayOf_xsd_int"> <complexContent> <restriction base="soapenc:Array"> <attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:int[]"/> </restriction> </complexContent> </complexType> </schema> </wsdl:types> fichier WSDD : beanMapping : qname : nom du type pour WSDL languageSpecificType : objet correspondant (attention au préfixe java) mapping standard : une struct SOAP un champ par propriété du Java Bean Services Web – SOAP en Java – p.PhoneBook"/> <parameter name="allowedMethods" value="*"/> <beanMapping qname="myNS:Person" xmlns:myNS="http://localhost:8080/axis/services/PhoneBookWS" languageSpecificType="java:org.apiacoa.wsdl.

echo.echo.*. basé sur Axis JBoss 3. /** * Session Bean Template * * @ejb:bean name="Echo" * display-name="Echo Bean" * type="Stateless" * transaction-type="Container" * jndi-name="ejb/org/apiacoa/echo/Echo" * **/ public class EchoBean implements SessionBean { private SessionContext mContext. } public String toString() { return "EchoBean [ " + hashCode() + " ]".ejb.EJBException.63/71 Services Web – SOAP en Java – p. J2EE 1. javax.lang. /** * @ejb:interface-method view-type="remote" **/ public String echo(String s) { return "Echo: "+s+"("+hashCode()+")". etc.SessionContext. } Services Web – SOAP en Java – p. javax.2 : basé sur Axis à démarrer en mode all attention aux problèmes de sécurité diverses extensions pour la gestion de session.ejb.apiacoa. javax.Do not edit! */ package org.out.4 ne concerne que les Stateless Session Beans déjà disponible dans divers produits : JOnAS 3.rmi. /** * Remote interface for Echo.apiacoa. import javax.ejb.ejb.SessionContext.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /* * Generated file . import javax.SessionBean. import javax. javax.String s ) throws java.RemoteException.ejb.String echo( java.ejb.ejb. pour la sécurité.EJBObject { public java. avec Axis : rien à programmer (en plus des EJB) tout passe par WSDD Code de l’EJB : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 Exemple avec JBoss EchoBean. import import import import import java.lang. } public void setSessionContext(SessionContext aContext) throws EJBException { mContext = aContext. } Services Web – SOAP en Java – p.CreateException.Publication d’un EJB comme service web spécification EJB 2.61/71 Code EJB (2) 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 EchoBean.1 (délicat à configurer).ejb.1. } public void ejbActivate() throws EJBException { } public void ejbPassivate() throws EJBException { } public void ejbRemove() throws EJBException{ } } XDoclet Engendre le reste du code : Echo. * @xdoclet-generated at 6 mai 2003 14:27:42 */ public interface Echo extends javax.64/71 .java /** * @ejb:create-method view-type="remote" **/ public void ejbCreate() throws CreateException { System.ejb.println( "EchoBean: create" ).62/71 Services Web – SOAP en Java – p.lang.CreateException.SessionBean.EJBException.java package org. import javax.

Do not edit! */ package org.echo. import import import import import java.wsdl <wsdl:binding name="EchoServiceSoapBinding" type="impl:Echo"> <wsdlsoap:binding style="rpc" transport="http://schemas.apiacoa.xmlsoap.AdminClient -lhttp://localhost:8080/jboss-net/services/Administration deploy. javax.org/axis/wsdd/providers/java"> <service name="EchoService" provider="java:EJB"> <parameter name="jndiURL" value="localhost"/> <parameter name="jndiContextClass" value="org.apiacoa.xmlsoap.wsdl <?xml version="1. Lookup using {1} * @xdoclet-generated at 6 mai 2003 12:21:40 */ public interface EchoHome extends javax.XDoclet (2) EchoHome.org/soap/encoding/" xmlns:wsdl="http://schemas.org/soap/encoding/" namespace="http://localhost:8080/jboss-net/services/EchoService" use="encoded"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="EchoService"> <wsdl:port binding="impl:EchoServiceSoapBinding" name="EchoService"> <wsdlsoap:address location="http://localhost:8080/jboss-net/services/EchoService"/> </wsdl:port> </wsdl:service> </wsdl:definitions> Services Web – SOAP en Java – p.org/2001/XMLSchema"> <wsdl:types/> <wsdl:message name="echoRequest"> <wsdl:part name="in0" type="xsd:string"/> </wsdl:message> <wsdl:message name="echoResponse"> <wsdl:part name="echoReturn" type="xsd:string"/> </wsdl:message> <wsdl:portType name="Echo"> <wsdl:operation name="echo" parameterOrder="in0"> <wsdl:input message="impl:echoRequest" name="echoRequest"/> <wsdl:output message="impl:echoResponse" name="echoResponse"/> </wsdl:operation> </wsdl:portType> Services Web – SOAP en Java – p. public static final String JNDI_NAME="ejb/org/apiacoa/echo/Echo".SessionContext.apache.NamingContextFactory"/> <parameter name="beanJndiName" value="ejb/org/apiacoa/echo/Echo"/> <parameter name="homeInterfaceName" value="org. javax.apiacoa.RemoteException.lang.67/71 WSDL engendré (2) 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 EchoService.w3.xmlsoap. } attention.EJBException. public org.apache.echo.SessionBean.68/71 .xmlsoap. javax.65/71 Services Web – SOAP en Java – p.jnp. on déploie (au sens web service) avec la commande : java org.ejb.apache.xmlsoap.ejb.org/wsdl/" xmlns:apachesoap="http://xml. /** * Home interface for Echo.ejb.org/soap/http"/> <wsdl:operation name="echo"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="echoRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.echo.org/xml-soap" xmlns:impl="http://localhost:8080/jboss-net/services/EchoService" xmlns:intf="http://localhost:8080/jboss-net/services/EchoService" xmlns:soapenc="http://schemas.echo.apiacoa.xmlsoap.CreateException.66/71 WSDL engendré 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 EchoService.ejb.Echo create() throws javax.apache.rmi.*.org/wsdl/" xmlns:wsdlsoap="http://schemas.wsdd <deployment xmlns="http://xml. javax.wsdd le service est accessible à l’URL http://localhost:8080/jboss-net/services/EchoService Services Web – SOAP en Java – p.Echo"/> <parameter name="allowedMethods" value="echo"/> </service> </deployment> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 /* * Generated file .CreateException.axis.client.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/jboss-net/services/EchoService" xmlns="http://schemas.EJBHome { public static final String COMP_NAME="java:comp/env/ejb/Echo".org/wsdl/soap/" xmlns:xsd="http://www. il ne faut pas mettre * dans allowedMethods.ejb.EchoHome"/> <parameter name="remoteInterfaceName" value="org.org/axis/wsdd/" xmlns:java="http://xml.java Fichier WSDD spécifique 1 2 3 4 5 6 7 8 9 10 11 12 deploy.ejb.org/soap/encoding/" namespace="http://localhost:8080/jboss-net/services/EchoService" use="encoded"/> </wsdl:input> <wsdl:output name="echoResponse"> <wsdlsoap:body encodingStyle="http://schemas.interfaces. java.

70/71 Conseils pratiques (2) utiliser des Business Delegates : “définition” : ensemble d’interfaces et de classes qui permet à la couche de présentation d’utiliser la couche métier design pattern standard en J2EE cache totalement au client le fait qu’il utilise un système réparti sous forme d’interfaces.echo.lookup("ejb/org/apiacoa/echo/Echo").getEchoService().out. import javax. System. Echo port=service.rmi. import org. import javax.class). } } EJB Conseils pratiques pas de solution portable pour la gestion de session : utiliser des stateless session beans gérer “à la main” la session.*. public class Client { public static void main(String[] args) throws Exception { InitialContext context = new InitialContext().InitialContext. EchoHome. ce qui permet de changer l’implémentation : une implémentation RMI classique (EJB) une implémentation locale (tests) une implémentation web service (firewall) etc.*.jboss_net.69/71 Services Web – SOAP en Java – p.narrow(context.echo(args[0])). } } Services Web – SOAP en Java – p.echo(args[0])).PortableRemoteObject.naming. public class Client { public static void main(String[] args) throws Exception { EchoService service=new EchoServiceLocator(). Echo service = home. System. EchoHome home = (EchoHome) PortableRemoteObject.println(port.create().out. Services Web – SOAP en Java – p. par exemple : une clé permanente par l’utilisateur une clé temporaire créée par un mécanisme de login à partir d’une clé permanente transmettre l’information de session à chaque appel par encore de solution portable pour la sécurité : utiliser HTTPS ( ?) on peut envisager des wrappers web services construits à la main (solution intérimaire) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package test.71/71 .println(service.apiacoa.Clients 1 2 3 4 5 6 7 8 Web services import localhost.EchoService.services.