Vous êtes sur la page 1sur 18

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 dun client : (a) principe de JAX-RPC (b) exemples (trois types de clients) (c) types Java et types SOAP (d) traduction dun service complet (e) gestion des erreurs 3. programmation dun service (avec Axis) : (a) dploiement instantan (b) dploiement adapt (c) EJB

Services Web SOAP en Java p.1/71

Services Web SOAP en Java p.2/71

Outils utiliss
API Java : JAX-RPC (XML RPC), http://java.sun.com/xml/jaxrpc/, sera intgre J2EE 1.4 implmentations : le Java Web Services Developer Pack 1.1 http://java.sun.com/webservices/ AXIS http://ws.apache.org/axis/ implmentation open source du groupe apache descendant de Apache SOAP 2.x et de IBM SOAP4J Dans ce cours : AXIS !

Rle de JAX-RPC
Rendre les RPC bass sur XML presque aussi simples que RMI : un service web devient une interface hritant de Remote une opration devient une mthode une erreur SOAP (Fault) devient une exception hritant de RemoteException JAX-RPC dnit un ensemble de traduction : faire le lien entre les types Java et les types des schmas du W3 reprsenter 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

Exemple de base
Service web minimaliste : Echo proposant une opration 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.wsdl <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/axis/services/Echo" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://localhost:8080/axis/services/Echo" xmlns:intf="http://localhost:8080/axis/services/Echo" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.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.wsdl <wsdl:binding name="EchoSoapBinding" type="impl:Echo"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="echo"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="echoRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/services/Echo" use="encoded"/> </wsdl:input> <wsdl:output name="echoResponse"> <wsdlsoap:body encodingStyle="http://schemas.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.5/71

Services Web SOAP en Java p.6/71

Client magique (AXIS)


on rcupre Echo.wsdl on lance java org.apache.axis.wsdl.WSDL2Java Echo.wsdl et on obtient 4 classes java (package localhost.axis.services.Echo) : Echo : interface (au sens java) du port EchoService : interface de localisation du port (usine abstraite au sens du design pattern Abstract Factory EchoServiceLocator : implmentation concrte de EchoService EchoSoapBindingStub : stub pour traduire les appels locaux en messages SOAP et vice-versa (implmente linterface Echo) il ne reste plus qu coder le client
1 2 3 4 5 6

Interfaces
Echo.java package localhost.axis.services.Echo; public interface Echo extends java.rmi.Remote { public java.lang.String echo(java.lang.String in0) throws java.rmi.RemoteException; } EchoService.java package localhost.axis.services.Echo; public interface EchoService extends javax.xml.rpc.Service { public java.lang.String getEchoAddress(); public localhost.axis.services.Echo.Echo getEcho() throws javax.xml.rpc.ServiceException; public localhost.axis.services.Echo.Echo getEcho(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; }

1 2 3 4 5 6 7 8 9 10 11

Services Web SOAP en Java p.7/71

Services Web SOAP en Java p.8/71

Le client
1 2 3 4 5 6 7 8 Client.java import localhost.axis.services.Echo.*; public class Client { public static void main(String[] args) throws Exception { EchoService service=new EchoServiceLocator(); Echo port=service.getEcho(); System.out.println(port.echo(args[0])); } } 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.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.1RC2 Host: 127.0.0.1 Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 455 <?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> <ns1:echo soapenv:encodingStyle="http://schemas.xmlsoap.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.10/71

Ce client est (en partie) spcique AXIS (ligne 4) la norme impose dengendrer les interfaces EchoService et Echo, mais pas la classe EchoServiceLocator solution diffrente dans limplmentation de Sun (le nom de la classe nest pas le mme) dans un contexte J2EE, on obtient une implmentation de EchoService grce lannuaire J2EE

Services Web SOAP en Java p.9/71

Message reu
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 echoAnswer HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Date: Thu, 03 Apr 2003 12:01:01 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> <ns1:echoResponse soapenv:encodingStyle="http://schemas.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 prcdente est statique : il faut engendrer les classes Java puis faire lappel aspect dynamique : appeler un service web sans le connatre avant le lancement du programme trs lourd : pas de gestion des types pas dinterface pas de gestion des espaces de noms etc. on peut faire plus simple que la solution du programme qui suit, mais on devient spcique AXIS

Services Web SOAP en Java p.11/71

Services Web SOAP en Java p.12/71

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.java javax.xml.rpc.Call; javax.xml.rpc.Service; javax.xml.rpc.ServiceFactory; javax.xml.rpc.ParameterMode; javax.xml.namespace.QName;

Solution intermdiaire
Mcanisme de proxy dynamique, bas sur le systme de dynamic proxy introduit par le jdk 1.3 : un dynamic proxy est une classe qui implmente une ou plusieurs interfaces spcies au moment de lexcution elle implmente linterface InvocationHandler (package java.lang.reflect) :
1 2 3 4 5 public interface InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args); }

