Vous êtes sur la page 1sur 21

Le but est de dvelopper des services Web avec des technologies Open Source.

Pour le dploiement des Web services, nous utilisons Tomcat (moteur de Servlet et de JSP) et Axis (une implmentation Java Open Source de SAOP). Vous aurez aussi la fin de ce document des informations sur XML-RPC Java qui est une technologie moins importante pour dvelopper des web services. Je vous rappelle que la technologie des Web services se base sur trois choses: 1) SOAP (le protocole d'change de messages XML (requtes et rponses) entre client et serveur 2) WSDL (Web Service Description Langage) est un langage reposant sur XML dont on se sert pour dcrire les services Web offerts. pour la description en XML. 3) UDDI annuaire des descriptions WSDL.

I) Tlchargement

Je vous conseille donc de tlcharger les versions binaires de tomcat et de axis partir respectivement des sites:
http://jakarta.apache.org/

http://ws.apache.org/axis/ Mais vous pouvez trouver par google des sites miroirs plus rapides. Ensuite lire les fichiers help attaches.

Dfinir certaines variables d'environnement


Mettre cela par exemple dans un fichier configuration Cela dpend du shell utilis. Je vous donne un exemple avec bash. Un exemple de ce fichier vous sera donn en TP. JAVA_HOME = LeCheminAVotreJDK LeCheminInstallationTomcat

CATALINA_HOME =

AXIS_HOME =LeCheminInstallationAxis PATH = ${PATH}:${HOME}/bin PATH PATH (ceci pour accder au bin local) (accs au bin de tomcat)

=${PATH}:${CATALINA_HOME}/bin =${PATH}:${JAVA_HOME}/bin

(accs au bin de java)

CLASSPATH = ${CLASSPATH}:. (on ajoute le rpertoire courant) Ajouter aussi dans le CLASSPATH tous les .jar du rpertoire ${AXIS_HOME}/lib

