Você está na página 1de 15

Web Services avec JBoss et ws4ee

Introduction
L'objectif de ce document est d'arriver à déployer un Web Service sous JBoss grâce à ws4ee. Ws4ee
utilise Axis mais le déploiement automatique demande une structure de fichier WAR particulière. Il
y a déjà beaucoup de tutoriels sur internet mais aucun ne m'a permis de comprendre l'intégralité du
développement jusqu'au déploiement.
Le but de ce document n'est pas d'expliquer le fonctionnement des Web Services dans le détails, j'en
suis d'ailleurs incapable. Le but est qu'un développeur habitué a faire du Java, soit capable en
suivant ce tutoriel de développer et de déployer un Web Service sous JBoss. Et accessoirement de
comprendre comment il y est parvenu.

Logiciels utilisés
● Eclipse WTP : http://www.eclipse.org/webtools/main.php
Il s'agit là d'une version d'Eclipse avec les PlugIns pour le développement d'applications
web pré-installé. Vous pouvez aussi essayé d'installer ces PlugIns à la main mais moi, j'y
suis pas arrivé.
● Java WSDP : http://java.sun.com/webservices/downloads/previous/index.jsp
Il s'agit la des librairie de développement web de Java. Je m'en suis servi pour générer les
fichiers wsdl et mapping.xml. On peut certainement faire autrement mais cette solution est
la seule qui marchait dans mon cas.
● Librairie Axis : http://ws.apache.org/axis/
Théoriquement, elle est déjà incluse avec la version WTP d'éclipse et vous n'aurez donc pas
a vous en préoccuper. Mais si vous en avez besoin, vous saurez où la trouver.

Voilà, on partira du principe que JBoss et Java sont déjà installé.


Eclipse est installé dans "C:\Program Files\eclipse", Java est installé dans "C:\Program Files\Java",
Wsdp est installé dans "C:\Program Files\Java\jwsdp-2.0"
Rq : J'ai ajouté un le NLPack d'éclipse pour l'avoir en français.
(http://download.eclipse.org/eclipse/downloads/#Language%20Pack)
Le tuto donne donc les noms de menu et d'écran en français (sauf s'il ne sont pas traduit).
Développement du Web Service
On va développer un WS basique qui du bonjour. C'est ce que l'on trouve le plus souvent dans les
tutoriel.

Paramétrage éclipse
Après le premier lancement d'éclipse, on va paramétrer un poil la bête histoire de se sentir plus à
l'aise.
Conseil, lors du démarrage il vous demande quel est le répertoire de l'espace de travail. Changez
celui par défaut pour un répertoire qui n'a pas d'espace dans le nom. Autrement, cela pose des
problèmes lors de l'utilisation de wscompile.
Allez donc dans Fenêtre > Préférences puis "Java > Chemin de génération"

A "Dossier source de sortie" changez pour "Dossiers" et laissez les valeurs. Eclipse va pour chaque
projet créer des sous-répertoires où il mettra les sources et le classes.
Création du projet
Une fois le paramétrage effectué, on va pouvoir créer le projet :
Choisissez "Fichier > Nouveau > Projet ..." puis dans la liste "Web > Dynamic Web Project"

Renseignez le nom du
projet puis faites
"Terminer".

A la demande d'acceptation de licence répondez "I Agree".