public class ClientDynamique { public static void main(String [] args) throws Exception { String ns="http://localhost:8080/axis/services/Echo"; String endpoint="http://localhost:8080/axis/services/Echo"; QName serviceName=new QName(ns,"EchoService"); QName portName=new QName(ns,"Echo"); QName operationName=new QName(ns,"echo"); ServiceFactory factory=ServiceFactory.newInstance(); Service service=factory.createService(serviceName); Call call=service.createCall(portName,operationName); call.setTargetEndpointAddress(endpoint); QName XSDString=new QName("http://www.w3.org/2001/XMLSchema","string"); call.addParameter("in0",XSDString,ParameterMode.IN); call.setReturnType(XSDString); String ret = (String) call.invoke( new String[] { "Essai" } ); System.out.println(ret); } }

un appel une mthode dune interface implmente par un dynamic proxy est transform en un appel la mthode invoke JAX-RPC propose dengendrer dynamiquement un stub partir du WSDL
Services Web SOAP en Java p.14/71

Totalement portable et dynamique


Services Web SOAP en Java p.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


Difcult principale par rapport RMI Types supports : les types fondamentaux (par exemple boolean devient xsd:boolean) les chanes de caractres (String devient xsd:string) les entiers et rels arbitraires (par exemple BigDecimal devient xsd:decimal) les dates (Calendar devient xsd:dateTime) le binaire sous la forme dun tableau de byte (byte[]) qui devient xsd:base64Binary ou xsd:hexBinary les types tableaux et les JavaBeans construits partir des types fondamentaux certaines implmentations proposent des traductions dautres types comme par exemple les Collections, mais on a alors de srieux problmes dinter-oprabilit
Services Web SOAP en Java p.16/71

import import import import import

ClientDynamiqueProxy.java localhost.axis.services.Echo.Echo; java.net.URL; javax.xml.rpc.Service; javax.xml.rpc.ServiceFactory; javax.xml.namespace.QName;

public class ClientDynamiqueProxy { public static void main(String [] args) throws Exception { String ns="http://localhost:8080/axis/services/Echo"; String wsdl="http://localhost:8080/axis/services/Echo?wsdl"; URL wsdlURL=new URL(wsdl); QName serviceName=new QName(ns,"EchoService"); QName portName=new QName(ns,"Echo"); ServiceFactory factory=ServiceFactory.newInstance(); Service service=factory.createService(wsdlURL,serviceName); Echo port=(Echo)service.getPort(portName,Echo.class); System.out.println(port.echo("Essai")); } }

Services Web SOAP en Java p.15/71

Exemple dune struct