Ajouter ce quil faut pour utiliser XmlRpc Unsetenv XMLRPC_HOME setenv XMLRRPC_HOME CheminInstallationXmlRP setenv CLASSPATH ${CLASSPATH}:${XMLRPC_HOME}/*.jar remplaer * par ce quil faut. Par exemple mon fichier est : unset JAVA_HOME

JAVA_HOME=/usr/lib/jvm/java-1.6.0-openjdk export JAVA_HOME

unset CATALINA_HOME CATALINA_HOME=/usr/local/apache-tomcat-6.0.20 export CATALINA_HOME

AXIS_HOME=/usr/local/axis-1_4 export AXIS_HOME

# setenv MYSQL_HOME ${HOME}/WebServices/mysql

unset PATH

PATH=/usr/kerberos/bin:/usr/bin:/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/local/A crobat5/bin

# On ajoute tout cela PATH=${PATH}:${HOME}/bin PATH=${PATH}:${CATALINA_HOME}/bin PATH=${JAVA_HOME}/bin:${PATH}:. export PATH

# Pour Axis

CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/axis.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/jaxrpc.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/commons-discovery-0.2.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/saaj.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/commons-logging-1.0.4.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/log4j-1.2.8.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/wsdl4j-1.5.1.jar CLASSPATH=${CLASSPATH}:${AXIS_HOME}/lib/axis-ant.jar CLASSPATH=${CLASSPATH}:/usr/share/java/activation.jar

# CLASSPATH=${CLASSPATH}:/usr/xerces-2_5_0/xerces.jar

#CLASSPATH=${CLASSPATH}:/usr/xerces-2_5_0/xml-apis.jar #CLASSPATH=${CLASSPATH}:/usr/xerces-2_5_0/xmlParserAPIs.jar #CLASSPATH=${CLASSPATH}:/usr/xerces-2_5_0/xercesSamples.jat

export CLASSPATH

II) Lier Tomact et Axis

Copier le rpertoire axis qui se trouve dans ${AXIS_HOME}/webapps dans ${CATALINA_HOME}/webapps/. Ainsi le serveur axis est install comme une application Web au sein de tomact. Sous shell, il suffit de faire: $ cp ${AXIS_HOME}/webapps/axis ${CATALINA_HOME}/webapps/

Vous pouvez copier cela aussi en utilisant la souris.

Tester linstallation

lancer tomcat comme suit : $ startup.sh (si vous laviez dj ajoute dans le PATH sinon aller dans ${CATALINA_HOME}/bin ) Vrifier que tomcat tourne correctement dans un navigateur : http://localhost:8080 Valider prsent linstallation daxis en vrifiant que les paquetages obligatoires sont prsents: http://localhost:8080/axis
Ensuite, cliquer sur Validate

Le message suit doit apparatre

: The core axis librairies are present

III) Dveloppement et dploiement de services Web

Dveloppons prsent un service Web Simple que nous dploierons avec Axis. On va crer un service Web qui affiche un message de bienvenue lutilisateur. Ce service expose une mthode appele sayHello(). Cette mthode prend un argument String et retourne un message String au client. Nous allons donc crire une classe Java HelloService. public class HelloService { String SayHello(String argument) { return Hello+argument ; } Le dveloppement du service Web est ainsi termin : inutile de compiler ce code Java.

Comment Dployer ce service ?

Axis propose deux manires de dployer un service : 1) En utilisant un fichier JWS 2) En passant un fichier WSDD AdminClient (voir plus loin) La deuxime approche sera dtaille ultrieurement. La premire approche est beaucoup plus simple que la seconde, mais ne permet pas la personnalisation (ne pas exposer que certaines mthodes par exemple) du dploiement. JWS: JWS (Java Web Service) est une technologie dApache permettant dcrire rapidement un service web qui se dploie instantanment une fois la source mis dans un rpertoire particulier. Il suffit de copier HelloService.java dans ${CATALINA_HOME}/webapps/axis/ en le renommant HelloService.jws, sans compilation! Sous shell, il suffit de faire la commande. $ cp HelloService.java ${CATALINA_HOME}webapps/axis/HelloService.jws Cest fini votre Web service est prt et il est accessible avec l'URL: http://localhost:8080/axis/HelloService.jws Vous devez alors constater que votre service a t bien dploy sur "axis" en ayant en retour la page HTML suivante: There is a Web Service Here Click to see the WSDL Si vous cliquez sur ce lien, vous voyez la dfinition "WSDL" (gnr automatiquement par Axis de votre service Web). Si cette description napparat pas (sur certains navigateurs), vous pouvez toujours la stocker localement et la visualiser. La description WSDL est gnre la vole est maintenant accessible sous
http://localhost:8080/axis/HelloService.jws?wsdl

Cette description est utile pour tout client souhaitant accder au service en gnrant ou non les

stubs ncessaires. Analyser cette description et retrouver votre mthode et les paramtres et le point daccs (endpoint). Tester galement: http://localhost:8080/axis/index.html Cliquer sur view et que voit-on apparatre ?

IV) Excution du service Web IV-1) Sans dvelopper de client Java

Votre service est accessible travers tout le net. Dans un premier temps, on va excuter la mthode sayHello() sans crire de client Java, mais on aura uniquement des rponses SOAP. Pour excuter cette mthode et obtenir une rponse "SOAP" correspondante, il suffit de mettre l'URL suivante dans votre navigateur: http://localhost:8080/axis/HelloService.jws?method=sayHello Et pour passer un argument sayHello, faire: http://localhost:8080/axis/HelloServic?method=sayHello&argument="ouahidi" La rponse affiche est le contenu "SOAP", c'est dire un fichier XML. Sur certains navigateurs vous verrez : Hello ouahidi

IV-2) On va crire un client Java qui appelle note service Web.

On verra par la suite qu'il existe plusieurs manires. Ici on ne se sert pas de la dfinition WSDL pour gnrer le client. Voici une plus simple.

import org.apache.axis.client.*; import javax.xml.namespace.QName; public class TestHelloService{ public static void main(String[] args) { try { // Tomcat est lance par startup.sh sur la machine locale // Le port utilise est 8080 qui peut tre change dans server.xml (voir // $ {CATALINA_HOME}/conf/server.xml // enpoint est l'URL du serveur Web String endpoint ="http://localhost:8080/axis/HelloService.jws";

// On Cre l'objet service. Cela suppose que le client (call par la // suite) construit tous les paramtres et non pas les prend // partir de wsdl du serveur Service service = new Service(); // Contruction d'un objet call permettant de construire la requte et // // rponse SOAP Call call = (Call) service.createCall(); // On cre un objet associ a l'URL endpoint call.setTargetEndpointAddress(new java.net.URL(endpoint)); // On prcise la mthode excuter (ici on une seule) call.setOperationName("sayHello"); //On invoque avec les paramtres (tableau d'Object) et on reoit le //rsultat. String ret = (String) call.invoke(new Object[] {"Ouahidi"}); System.out.println(ret); } catch (Exception e) { System.err.println(e.toString()); } } }
Compiler et excuter.

$ javac TestHelloService.java $ java TestHelloService Hello ouahidi On verra dautres manires dcrire les clients. A prsent construisons un autre exemple avec toujours la mme manire de dploiement, cest dire avec un fichier JWS. Ecrire une super-calculatrice ayant les mthodes somme(int,int) et produit(int,int) pour l'instant (soyons modeste :) criture du service web : il s'agit de votre fichier CalculService.java (crit trs simplement : aucun import, pas d'hritage, etc...) Dploiement : il suffit de copier le fichier CalculService.java dans le rpertoire ${CATALINA_HOME}webapps/axis en le renommant en CalculService.jws class CalculService{ int somme (int a, int b) { return a+b ;} int produit(int a, int b){ return a*b ;} int soustration(int a, int b) {return a-b;}

Public Public Public public }

Excution travers un navigateur : Tester : http://localhost:8080/axis/CalculService.jws?wsdl Analyser sa description WSDL et retrouver les mthodes mtier, les paramtres, et le point d'accs (endpoint). http://localhost:8080/axis/CalculService.jws?method=somme&a=3&b=5 http://localhost:8080/axis/CalculService.jws?method=produit&a=3&b=5 Dveloppons un client Java
// Permet de tester CalculService.jws qui a trois mthodes somme et produit, et soustraction. // Ce fichier est mis dans ${CATALINA_HOME}/webapps/axis/CalculService.jws // Attention l'extension jws et non pas java import org.apache.axis.client.Call; import org.apache.axis.client.Service; import javax.xml.namespace.QName; public class TestCalculService{ public static void main(String[] args) { try { // enpoint est l'URL du serveur Web String endpoint ="http://localhost:8080/axis/CalculService.jws"; Service service = new Service();

Call call = (Call) service.createCall(); call.setTargetEndpointAddress(new java.net.URL(endpoint)); // On prcise la mthode excuter est somme call.setOperationName("somme"); // On invoque avec les paramtres (tableau d'Objet) et on // reoit le rsultat. //les deux entiers Integer i = new Integer(5); Integer j = new Integer(7); Integer ret = (Integer) call.invoke(new Object[] {i,j}); System.out.println("Somme = "+ret.intValue()); // lautre mthode si lon veut // On prcise la mthode a excuter est produit call.setOperationName("produit"); // On invoke ret = (Integer) call.invoke(new Object[] {i,j}); System.out.println("produit = "+ret.intValue()); = "+ret.intValue()); } catch (Exception e) { System.err.println(e.toString()); } } }

V) Approche WSDD

On va maintenant aborder une autre approche de dploiement des services web. Le fichier JWS offre le moyen le plus rapide et le plus simple de dployer un service Web sous Axis. Il ne permet cependant pas de personnaliser le dploiement. En outre, il laisse le code source sur le serveur disposition dventuels pirates et ne permet pas de dcider dune expression slective de certaines mthodes. Pour ce faire, Axis propose une manire de personnaliser le dploiement: WSDD (Web Service Delloyment Descriptor), le descripteur de dploiement de service Web. Le WSDD est un document XML (toujours lui). Il contient les informations sur le service Web dployer et spcifier le nom de la classe du service Web, la liste des mthodes exposer, etc. Voici les tapes: a) Ecrire un fichier.wsdd On compile HelloService.java et on met la classe HelloService.class dans le rpertoire ${CATALINA_HOME}/webapp/axis/WEB-INF/classes Le contenu du fichier (DeployHello.wsdd) de dploiement de notre exemple HelloService.java est le suivant : <!-- Inclure les espaces de noms --> <deployment

xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/jav a"> <service name="HelloService" provider="java:RPC"> <parameter name="className" value="HelloService"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> Un peu dexplications de ce fichier, mme si je vous conseille dans un premier temps de ne pas trop se focaliser sur les dtails. Nanmoins, pour avoir plus de dtails, tlcharger un tutoriel sur Axis. Llment XML <deployment> inclut les espaces de noms (pour viter les ambiguts, voir cours ) ncessaires. Llment <service> spcifie les dtails du service dployer. Dans llment <service> prcdent, name spcifie lURI du service dploy et provider dsigne le handler qui appelle lobjet rel de la classe du service. Dans notre exemple, nous utilisons java:RPC, qui est de la class org.apache.axis.providers.RPCProvider, comme fournisseur. Il existe dautre fournisseur comme java:MSG pour les services messageries. Dans llment <service>, nous spcifions les paramtres en utilisant la balise <parameter>. ClassName sert spcifier la class Java qui fournit le service souhait. Le nom de la classe est donn par la valeur value du paramtre. Le fichier .class de cette class doit se trouver dans le rpertoire ${CATALINA_HOME}/webapps/axis/WEBINF/classes. Cest dire HelloService.class est mettre dans ce rpertoire. Ensuite nous spcifions, le paramtre AllowedMethods. Celui-ci indique les mthodes exposer au monde extrieur (cest bien une personnalisation). Le symbole * dans le champ value indique que toutes les mthodes sont exposes au monde extrieur. Il est galement possible de spcifier une liste de mthodes spares par des espaces, voir lexemple du service CalculService.java. b) Utilisation de lutilitaire AdminClient AdminClient est utilitaire fournit par Axis qui lit le fichier WSDD et dploie le service Web. Pour le lancer il suffit de taper au niveau shell : $ java org.apache.axis.client.AdminClient DeployHelloService.wsdd On doit avoir apparatre les messages : -Processing file DeployHelloService.wsdd <Admin> Done Processing </Admin>

Vous pouvez constater que ce service s'affiche effectivement dans la liste des services web dploys : http://localhost:8080/axis/servlet/AxisServlet Tester le dploiement : http://localhost:8080/axis/services/HelloService, dcouvrez la description wsdl : http://localhost:8080/axis/services/HelloService?wsdl Retirer le service (undeploy) : c) Dveloppement dun client Java Il suffit de changer dans les exemples de client JAVA prcdent:
par String endpoint ="http://localhost:8080/axis/services/HelloService"; Ou par String endpoint ="http://localhost:8080/axis/servlet/AxisServlet"; call.setOperationName(new QName("HelloService","sayHello")); String endpoint ="http://localhost:8080/axis/HelloService.jws";

Et de le compiler et excuter. Je rsume cette approche: lcriture de la classe de service HelloService.java, la compiler et la placer dans ${CATALINA_HOME}/webapps/axis/WEB-INF/classes, criture du fichier de dploiement DeployHelloService.wsdd, lancer lutilitaire AdminClient, crire un client Java comme dans le cas JWS avec un changement de de lURL endpoint ou de lURL endpoint et le paramtre call.setOperationName() d) Un autre Exemple avec WSDD On va utiliser lexemple CalculService.java. Compiler ce fichier et placer la classe dans ${CATALINA_HOME}/axis/WEB-INF/classes. d-1) Le fichier DeployCalculService.wsdd <!-- Inclure les espaces de noms --> <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="CalculService" provider="java:RPC"> <parameter name="className" value="CalculService"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> $ Ou par exemple si l'on veut exposer uniquement somme et produit <!-- Inclure les espaces de noms --> <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="CalculService" provider="java:RPC">

<parameter name="className" value="CalculService"/> <parameter name="allowedMethods" value="somme,produit"/> </service> </deployment> d-2) AdminClient $ java org.apache.axis.client.AdminClient DeployCalculService.wsdd d-3) Client Java Il suffit de changer dans les exemples de client JAVA prcdent lURL endpoint par:
Ou par

String endpoint ="http://localhost:8080/axis/services/CalculService";

String endpoint ="http://localhost:8080/axis/servlet/AxisServlet"; call.setOperationName(new QName("CalculService","somme"));

Et de le compiler et excuter.

VI) Utilisation de l'utilitaire WSDL avec Axis

WSDL (document XML) dcrit linterface expose par un service Web. Il dcrit les diffrentes mthodes Web exposes par le service Web, ainsi que leurs paramtres et types retourns. Axis supporte WSDL de trois manires : a) Aprs avoir dploy le service, un document WSDL automatiquement gnr peut tre obtenu en accdant lURL du service partir dun navigateur Web standard et en attachant?wsdl la fin de lURL. b) Loutil WSDL2Java construit des proxies et des structures de services avec des descriptions WSDL. c) Un outil Java2WSDL construit WSDL partir de classes java. VI-1) Utilisation de WSDL2Java Le but est de crer un client par le bias des stubs (proxy) que lutilitaire WSDL2Java va gnrer. On va construire un service Web qui expose une mthode carre() qui retourne le carre dun entier pass en paramtre. La classe Java de cet est exemple est la suivante : public class Carre{ Public int carre(int a) { return a*a;} } Sauvegardons cette classe Carre.java dans ${CATALINA_HOME}/webapps/axis/ en la renommant Carre.jws. On peut ainsi rcuprer son WSDL comme auparavant (http://localhost:8080/axis/Carre.jws?wsdl) . Nommant ce fichier Carre.wsdl. Dans un scnario rel, lditeur du service Web peut placer ce fichier dans un annuaire. Pour gnrer les classes proxy partir de ce fichier WSDL, nous utilisons la commande

suivante:
$ java org.apache.axis.wsdl.WSDL2Java -p repertoire Carre.wsdl.

Quatre fichiers seront gnrs dans le package repertoire : Carre_PortType.java, CarreService.java,CarreServiceLocator.java,CarreSoapBindingStub .java Carre est une interface qui hberge les signatures des mthodes Web exposes par la service Web. Voici son code :
/** * Carre_PortType.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package reperoire; public interface Carre extends java.rmi.Remote { public int carre(int a) throws java.rmi.RemoteException; }

Rappelez vous les RMIs !!!!!!!!!!!!!! CarreService est une interface qui contient les signatures des mthodes utilises pour localiser le service. Le code de linterface est le suivant :
/** * CarreService.java * * This file was auto-generated from WSDL * by the Apache Axis WSDL2Java emitter. */ package repertoire; public interface CarreService extends javax.xml.rpc.Service { public java.lang.String getCarreAddress(); public repertoire.Carre_PortType getCarre() throws javax.xml.rpc.ServiceException; public repertoire.Carre_PortType getCarre(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; }

Les deux mthodes acqureurs retournent la rfrence au serveur. La premire mthode ne prend aucun argument, alors que la seconde accepte lURL du service comme argument. La classe CarreServiceLocator implmente linterface CarreService et fournit donc limplmentation des deux mthodes acqureurs. La classe CarreSoapBindingStub implmente linterface Carre_PortType. Cette classe dfinit lobjet Call et dfinit les paramtres ncessaires pour la mthode Web spcifie.

Le codes des classes CarreServiceLocator et CarreSoapBindingStub sont trop grands pour linclure dans le document. Cration dun client par la biais de stubs gnrs : Il est maintenant simple dcrire un programme qui utilise les classes que nous venons de gnrer. Voici son code : // Un client TestCarre qui utilise les proxy gnrs par WSDL // J'ai rcupr d'abord Carre.wsdl (comme dhabitude) // j'ai lanc java org.apache.axis.wsdl.WSDL2Java p repertoire // Carre.wsdl
// Ca m'a gnr un package repertoire qui contient // 1) Carre.java contient une interface de proxy du service Web. // des mthodes exposes par le serveur. // 2) CarreService.java. est une interface qui contient les signatures des //mthodes utilises pour localiser le serveur Web. // Deux mthodes qui retournent la rfrence au serveur. La //premire ne prend aucun argument. Le deuxime accepte l'URL du service //comme argument // 3) la classe CarreServiceLocator implmente l'interface //CarreService.java // La classe CarreSoapBindingStub.java implmente l'interface Carre.java. //Cette class cre l'objet Call et dfinit les paramtres //ncessaires pour la mthode Web spcifie. import repertoire.*; public class TestCarre{ public static void main (String [] args) { // crer une instance sur la classe de localisation CarreServiceLocator locator= new CarreServiceLocator(); try { Carre_PortType server =locator.getCarre(); int } a = server.carre(4);

System.out.println("Resulat "+ a); catch(java.lang.Exception e) { e.printStackTrace();}

} }