Développement du EndPoint
Déjà qu'est ce qu'un EndPoint ? Un EndPoint une l'URL donnant accès à un service par un protocol
spécifique. En gros, c'est un point d'accès à une classe Java ou plutôt à une classe dérivé d'une
interface qui étend la classe java.rmi.Remote.
(cf. http://www.w3.org/TR/ws-gloss/#endpoint)

Créez un nouveau package "bonjour" et à l'intérieur une interface "BonjourIF" qui ressemble à ça :
package bonjour;
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface BonjourIF extends Remote {


public String salutToi(String p_nom) throws RemoteException;
}
Puis on crée la classe "Bonjour" qui implémente cette interface :
package bonjour;
public class Bonjour implements BonjourIF {
public String salutToi (String p_name) {
return "Salut "+p_name+" !";
}
}

Je ne vais pas m'étendre sur l'écriture de la classe, c'est du Java standard. Toutes les fonctions
publiques de la classe seront visible dans le Web Service. (En réalité, les fonctions utilisables dans
le cadre du WS sont paramétrées dans le fichier wsdl).

Retourner des objet complexe


Voilà un problème auquel je viens de me retrouver confronté ! Dans certains cas, vous aurez besoin
de retourner des objets complexes. Dans une classe contenant un statut, un possible message
d'erreur et un tableau d'une autre classe. Ce qui rend la chose un poil plus compliqué.
Ce qu'il faut garder en tête c'est que les classes à retournés doivent être les plus simple possible.
Composés de variables membre, d'un constructeur par défaut et des getter et setter. Rien d'autre.
N'utilisez pas non plus de conteneur complexe comme variables membre, il ne sont pas compatible
avec JAX-RPC. Idem pour les constantes (private static final), elles ne seront pas prisent en compte
dans le WSDL et lors de la génération du client elle ne seront pas générées.

Si par exemple on veut que la fonction "salutToi" de notre WS retourne la liste des gens qui
répondent au bonjour avec leur nom et leur réponse (oui je sais, c'est débile mais c'est un exemple !)
on va avoir quelque chose comme ça :
package bonjour;
public class Bonjour implements BonjourIF {
public WSReponse salutToi (String p_name) {
return new WSReponse();
}
}

Commençons par créer la classe UneReponse avec les variables membres qui vont bien :
public class UneReponse {
private String nom;
private String reponse;

public UneReponse() {

}
}
On peut constater que la classe est dans un autre package "bonjour.types". Ca permettra de mieux
structurer et pour ceux qui vont faire le client, c'est plus facile à relire.
Ensuite, juste ça ne suffira pas pour pourvoir générer le WSDL. Donc on va vite fait bien fait
générer les getter & setter grâce à éclipse.
Pour cela on se positionne sur la
classe, puis on fait click-droit et
on va dans "Source > Générer les
methodes d'accés get et set..."

Ici, vous cochez tout les champs et


vous faites OK !

Vous avez alors tout les accésseurs nécessaires à votre classe pour quelle soit correctement
interprété par wscompile.
Passons maintenant à la classe WSReponse qui ressemble à ça une fois que les accésseurs sont créé
:
package bonjour.types;

public class WSReponse {


private String statut;
private String msgErreur;
private UneReponse[] lstResponses;

public WSReponse() {

public UneReponse[] getLstResponses() {


return lstResponses;
}

public void setLstResponses(UneReponse[] lstResponses) {


this.lstResponses = lstResponses;
}
public String getMsgErreur() {
return msgErreur;
}
public void setMsgErreur(String msgErreur) {
this.msgErreur = msgErreur;
}
public String getStatut() {
return statut;
}
public void setStatut(String statut) {
this.statut = statut;
}

On notera que j'ai volontairement utilisé un simple tableau plutôt qu'un Vector ou un ArrayList.
Pour des raison de compatibilités on n'utilisera pas de type complexe. En cherchant sur internet j'ai
vue que cela n'était pas impossible mais si, par exemple, vous créez un WS en Java avec ce genre de
classe, et que derrière quelqu'un veux développer un client en C++, l'utilisation de classe complexe
va poser des problème voir rendre cela impossible.

Voilà, maintenant que les classes de retour sont créer, il faut vous débrouiller avec les accésseur
pour remplir correctement vos champs. Ne créer pas d'autre fonction membre de ces classes, elles
ne seraient pas utilisables dans les clients générés à partir du wsdl. C'est pas toujours pratique mais
c'est comme ça :).
Empaquetage du Web Service dans un WAR
Ant
Ant est pour le Java ce que Make est pour le C++. Cela permet de créer des scripts de compilation
pour automatiser les actions fastidieuses et répétitives.
Justement, la génération de certains fichier XML ainsi que de certaines classe est une opération
relativement fastidieuse. On crée donc un script Ant pour générer automatiquement ces deux
fichiers xml et les classes à l'aide de wscompile (inclus dans Java WSDP).

Création des fichiers de déploiement


Bon bon, on a finit le plus facile. On va maintenant s'attaquer a générer les fichiers de déploiement.
C'est un palanqué de fichiers XML qui permettent a JBoss et Axis de déployer et mettre a
disposition le Web Service.

WSDL et mapping
Les premiers fichiers que l'ont va créer sont le fichier wsBonjour.wsdl et jaxrpc-mapping.xml.
Pour ce faire, on utilise wscompile, un utilitaire présent dans Java WSDP. Le truc c'est que
l'opération est un peu fastidieuse et que vous risquez de la reproduire un paquet de fois. On va donc
créer un script Ant.
Ant est à Java ce que Make est au C++. Cela permet de créer des script de compilation pour
automatiser les actions fastidieuses et répétitives.
J'ai testé plusieurs façon de créer le script et plusieurs syntaxes mais la seule chose qui ai bien
marché pour moi c'est de créer manuellement le fichier "wscompile.xml" dans le répertoire du
projet :
<?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="wscompile" name="wsBonjour">
<property name="build.webinf.dir" value="WebContent/WEB-INF" />
<property name="build.classes.dir" value="build/classes" />
<target name="wscompile">
<exec executable="wscompile.bat">
<arg line ="-verbose -cp ${build.classes.dir} -gen:server -f:
rpcliteral -d ${build.webinf.dir}/wsdl -mapping ${build.webinf.dir}/jaxrpc-
mapping.xml ${basedir}\wsconfig.xml"/>
</exec>
<move todir= "${build.classes.dir}">
<fileset dir = "${build.webinf.dir}/wsdl">
<exclude name="*.wsdl"/>
</fileset>
</move>
</target>
</project>

Ainsi que le fichier de configuration "wsconfig.xml" toujours dans le répertoire :


<?xml version="1.0" encoding="UTF-8"?>
<configuration
xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<service name="wsBonjour"
targetNamespace="http://localhost:8080/wsBonjour"
typeNamespace="http://localhost:8080/wsBonjour/types"
packageName="bonjour">
<interface name="bonjour.BonjourIF"
servantName="bonjour.Bonjour" />
</service>
</configuration>

Les paramètres du fichier de configuration sont les suivants :


● name : Nom du service
● targetNamespace : URL du EndPoint. Pas super important; c'est JBoss qui va se le gérer.
● typeNamespace : URL des types, idem, JBoss se la gère.
● PackageName : Nom du package contenant la classe du WS
● interface name : package.interface d'implementation du WS
● interface servantName : package.classe implémentant l'interface précédemment citée.

Concernant le script Ant, on s'assurera que "wscompil.bat" est bien accessible, sinon il faudra le
mettre dans la variable PATH de la machine.
Sur la ligne contenant les arguments de wscompile on retrouve :
● -cp <classpath> qui contient le classpath nécessaire pour générer les fichiers. On y met le
répertoire de sortie de nos classes.
● -gen:server qui indique que l'on génère la partie serveur du WS.
● -f:rcplitteral qui est l'encodage (enfin, je suis pas sur de moi sur celui là
● -d <rep de sortie> qui est le répertoire de sortie pour les fichiers générés
● -mapping <mapping.xml> qui est le nom du fichier de mapping a générer
● <wsconfig.xml> qui est le nom du fichier de configuration

Une fois que tout est prêt, clic droit sur "wscompile.xml" puis "Exécuter en tant que ... > Génération
Ant ..."
A la sortie de la génération, vous devez obtenir quelque chose qui ressemble a ça :

Les fichiers wsdl, mapping.xml et le répertoire


BonjourIFService ont été générés.
Le fichier wsBonjour.wsdl doit absoluement se
trouver dans WEB-INF/wsdl et jaxrpc-
mapping.xml doit se trouver dans WEB-INF.

Conseil : Les fichiers wsdl et mapping.xml


générés contient des entête avec des liens pour
la validation. En supprimant ces liens et ne
laissant que le paramètre version, JBoss met
moins de temps à les déployer.

Fichier web.xml
Celui ci est normalement déjà présent dans votre répertoire WEB-INF. Mais il n'est pas terrible
alors on va le modifier :

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


<web-app version="2.4">
<servlet>
<servlet-name>wsBonjourServlet</servlet-name>
<servlet-class>bonjour.Bonjour</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>wsBonjourServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

Ce fichier va servir a déclarer une servlet au niveau du serveur d'applications (je suis pas hyper sur
de ça). Donnez un nom à cette servlet, indiqué la classe correspondante.
Fichiers JBoss
Maintenant il ne nous reste plus que les fichiers JBoss.
Tout d'abord, le fichier jboss-web.xml

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


<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 2.2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web.dtd">
<jboss-web>
<!-- Resource references -->
<!-- EJB References -->
</jboss-web>

Je sais pas trop bien à quoi est ce qu'il sert celui là, il est quasi vide mais j'ai pas essayé sans.

Et enfin, le fichier "webservices.xml"

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


<webservices version="1.1">
<webservice-description>
<webservice-description-name>wsBonjour</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/wsBonjour.wsdl</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/jaxrpc-mapping.xml</jaxrpc-mapping-file>
<port-component>
<port-component-name>bonjour.Bonjour</port-component-name>
<wsdl-port>BonjourIFPort</wsdl-port>
<service-endpoint-interface>bonjour.BonjourIF</service-endpoint-
interface>
<service-impl-bean>
<servlet-link>wsBonjourServlet</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>

Ce fichier indique à JBoss que c'est un Web Services qu'il va déployer et lui donne la localisation
des différents fichier dont il aura besoin pour le déploiement.

Tout ces derniers fichier sont a créer manuellement dans le répertoire "WebContent\WEB-INF" de
votre projet.
Déploiement
Voilà, tous les fichiers sont créés et correctement rempli. Il ne reste plus qu'a déployer le WS. Pour
cela, vous faites un click droit sur le projet puis "Exporter...". Dans la liste choisissez "Web > WAR
file".
Ce que vous pouvez faire
c'est choisir directement
la destination du
répertoire de
déploiement de votre
JBoss. Sinon, il faudra
l'y copier manuellement.

Une fois que le fichier WAR s'y trouve, JBoss va faire tout le boulot :
15:29:38,288 INFO [TomcatDeployer] deploy, ctxPath=/wsBonjour,
warUrl=.../tmp/deploy/tmp36525wsBonjour-exp.war/
15:29:38,519 INFO [WSDLFilePublisher] WSDL published to: file:/C:/install/jboss-
4.0.3SP1/server/CCS/data/wsdl/wsBonjour.war/wsBonjour.wsdl
15:29:38,569 INFO [AxisService] WSDD published to: C:\install\jboss-
4.0.3SP1\server\CCS\data\wsdl\wsBonjour.war\bonjour.Bonjour.wsdd
15:29:38,579 INFO [AxisService] Web Service deployed: http://Albator:8080/wsBonjour

Si tout a marché comme prévu, en vous rendant a cette adresse :


http://localhost:8080/ws4ee/services

Vous devriez avoir quelque chose comme ça :

Sur certain tuto, vous trouverez des URL du genre


http://localhost:8080/wsBonjour?method=salutToi&p_name=Fred pour tester si votre WS
fonctionne. Dans notre cas, cette URL ne retourne jamais rien mais cela ne veut pas dire que le WS
ne fonctionne pas. Je pense que ws4ee ne gère pas ce mode d'appel.

Une fois votre WS déployé, il faut le tester. Pour cela, deux solutions :
● Développer un client qui va faire appel à celui ci. C'est un peu long si on est pressé et que
l'on a pas besoin de client par la suite.
● Utiliser ce merveilleux outil qu'est Eclipse pour tester que cela fonctionne bien.
Test du Web Service
Eclipse WTP dispose d'un outil plutôt très sympa pour tester un web service sans se faire chier à
faire un client. C'est le "Web Service Explorer" !
Donc allez dans "Run > Launch Web Service Explorer"

Voilà gromo-dosso ce que vous devriez avoir. Cliquez sur l'avant


dernier bouton en haut à droite de la fenêtre pour accéder à la partie de
test via WSDL

Vous rentrez l'adresse du WS


que JBoss vous a donné lors du
déploiement avec "?wsdl" pour
accéder au fichier wsdl !
(Ici les captures d'écran porte
sur un autre WS car il est plus
intéressant que wsBonjour et
qu'en plus, je n'ai plus les
sources de ce dernier).
Faites "Go"
Et la magie s'accomplit ! Nous avons la la liste des fonctions déployé pour le web service demandé.
Un clic sur l'une des fonctions permettra de la tester.
Rq: Si eclipse est configurer pour passer par un proxy et que votre WS est déployé en local, assurer
vous qu'éclipse n'utilisera pas le proxy pour accéder à votre machine. Pour configurer cela allez
dans "Fenêtre > Préférences > Internet > Proxy Settings".

Voici par exemple ce


que vous avez si vous
voulez tester une des
fonctions.
Vous renseignez les
valeurs, appuyez sur Go
et dans le section
inférieure le résultat
s'affiche.
Consommation du Web Service
Bon, là ya pas grand chose de compliqué !

Génération du Stub
Le Stub est l'ensemble des classes clientes pour l'appel à un web service. Elles sont
automatiquement générée grâce au fichier wsdl (Fichier de description que l'on a généré lors de la
création du web service). Si vous ne l'avez pas, il est toujours possible de le trouvé en tapant l'URL
http://localhost:8080/endpoint?wsdl .

Dans un nouveau projet, importez le fichier wsdl. Puis faites un clic droit sur celui-ci "Web
Services > Generate Client".

Descendez le curseur
jusqu'à "Develop
client" puis cliquez
sur "Terminer".
Si cela a bien fonctionné, vous avez une arborescence qui ressemble à ça :

Le générateur a automatiquement ajouté les


librairie Axis.

Création de la classe de consommation


Ajoutez une classe à votre projet :
clientBonjour.java
import localhost.wsBonjour.BonjourIF;
import localhost.wsBonjour.WsBonjourLocator;

public class clientBonjour {


public static void main(String[] args)throws Exception {
WsBonjourLocator w_service;
BonjourIF w_port;

// Création du service
w_service = new WsBonjourLocator();

// Changement de l'URL de endpoint


// Il est possible de ne rien mettre, dans ce cas, l'URL utilisé
// est celle paramétré automatiquement lors de la génération du
// fichier WsBonjourLocator.java
w_service.setBonjourIFPortEndpointAddress("http://albator:8080/wsBonjour");

// On récupère le port qui va bien pour faire les appels


w_port = w_service.getBonjourIFPort();

// Le port s'utilise maintenant comme une classe java standard


System.out.println(w_port.salutToi("Fred"));
}
}

Et voilà, en exécutant ça, vous allez avoir :


22 mai 2007 17:03:35 org.apache.axis.utils.JavaUtils isAttachmentSupported
ATTENTION: Unable to find required classes (javax.activation.DataHandler and
javax.mail.internet.MimeMultipart). Attachment support is disabled.
Salut Fred !

L'avertissement vient du fait que l'on a pas inclus la librairie mail.jar dans le classpath du projet.
C'est pas grave mais ça pourrait poser des problèmes selon les web services que l'on consomme. Il
suffira d'ajouter mail.jar dans la liste des librairies du projet pour que l'avertissement disparaisse.

Você também pode gostar