une struct SOAP correspond un JavaBean le nom du bean correspond celui de la struct chaque champ de la struct correspond une proprit du bean, cest--dire une paire : setXxx pour xer la valeur de proprit getXxx pour obtenir la valeur de la proprit exemple : PhoneBookWS et son opration getPhoneNumber reprsentation dune personne : prnom et nom WSDL : PersonType.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.java /** * Person.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package PhoneBookWS; public class Person implements java.io.Serializable { private java.lang.String first; private java.lang.String last; public Person() { } public java.lang.String getFirst() { return first; } public void setFirst(java.lang.String first) { this.first = first; } public java.lang.String getLast() { return last; }
Services Web SOAP en Java p.18/71

Services Web SOAP en Java p.17/71

Exemple (3) : code engendr par Axis


Person.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.lang.String last) { this.last = last; }

le reste de la classe est trs complexe il est spcique Axis le programmeur na pas besoin de le connatre Message SOAP engendr (partie) :
1 2 3 4 5 6 7 8 Exemple <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:Person" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:PhoneBookWS"> <first xsi:type="xsd:string">John</first> <last xsi:type="xsd:string">Doe</last> </multiRef>

Test.java import PhoneBookWS.Person; import localhost.axis.services.PhoneBookWS.*; public class Test { public static void main(String[] args) throws Exception { PhoneBookService service=new PhoneBookServiceLocator(); PhoneBook port=service.getPhoneBookWS(); Person p=new Person(); p.setFirst("John"); p.setLast("Doe"); int[] result=port.getPhoneNumber(p); for(int i=0;i<result.length;i++) { System.out.print(result[i]+" "); } System.out.println(); } }

Services Web SOAP en Java p.19/71

Services Web SOAP en Java p.20/71

Requte
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.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.1RC2 Host: localhost Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 776 <?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> <ns1:getPhoneNumber soapenv:encodingStyle="http://schemas.xmlsoap.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.org/soap/encoding/" xsi:type="ns2:Person" xmlns:soapenc="http://schemas.xmlsoap.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.21/71

Rponse
Rponse 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.1 200 OK Content-Type: text/xml; charset=utf-8 Date: Wed, 30 Apr 2003 08:13:59 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> <ns1:getPhoneNumberResponse soapenv:encodingStyle="http://schemas.xmlsoap.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.w3.org/2002/12/soap-encoding" xmlns:soapenc="http://schemas.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.22/71

Modes de passage des paramtres


trois modes de passage en SOAP/RPC : in : pas de problme en Java out : rsultat, inconnu en Java (sauf si le rsultat est unique, i.e., un seul paramtre en mode out) inout : mixte, inconnu en Java reprsentation en Java de out et inout : classes Holder dj dnies pour les types standards (par exemple IntHolder et StringHolder) engendres automatiquement pour les autres types par exemple pour le type Truc :
1 2 3 4 5 6 7 8
TrucHolder.java public final class TrucHolder implements javax.xml.rpc.holders.Holder { public Truc value; public TrucHolder() { } public TrucHolder(Truc value) { this.value = value; } }

Exemple
un service de calculs proposant le port Calc type de port Arrays opration meanVar : prend comme paramtre in un tableau de double prend comme paramtres inout deux doubles, la moyenne et la variance du tableau paramtre en Java, il ny a pas vraiment de diffrences en out et inout

Services Web SOAP en Java p.23/71

Services Web SOAP en Java p.24/71

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.wsdl <wsdl:types> <schema targetNamespace="http://localhost:8080/axis/services/Calc" xmlns="http://www.w3.org/2001/XMLSchema"> <import namespace="http://schemas.xmlsoap.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> <!-- ... --> <wsdl:message name="meanVarResponse"> <wsdl:part name="mean" type="xsd:double"/> <wsdl:part name="var" type="xsd:double"/> </wsdl:message> <wsdl:portType name="Arrays"> <!-- ... --> <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.java import localhost.axis.services.Calc.*; import javax.xml.rpc.holders.DoubleHolder; public class ClientStat { public static void main(String[] args) throws Exception { ArraysService service=new ArraysServiceLocator(); Arrays port=service.getCalc(); double[] x={1.5,2.5,2}; DoubleHolder mean=new DoubleHolder(); DoubleHolder var=new DoubleHolder(); port.meanVar(x,mean,var); System.out.println(mean.value); System.out.println(var.value); } }

Services Web SOAP en Java p.25/71

Services Web SOAP en Java p.26/71

Requte
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; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.1RC2 Host: localhost Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 696 <?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> <ns1:meanVar soapenv:encodingStyle="http://schemas.xmlsoap.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.xmlsoap.org/soap/encoding/"> <item>1.5</item> <item>2.5</item> <item>2.0</item> </x> <mean xsi:type="xsd:double">0.0</mean> <var xsi:type="xsd:double">0.0</var> </ns1:meanVar> </soapenv:Body> </soapenv:Envelope>
Services Web SOAP en Java p.27/71

Requte
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Rponse e HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Date: Thu, 01 May 2003 10:05:14 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> <ns1:meanVarResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://localhost:8080/axis/services/Calc"> <mean xsi:type="xsd:double">2.0</mean> <var xsi:type="xsd:double">0.25</var> </ns1:meanVarResponse> </soapenv:Body> </soapenv:Envelope>

Services Web SOAP en Java p.28/71

Traduction des types


Loutil de traduction WSDL vers Java doit engendrer une classe pour chaque lment type dni dans le WSDL (la classe porte le mme nom que le type) engendrer une classe Holder pour chaque type spcique utilis comme paramtre ou ou inout dans une opration chaque espace de noms dni dans le document WSDL doit tre associ un package Java : si par exemple le document dnit plusieurs espaces de noms, la traduction doit donc produire plusieurs packages

Traduction des portTypes


Loutil de traduction WSDL produit une interface pour chaque portType du WSDL : portant le nom du portType drive de Remote proposant une mthode par operation qui reprsente le serveur sur le client exemple : Arrays.java
1 2 3 4 5 6 7 8 9 10 package localhost.axis.services.Calc; public interface Arrays extends java.rmi.Remote { public double[] sum(double[] x, double[] y) throws java.rmi.RemoteException; public void meanVar(double[] x, javax.xml.rpc.holders.DoubleHolder mean, javax.xml.rpc.holders.DoubleHolder var) throws java.rmi.RemoteException; }

Services Web SOAP en Java p.29/71

Services Web SOAP en Java p.30/71

Traduction des bindings


Loutil de traduction WSDL produit pour chaque binding une classe concrte : de nom name Stub qui implmente linterface associe au portType quincarne le binding qui traduit les appels locaux en messages SOAP et les rponses du serveur (messages SOAP) en rponse locale exemples : CalcSoapBindingStub implmente Arrays EchoSoapBindingStub implmente Echo etc. transparent pour le programmeur (ne sutilise pas directement)

Traduction des services


Loutil de traduction WSDL produit pour chaque service : une interface : de nom name Service qui propose une mthode get pour chacun des ports regroups dans le service exemple : Arrays.java
1 2 3 4 5 6 7 8 9 10 11
package localhost.axis.services.Echo; public interface EchoService extends javax.xml.rpc.Service { public java.lang.String getEchoAddress(); public localhost.axis.services.Echo.Echo getEcho() throws javax.xml.rpc.ServiceException; public localhost.axis.services.Echo.Echo getEcho(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; }

une classe : de nom name ServiceLocator spcique Axis implmentation de linterface name Service
Services Web SOAP en Java p.32/71

Services Web SOAP en Java p.31/71

Gestion des erreurs


Exemple : un service de calculs proposant le port Calc type de port Arrays opration sum : prend comme paramtre deux tableaux de double renvoie le tableau somme des paramtres client incorrect (tableaux de tailles diffrentes) :
1 2 3 4 5 6 7 8 9 10 11 12 13
Client.java import localhost.axis.services.Calc.*; public class Client { public static void main(String[] args) throws Exception { ArraysService service=new ArraysServiceLocator(); Arrays port=service.getCalc(); double[] x={1.5,2.5,3}; double[] y={1,-2}; double[] z=port.sum(x,y); for(int i=0;i<z.length;i++) { System.out.println(z[i]); } } }

Requte
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; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.1RC2 Host: localhost Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 789 <?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> <ns1:sum soapenv:encodingStyle="http://schemas.xmlsoap.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.xmlsoap.org/soap/encoding/"> <item>1.5</item><item>2.5</item><item>3.0</item> </in0> <in1 xsi:type="soapenc:Array" soapenc:arrayType="xsd:double[2]" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <item>1.0</item><item>-2.0</item> </in1> </ns1:sum></soapenv:Body> </soapenv:Envelope>
Services Web SOAP en Java p.34/71

Services Web SOAP en Java p.33/71

Rponse (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.1 500 Erreur Interne de Servlet Content-Type: text/xml; charset=utf-8 Date: Thu, 01 May 2003 06:37:42 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> <soapenv:Fault> <faultcode>soapenv:Server.userException</faultcode> <faultstring>java.lang.ArrayIndexOutOfBoundsException: 2</faultstring> <detail/> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope>

Un exemple complet
Service : requtes DNS implment en .NET modle document (pas RPC) propos par www.esynaps.com WSDL assez complexe : 264 lignes binding POST et GET

Le client traduit le Fault en une RemoteException


Services Web SOAP en Java p.35/71 Services Web SOAP en Java p.36/71

Code engendr
Le service :
1 2 3 4 5 6 7 8 9
package org.tempuri; public interface YourHost extends javax.xml.rpc.Service { public java.lang.String getYourHostSoapAddress(); public org.tempuri.YourHostSoap getYourHostSoap() throws javax.xml.rpc.ServiceException; public org.tempuri.YourHostSoap getYourHostSoap(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; } YourHost.java

Types engendrs (fragments)


HostInfo.java

Le port :
YourHostSoap.java

1 2 3 4 5 6 7 8 9 10

package org.tempuri; public interface YourHostSoap extends java.rmi.Remote { public org.tempuri.HostInfo whoAmI() throws java.rmi.RemoteException; public org.tempuri.HostInfo getHostInfoByIP(java.lang.String IPAddress) throws java.rmi.RemoteException; public org.tempuri.HostInfo getHostInfoByName(java.lang.String name) throws java.rmi.RemoteException; }

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.tempuri; public class HostInfo implements java.io.Serializable { private java.lang.String name; private org.tempuri.ArrayOfString IPList; private org.tempuri.ArrayOfString1 aliases; private java.lang.String error; public HostInfo() { } public java.lang.String getName() { return name; } public void setName(java.lang.String name) { this.name = name; } public org.tempuri.ArrayOfString getIPList() { return IPList; } public void setIPList(org.tempuri.ArrayOfString IPList) { this.IPList = IPList; } public org.tempuri.ArrayOfString1 getAliases() { return aliases; }

Services Web SOAP en Java p.37/71

Services Web SOAP en Java p.38/71

Types engendrs (fragments) (2)


26 27 28 29 30 31 32 33 34
HostInfo.java public void setAliases(org.tempuri.ArrayOfString1 aliases) { this.aliases = aliases; } public java.lang.String getError() { return error; } public void setError(java.lang.String error) { this.error = error; }

Types engendrs (fragments) (3)


ArrayOfString.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.tempuri; public class ArrayOfString implements java.io.Serializable { private java.lang.String[] IPAddress; public ArrayOfString() { } public java.lang.String[] getIPAddress() { return IPAddress; } public void setIPAddress(java.lang.String[] IPAddress) { this.IPAddress = IPAddress; } public java.lang.String getIPAddress(int i) { return IPAddress[i]; } public void setIPAddress(int i, java.lang.String value) { this.IPAddress[i] = value; }

Services Web SOAP en Java p.39/71

Services Web SOAP en Java p.40/71

Types engendrs (fragments) (4)


ArrayOfString1.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.java import org.tempuri.*; public class Client { public static void print(String[] str) { if(str != null) { for(int i=0;i<str.length;i++) { System.out.println(\t+str[i]); } } else { System.out.println("nant"); e } } public static void main(String[] args) throws Exception { YourHost service=new YourHostLocator(); YourHostSoap port=service.getYourHostSoap(); HostInfo info=port.getHostInfoByName(args[0]); System.out.println("Nom : "+info.getName()); ArrayOfString ips=info.getIPList(); System.out.println("Adresse(s) IP :"); print(ips.getIPAddress()); ArrayOfString1 aliases=info.getAliases(); System.out.println("Alias :"); print(aliases.getAlias()); } }

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.tempuri; public class ArrayOfString1 implements java.io.Serializable { private java.lang.String[] alias; public ArrayOfString1() { } public java.lang.String[] getAlias() { return alias; } public void setAlias(java.lang.String[] alias) { this.alias = alias; } public java.lang.String getAlias(int i) { return alias[i]; } public void setAlias(int i, java.lang.String value) { this.alias[i] = value; }

Services Web SOAP en Java p.41/71

Services Web SOAP en Java p.42/71

Excution
1 2 3 4 5 6 7 8 9 10 11 12

Requte
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.asmx HTTP/1.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.1RC2 Host: www.esynaps.com Cache-Control: no-cache Pragma: no-cache SOAPAction: "http://tempuri.org/GetHostInfoByName" Content-Length: 374 <?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> <GetHostInfoByName xmlns="http://tempuri.org/"> <Name>www.microsoft.com</Name> </GetHostInfoByName> </soapenv:Body> </soapenv:Envelope>

java Client www.microsoft.com Nom : www.microsoft.akadns.net Adresse(s) IP : 207.46.249.27 207.46.134.155 207.46.249.190 207.46.134.190 207.46.134.222 207.46.249.222 Alias : www.microsoft.com

Services Web SOAP en Java p.43/71

Services Web SOAP en Java p.44/71

Rponse
Rponse e

Programmation dun service


Avec Axis : Axis est une application web et sinstalle donc dans un serveur JSP/Servlet Instant Deployment : mcanisme (spcique Axis) permettant de se contenter de copier une classe un emplacement spcique pour obtenir le service correspondant ! Custom Deployment : mcanisme (spcique Axis) permettant de raliser des services plus complexes (i.e. ncessitant plusieurs classes par exemple) Problmes : trs spcique Axis implmentation basique : pas de persistance, pas de services de haut niveau, etc.

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.1 200 OK Server: Microsoft-IIS/5.0 Date: Wed, 30 Apr 2003 14:20:06 GMT Cache-Control: private, max-age=0 Content-Type: text/xml; charset=utf-8 Content-Length: 706 <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <GetHostInfoByNameResponse xmlns="http://tempuri.org/"> <GetHostInfoByNameResult> <Name>www.microsoft.akadns.net</Name> <IPList> <IPAddress>207.46.249.27</IPAddress> <IPAddress>207.46.134.155</IPAddress> <IPAddress>207.46.249.190</IPAddress> <IPAddress>207.46.134.190</IPAddress> <IPAddress>207.46.134.222</IPAddress> <IPAddress>207.46.249.222</IPAddress> </IPList> <Aliases> <Alias>www.microsoft.com</Alias> </Aliases> </GetHostInfoByNameResult> </GetHostInfoByNameResponse> </soap:Body> </soap:Envelope>

Services Web SOAP en Java p.45/71

Services Web SOAP en Java p.46/71

Solution volue
Avenir pour limplmentation en Java : exposer un Entreprise Java Bean en tant que web service limitations : Stateless Session Bean prvu dans J2EE 1.4 (qui nexiste pas encore ofciellement !) version basique des services web (problme dintgration avec les mcanismes de scurit, les transactions, etc.) avantages : on rcupre toute la puissance des EJB possible avec Axis ds maintenant
1 2 3 4 5 6 7 8 9

Exemple dInstant Deployment


programme Java : Calendrier.java import java.util.Calendar; import java.util.Date; public class Calendrier { public Calendar getDate() { Calendar result = Calendar.getInstance(); result.setTime(new Date(System.currentTimeMillis())); return result; } } recopier sous le nom Calendrier.jws dans un dossier particulier (cf la doc Axis) le web service est cr : dploy lURL http://localhost:8080/axis/Compteur.jws WSDL accessible lURL
http://localhost:8080/axis/Compteur.jws?wsdl

si on modie le chier .jws, le web service est mis jour automatiquement (recompilation et production du .wsdl)
Services Web SOAP en Java p.47/71 Services Web SOAP en Java p.48/71

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.wsdl <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/axis/Calendrier.jws" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://localhost:8080/axis/Calendrier.jws" xmlns:intf="http://localhost:8080/axis/Calendrier.jws" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.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.wsdl <wsdl:binding name="CalendrierSoapBinding" type="impl:Calendrier"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getDate"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="getDateRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/Calendrier.jws" use="encoded"/> </wsdl:input> <wsdl:output name="getDateResponse"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/Calendrier.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.jws"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
Services Web SOAP en Java p.50/71

Services Web SOAP en Java p.49/71

Exemple de client
1 2 3 4 5 6 7 8 9 10 11 12 Client import localhost.axis.Calendrier_jws.*; import java.util.Date; import java.util.Calendar; import java.text.DateFormat; public class Client { public static void main(String[] args) throws Exception { CalendrierService service=new CalendrierServiceLocator(); Calendrier port=service.getCalendrier(); Calendar now=port.getDate(); System.out.println(DateFormat.getDateInstance().format(now.getTime())); } }

Limitations de lInstant Deployment


pas de Java Beans pour le mapping de types volus code source obligatoire pas de matrise du cycle de vie : cration de lobjet destruction pas de contrle n : sur le chier WSDL engendr sur les mthodes exportes etc.

Services Web SOAP en Java p.51/71

Services Web SOAP en Java p.52/71

Cration
Avec lInstant Deployment, lobjet est recr chaque invocation : exemple :
Compteur.java 1 2 3 4 5 6 7 8 9 public class Compteur { private int compte; public Compteur() { compte = 0; } public int next() { return compte++; } }

Exemple de Custom Deployment


on reprend le mme programme on copie le chier compil (Compteur.class) un emplacement spcique (cf la doc Axis) on fabrique un chier WSDD : Web Service Deployment Descriptor spcique Axis exemple :
1 2 3 4 5 6 7

nouvel objet chaque appel : le compteur est toujours nul ! problmes : pas de persistance simple gaspillage de ressources (reconnexion une BD par exemple)
Services Web SOAP en Java p.53/71

deploy.wsdd <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.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 dun service, les mthodes exporter, etc.

Services Web SOAP en Java p.54/71

Exemple de Custom Deployment (2)


on excute java org.apache.axis.client.AdminClient deploy.wsdd le service est dploy : lURL http://localhost:8080/axis/services/Compteur WSDL : http://localhost:8080/axis/services/Compteur?wsdl pour supprimer le service, on utilise un autre chier WSDD : undeploy.wsdd
1 2 3 <undeployment xmlns="http://xml.apache.org/axis/wsdd/"> <service name="Compteur"/> </undeployment>

Java beans
On reprend lexemple de lannuaire : type Person :
Person.java

gestion du cycle de vie : sous-lment de service <parameter name="scope" value="value"/> lattribut value peut tre : request : un objet par requte (par dfaut) application : un seul objet par serveur session : un objet par session (extension Axis)
Services Web SOAP en Java p.55/71

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

package org.apiacoa.phonebook; public class Person { private String first; private String last; public void setFirst(String f) { first=f; } public String getFirst() { return first; } public void setLast(String f) { last=f; } public String getLast() { return last; } }

service :
1 2 3 4 5 6
package org.apiacoa.phonebook; public class PhoneBook { public int[] getPhoneNumber(Person p) { return new int[] {1,2,3}; } }

PhoneBook.java

Services Web SOAP en Java p.56/71

Dploiement
1 2 3 4 5 6 7 8 9 10
deploy.wsdd <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="PhoneBookWS" provider="java:RPC"> <parameter name="className" value="org.apiacoa.phonebook.PhoneBook"/> <parameter name="allowedMethods" value="*"/> <beanMapping qname="myNS:Person" xmlns:myNS="http://localhost:8080/axis/services/PhoneBookWS" languageSpecificType="java:org.apiacoa.phonebook.Person"/> </service> </deployment>

Types engendrs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 PhoneBookWS.wsdl <wsdl:types> <schema targetNamespace="http://localhost:8080/axis/services/PhoneBookWS" xmlns="http://www.w3.org/2001/XMLSchema"> <import namespace="http://schemas.xmlsoap.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>

chier WSDD :

beanMapping : qname : nom du type pour WSDL languageSpecificType : objet correspondant (attention au prxe java) mapping standard : une struct SOAP un champ par proprit du Java Bean

Services Web SOAP en Java p.57/71

Services Web SOAP en Java p.58/71

WSDL
engendr automatiquement au dploiement peut tre engendr avant : java org.apache.axis.wsdl.Java2WSDL ... permet de prciser certains lments : traduction package vers namespace emplacement du WS encoding (literal ou encoded) style (document ou RPC) etc. emplacement prcis par llment wsdlFile (ls de service)

Fonctions avances
mapping XML spcique : permet de transformer toute classe Java en XML et vice-versa demande la programmation des traductions ( !) Handlers : sintercale entre le serveur et le client peut modier les messages SOAP au vol applications : cryptographie, signature, compression, logging, etc. transport par messages ( la place de HTTP) bas sur JMS signature sessions (HTTP et header SOAP) attachments

Services Web SOAP en Java p.59/71

Services Web SOAP en Java p.60/71

Publication dun EJB comme service web


spcication EJB 2.1, J2EE 1.4 ne concerne que les Stateless Session Beans dj disponible dans divers produits : JOnAS 3.1 (dlicat congurer), bas sur Axis JBoss 3.2 : bas sur Axis dmarrer en mode all attention aux problmes de scurit diverses extensions pour la gestion de session, pour la scurit, etc. avec Axis : rien programmer (en plus des EJB) tout passe par WSDD Code de lEJB :
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.java package org.apiacoa.echo; import javax.ejb.CreateException; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; /** * 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; /** * @ejb:interface-method view-type="remote" **/ public String echo(String s) { return "Echo: "+s+"("+hashCode()+")"; }
Services Web SOAP en Java p.62/71