Un deuxime exemple. Rcuprer le wsdl de CalculService.java La classe de ce service


public public public public } public CalculService{ int somme (int a, int b){return a+b;} int produit (int a, int b){return a*b;} int difference (int a, int b){return a-b;}

$ java org.apache.axis.wsdl.WSDL2Java p repertoire CalculService.wsdl // La client // Ce fichier je l'ai crer pour teste WSDL2Java // J'ai rcuprer d'abord CalculService.wsdl // j'ai lanc java org.apache.axis.wsdl.WSDL2Java -p repertoire //CalculService.wsdl // Ca m'a gnr un package appel repertoire // Ce package contient: // 1) CalculService.java contient une interface de proxy du service Web. Le //proxy hberge des mthodes exposs par le serveur. // 2) CalculServiceService.java. est une interface qui contient les //signatures des mthodes utilises pour localiser le serveur Web. // Deux mthodes qui retournent la rfrence au serveur. La premire ne //prend aucun argument. Le deuxime accepte l'URL du service comme //argument // 3) la classe CalculServiceServiceLocator implmente l'interface //CalculServiceService // 4) La classe CalculServiceSoapBindingStub.java implmente l'interface //CalculService.java. Cette class Cree l'objet Call et dfinit les //paramtres ncessaires. // // // // j'ai dans classpath jusqu'a pere de repertoire On import les classe du repertoire java est capabable d'aller jusqu'au repertoire pere de repertoie mais apres il faut importer les classes

import repertoire.*; public class TestCalculService{ public static void main (String [] args) { // crer une instance sur la classe de localisation // Pour pouvoir localiser le serveur Web CalculServiceServiceLocator locator= new CalculServiceServiceLocator(); try { // retourne la rfrence du serveur Web CalculService server =locator.getCalculService(); // jappelle la mthode somme int a = server.somme(4,5); System.out.println("somme "+ a); // jappelle la mthode produit int b= server.produit(4,5); System.out.println("produit "+ b); // jappelle la mthode soustraction int c= server.soustraction(4,5); System.out.println("soustraction "+ c); }

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

VI-2) Utilisation de Java2WSDL Lutilitaire Java2WSDL permet de gnrer WSDL partir de la classe. Considrons lexemple dj tudi Carre.java. a) Compiler cette classe b)#java org.apache.axis.wsdl.Java2WSDL -o http://localhost:8080/axis/services/Carre -n "urn:Carre" Carre Gnre le fichier Carre.wsdl et place le service la place indique. La liste suivante donne la signification de chaque option utilise : -o: Nom de fichier WSDL -l: Emplacement du service - : Espace de noms cible du chichier WSDL. Visualiser le fichier produit Carre.wsdl Carre.wsdl -l

