Aller au contenu

Exercice 2 - Consommer un WS avec JAX-WS⚓︎

Commençons par créer un projet Web Java (archetype maven webapp-jakartaee10), que nous appellerons td9 (toujours dans le group id fr.univtours.polytech).

L'idée est ici d'intégrer le résultat de l'appel d'un WS dans notre application Web écrite en JEE.

On souhaite créer une application Web offrant un formulaire, dans lequel on indique dans un formulaire Web le code d'un pays, et qui renvoie la capitale du pays correspondant.

Choix runtime

Pour cela, nous allons avoir besoin de créer les couches suivantes :

  1. Couche présentation (vue) : Une JSP affichant un formulaire permettant d'indiquer le code du pays et affichant sa capitale lorsque le pays existe.
  2. Couche présentation (contrôleur) : Une servlet permettant
    • L'affichage de la JSP (GET).
    • L'exécution du WS et l'affichage de la JSP (POST).
  3. Couche métier : appel de du WS. Ici, notre WS correspond plus à un service qu'à un dao, on l'appelle donc depuis la couche métier, et il n'y a pas de couche dao dans notre appli. On aurait pu faire le choix de rajouter la couche dao, et d'appeler le WS depuis cette dernière.

Il va donc falloir créer tout le code Java permettant l'appel de ce WS et la récupération du résultat. Heureusement, tout cela est automatique ! C'est le principe du Contract First. Tout le code va être automatiquement généré à partir du WSDL.

Pour cela, il faut utiliser l'utilitaire wsimport, qui était fourni avec la JDK jusqu'à la version 1.8, mais dont l'utilisation nécessite maintenant un peu de configuration !

Configuration pour wsimport pour les JDK postérieurs à la 1.8

Dans le 📄pom.xml du projet, il faut ajouter des dépendances (notamment vers JaxB) :

📄pom.xml
<!-- Pour JaxB -->
<dependency>
    <groupId>jakarta.jws</groupId>
    <artifactId>jakarta.jws-api</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.2</version>
</dependency>
<dependency>
    <groupId>jakarta.xml.ws</groupId>
    <artifactId>jakarta.xml.ws-api</artifactId>
    <version>4.0.1</version>
</dependency>
<!-- Pour wsimport -->
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>4.0.2</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>4.0.2</version>
    <type>pom</type>
</dependency>

Toujours dans le 📄pom.xml, il faut également ajouter un plugin maven, avec deux informations à configurer :

📄pom.xml
<plugin>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-maven-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <wsdlUrls>
            <wsdlUrl>http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL</wsdlUrl><!-- (1)-->
        </wsdlUrls>
        <keep>true</keep>
        <packageName>fr.univtours.polytech.td9.business.country</packageName><!-- (2)-->
        <sourceDestDir>src/main/java</sourceDestDir>
    </configuration>
</plugin>
  1. On indique ici le WSDL à partir duquel on souhaite générer les objets Java.
  2. On indique ici dans quel package on souhaite les générer.

Enfin, pour générer toutes les sources Java, il suffit d'exécuter ce plugin. On le fait en exécutant la commande suivante, après s'être placé dans le dossier contenant ce 📄pom.xml :

mvn clean jaxws:wsimport
  • Comme indiqué plus tôt, le client SOAP va permettre d'implémenter un service, on place donc ces sources dans le package business.

  • Parfois, le client SOAP sera la source de données. Dans ce cas là, on pourra placer les sources dans le package dao.

  • De nombreuses classes peuvent être générées (c'est le cas ici - il y en a 58 normalement), afin de ne pas se mélanger avec le reste de l'application, on les places dans un sous package country.

Appeler le WS depuis la couche métier

Une fois les classes Java générées, il faut identifier celles qui vont nous permettre d'appeler le WS depuis notre code Java.

Il y a normalement une interface et une classe qui ont un nom proche de celui du WS. Ici, l'interface est CountryInfoServiceSoapType et la classe est CountryInfoService.

Pour appeler le WS, depuis notre couche business donc, voici le code qu'il faut écrire :

CountryInfoServiceSoapType ws = new CountryInfoService().getCountryInfoServiceSoap();

L'objet ws permet alors d'appeler toutes les méthodes (c'est-à-dire tous les services) disponibles.

Rappels - Architecture de l'application

Pour rappel,

  • La couche métier est composée d'une interface (CountryBusiness par exemple), et d'une classe l'implémentant (CountryBusinessImpl par exemple) avec l'annotation @Stateless.

    Cette couche ne propose qu'un seul service :

    public String getCapitalCity(String code);
    
  • Dans la servlet, il y a une dépendance vers l'interface métier, avec l'annotation @EJB.