Services Web SOAP en Java p.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.java /** * @ejb:create-method view-type="remote" **/ public void ejbCreate() throws CreateException { System.out.println( "EchoBean: create" ); } public String toString() { return "EchoBean [ " + hashCode() + " ]"; } public void setSessionContext(SessionContext aContext) throws EJBException { mContext = aContext; } public void ejbActivate() throws EJBException { } public void ejbPassivate() throws EJBException { } public void ejbRemove() throws EJBException{ } }

XDoclet
Engendre le reste du code :
Echo.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 - Do not edit! */ package org.apiacoa.echo; import import import import import java.lang.*; javax.ejb.CreateException; javax.ejb.EJBException; javax.ejb.SessionBean; javax.ejb.SessionContext;

/** * Remote interface for Echo. * @xdoclet-generated at 6 mai 2003 14:27:42 */ public interface Echo extends javax.ejb.EJBObject { public java.lang.String echo( java.lang.String s ) throws java.rmi.RemoteException; }

Services Web SOAP en Java p.63/71

Services Web SOAP en Java p.64/71

XDoclet (2)
EchoHome.java

Fichier WSDD spcique


1 2 3 4 5 6 7 8 9 10 11 12 deploy.wsdd <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="EchoService" provider="java:EJB"> <parameter name="jndiURL" value="localhost"/> <parameter name="jndiContextClass" value="org.jnp.interfaces.NamingContextFactory"/> <parameter name="beanJndiName" value="ejb/org/apiacoa/echo/Echo"/> <parameter name="homeInterfaceName" value="org.apiacoa.echo.EchoHome"/> <parameter name="remoteInterfaceName" value="org.apiacoa.echo.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 - Do not edit! */ package org.apiacoa.echo; import import import import import java.lang.*; javax.ejb.CreateException; javax.ejb.EJBException; javax.ejb.SessionBean; javax.ejb.SessionContext;