VI) Apache XML-RPC


XML-RPC est un protocole RPC bas sur XML. Il sagit dune spcification et dun jeu dimplmentation qui permettent aux logiciels sexcutant sur des systmes disparates, dans des environnements diffrents, deffectuer des appels de procdures sur Internet. Cela conduit effectuer des appels de procdures distants via HTTP POST pour ce qui est du transport et XML pour ce qui est du codage. XML-RPC a t conu pour tre aussi simple que possible, tout en autorisant les transmissions, le traitement et les retours de structures de donnes complexes. Une procdure sexcute sur le serveur et la valeur quelle retourne est galement formate en XML. Les paramtres de procdures peuvent tre des scalaires, des nombres, des chanes, des dates, ainsi que des structures denregistrements et de listes. Apache XML-RPC est une implmentation Java de XML-RPC. Elle propose la classe org.apache.XmlRpc qui permet de crer des applications clients en utilisant les appels XMLRPC sur un serveur distant. Un client peut appeler les mthodes distantes de manires synchrone ou asynchrone. Nous illustrons ces deux mthodes. Pour commencer tlcharger XML-RPC partir du web http://ws.apache.org/xmlrpc/download.html et installer ce logiciel et mettre jour votre CLASSPATH. Je vous conseille avant de commencer programmer les deux exemples suivants de consulter la page http://ws.apache.org/xmlrpc/apidocs/index.html 1) Premier Exemple de Service Web Le premier service web permet dexposer une mthode sumAndDifference qui prend deux entiers en paramtres et retourne la somme et la diffrence.