/** * Home interface for Echo. Lookup using {1} * @xdoclet-generated at 6 mai 2003 12:21:40 */ public interface EchoHome extends javax.ejb.EJBHome { public static final String COMP_NAME="java:comp/env/ejb/Echo"; public static final String JNDI_NAME="ejb/org/apiacoa/echo/Echo"; public org.apiacoa.echo.Echo create() throws javax.ejb.CreateException, java.rmi.RemoteException; }

attention, il ne faut pas mettre * dans allowedMethods. on dploie (au sens web service) avec la commande :
java org.apache.axis.client.AdminClient -lhttp://localhost:8080/jboss-net/services/Administration deploy.wsdd

le service est accessible lURL


http://localhost:8080/jboss-net/services/EchoService
Services Web SOAP en Java p.65/71 Services Web SOAP en Java p.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.wsdl <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://localhost:8080/jboss-net/services/EchoService" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.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.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.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.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.wsdl <wsdl:binding name="EchoServiceSoapBinding" type="impl:Echo"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="echo"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="echoRequest"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/jboss-net/services/EchoService" use="encoded"/> </wsdl:input> <wsdl:output name="echoResponse"> <wsdlsoap:body encodingStyle="http://schemas.xmlsoap.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.68/71

Clients
1 2 3 4 5 6 7 8
Web services import localhost.jboss_net.services.EchoService.*; public class Client { public static void main(String[] args) throws Exception { EchoService service=new EchoServiceLocator(); Echo port=service.getEchoService(); System.out.println(port.echo(args[0])); } } EJB