import java.util.Hashtable; import org.apache.xmlrpc.WebServer; public class ServeurSomDiff { public ServeurSomDiff () { // Cest un objet ordinaire. Il peut avoir un constructeur //et des variables. Les mthodes public sont exposes aux // clients. } // On a besoin de Hashtable car deux valeurs de retours // La mthode expose du serveur public Hashtable sumAndDifference (int x, int y) { Hashtable result = new Hashtable(); result.put("somme", new Integer(x + y)); result.put("difference", new Integer(x - y)); return result; } public static void main (String [] args) { try { // Invoke me as <http://localhost:8000/RPC2>. //On cre un objet server qui recevra les requtes pour // notre web service, il coute le port 8000. WebServer server = new WebServer(8000); // on lie la chane SOMDIFF au serveur ServeurSomDiff() server.addHandler("SOMDIFF", new ServeurSomDiff()); // On lance le serveur server.start(); System.out.println("Serveur lance sur http://localhost:8000/RPC2"); } catch (Exception exception) {System.err.println("JavaServer: " + exception.toString());

} } } Commentaire : La mthode main() cre une instance de la classe WebServer qui coute le port 8000 dans lattente de requtes clientes et cre un handler appel SOMDIFF que les clients utilisent pour appeler une mthode sur le serveur. La classe WebServer est fournit par la package XML-RPC org.apache.xmlrpc que nous avons import. Compiler et excuter le serveur. On va maintenant crire un client Java. Deux manires : un client synchrone, ou un client asynchrone. Un client synchrone.
// Un client Synchrone bloqu jusqu'a ce que le serveur retourne le //rsultat

import java.util.Vector; import java.util.Hashtable; import org.apache.xmlrpc.*; public class SynClientSomDiff { // serveur_url lURL de localisation du serveur private final static String server_url = "http://localhost:8000/RPC2"; public static void main (String [] args) { try { // Cration dun objet reprsentant le serveur. XmlRpcClient server = new XmlRpcClient(server_url); // Construction de la liste des paramtres Vector params = new Vector(); params.addElement(new Integer(5)); params.addElement(new Integer(3)); // Appel du serveur et rception du rsultat
Hashtable result=(Hashtable) server.execute ("SOMDIF.sumAndDifference", params);

// Rcupration du rsultat partir du Vector int sum = ((Integer) result.get("somme")).intValue(); int difference = ((Integer) result.get("difference")).intValue(); // Affichage des rsultats System.out.println("Somme: " + Integer.toString(sum) + System.out.println(Difference: " + Integer.toString(difference)); } catch (XmlRpcException exception) { System.err.println("JavaClient: + Integer.toString(exception.code) + ": " + exception.toString()); } catch (Exception exception) { System.err.println("JavaClient: " + exception.toString()); } } }

Commentaire : Notez que nous avons spcifi lURL du serveur comme paramtre du constructeur de classe XmlRpcClient. Ensuite, nous crons un objet Vector qui va stocker les paramtres passer aux mthodes de class du serveur. Lun des types de paramtres de la mthode du serveur execute() doit tre un Vector. La mthode sumAndDifference() du serveur est appel via la mthode execute(). Cet appel indique au serveur le nom de la mthode comme premier paramtre et sa liste de

paramtres (voil pourquoi nous avons employ un Vector) comme second paramtre. La valeur retourne par la mthode du serveur est assigne une variable Hastable. Un client asynchrone
// Un client asynchrone qui n'attend pas le retour import java.util.Vector; import java.util.Hashtable; import org.apache.xmlrpc.*; public class AsynClientSomDiff { private final static String server_url = "http://localhost:8000/RPC2"; public static void main (String [] args) { try { XmlRpcClient server = new XmlRpcClient(server_url); Vector params = new Vector(); params.addElement(new Integer(5)); params.addElement(new Integer(3));
server.executeAsync("sample.sumAndDifference", params, new AsynCallHandlerSomDiff()); /

du serveur

for (int i=0; i<2000; i++) System.out.print(*."); } catch (Exception exception) { System.err.println("JavaClient: " + exception.toString()); } } }

/ des * sont affiches en attendant le rsultat

2)

Deuxime exemple

Nous allons dvelopper une application serveur simple qui retourne au client un prix daction correspondant au code de laction (symbole). Pour que cette application reste simple, nous avons fait appel une table de hachage Hashtable qui contient les symboles boursiers et leurs prix. Voici le code complet du programme :
import java.util.Hashtable; import org.apache.xmlrpc.*; public class ServeurQuote { Hashtable StockesQuotes; // le constructeur de cette classe initialise cette Hashtable public ServeurQuote () { StockesQuotes = new Hashtable (); StockesQuotes.put ("SUN", new Double(120.00)); StockesQuotes.put ("IBM", new Double(1460.00)); StockesQuotes.put ("AIRFRANCE", new Double(1745.00)); } // La mthode GetStockPrice() prend un symbole boursier comme paramtre

et //retourne le cours actuel de laction lappelant. public Double getStockPrice(String symbole) { return (Double) (StockesQuotes.get(symbole)); } public static void main (String [] args) { try { //le serveur doit tre invoqu par http://localhost:8000/RPC2. // Une instance de la classe WebServer est cre et coute sur le port 8000 WebServer server = new WebServer(8000); // Un handler appel STOCK est cre. Ce handler sera utilis par le client //pour appeler une mthode sur le serveur. server.addHandler("STOCK", new ServeurQuote()); // lancer le serveur server.start(); System.out.println(" A invoquer sur http://localhost:8000/RPC2"); } catch (Exception exception) { System.err.println("JavaServer: " + exception.toString()); }

} }

Un client synchrone
import java.util.Vector; import java.util.Hashtable; import org.apache.xmlrpc.*; public class SynClientQuote { private final static String server_url = "http://localhost:8080/RPC2"; public static void main (String [] args) { if (args.length!=1) { System.out.println("Usage=> java JavaClient2 <StockSymole>"); System.exit(0);} try { XmlRpcClient server = new XmlRpcClient(server_url); // Construction des paramtres Vector params = new Vector(); params.addElement(args[0]); Double price = (Double) server.executeAsync("STOCK.getStockPrice",params); // DecimalFormat df = new DecimalFormat("##.00"); // afficher le resultat System.out.println("Le prix est : "+ price.doubleValue()+"$"); } catch (XmlRpcException exception) { System.err.println("JavaClient: XML-RPC Fault #" + Integer.toString(exception.code) + ": " + exception.toString()); } catch (Exception exception) { System.err.println("JavaClient: " + exception.toString()); }

} }

Ecrire un client Asynchrone.