Conseils pratiques
pas de solution portable pour la gestion de session : utiliser des stateless session beans grer la main la session, par exemple : une cl permanente par lutilisateur une cl temporaire cre par un mcanisme de login partir dune cl permanente transmettre linformation de session chaque appel par encore de solution portable pour la scurit : utiliser HTTPS ( ?) on peut envisager des wrappers web services construits la main (solution intrimaire)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

package test; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; import org.apiacoa.echo.*; public class Client { public static void main(String[] args) throws Exception { InitialContext context = new InitialContext(); EchoHome home = (EchoHome) PortableRemoteObject.narrow(context.lookup("ejb/org/apiacoa/echo/Echo"), EchoHome.class); Echo service = home.create(); System.out.println(service.echo(args[0])); } }

Services Web SOAP en Java p.69/71

Services Web SOAP en Java p.70/71

Conseils pratiques (2)


utiliser des Business Delegates : dnition : ensemble dinterfaces et de classes qui permet la couche de prsentation dutiliser la couche mtier design pattern standard en J2EE cache totalement au client le fait quil utilise un systme rparti sous forme dinterfaces, ce qui permet de changer limplmentation : une implmentation RMI classique (EJB) une implmentation locale (tests) une implmentation web service (rewall) etc.

Services Web SOAP en Java p.71/71