Créer des services web Soap simplement avec JAX-WS et Spring-Boot (part I)

jaxws-tutorialsSpring_framework

 

 

Je vais vous présenter dans cette série d'articles les étapes de création des web services soap (serveur et client). En partant sans aucun framework, juste l'API JAX_WS pour commencer. Puis on enchaîne avec Spring-Boot.

Cette série est divisée en trois parties bien distinctes:

  • La première partie, pour les novices, présente deux démos basées sur l'API JAX-WS 2.x ne nécessitant aucune connaissance préalable, si ce n'est un peu de culture sur les approches de développement (top-down ou bottom-up c'est à dire partir du contrat wsdl ou de classes java annotées).
    Vous verrez que les annotation faciliteront l'approche bottom-up utilisée dans les démos.
    Donc, nous commençons par un projet maven simple style HelloWorld, puis nous enchaînons avec un exemple un peu plus sérieux.
    Faisant de la sorte, nous écartons ainsi quelques difficultés avant d'entamer la suite.
    Vous notez que cette partie n'utilise pas Spring.
  • La seconde partie explique la création des web services soap réalisée (et facilitée) par Spring-Boot,
  • La troisième partie introduit la sécurisation de nos web services.

Sommaire

  • Introduction à JAX-WS
  • Partie 1: Deux projets JAX-WS 2.x démos simples,
  • Partie 2: Un projet démo avec Spring-Boot,
  • Partie3: Sécuriser les web services.

Les différents projets démos utilisent java 8. Nous n'abordons pas ici la comparaison des web services soap vs RestFul (ou jax_ws vs jaw-rs) car le sujet est abondamment traité sur le net.

Rappelons juste que, par exemple, JAX-WS (ou big web service) convient mieux à des scénarios d'intégration entreprise nécessitant un service QoS (Quality Of Service) avancé.

INTRODUCTION JAX-WS

JAX-WS ou Java API pour XML Web Services est une spécification permettant de construire des web services (services à travers protocole http) orientés messages ou orientés RPC (Remote Procedure Call) au format xml.
L'un des objectifs de l'API JAX-WS est de faciliter le développement des web services et de leurs clients consommateurs  avec le minimum de code puisque JAX-WS masque la complexité des messages SAOP (Simple Object Access Control). En effet, la spécification définit la structure d'un message sous forme enveloppe, ses règles, le modèle de données et les  conventions pour effectuer les appels (requêtes) et recevoir les réponses transmises via des formats XML par le protocole HTTP.

 WSDL ?

Le WSDL prononcé "whiz-deul" décrit l'interface d'accès aux services web, c'est une description en xml précisant comment utiliser le web service.

Sa description XML n'est pas forcément aisée pour l'être humain.
Or, à partir du moment où l'on souhaite communiquer avec les web services SOAP nous avons recourt au fichier WSDL qui nous permettra de générer les artifacts (en java ou autre langage) pour consommer ce web service (comme nous le ferons aux étapes 6 et 7 ci-après).

 

PREMIÈRE PARTIE

Dans la première partie, nous nous efforcerons d'expliquer les différents thèmes et annotations utilisés pour permettre aux novices d'en comprendre l'essentiel.

Voici pour permettre de bien suivre la première partie, les étapes à suivre:

  1. Créer un projet maven avec une seule dépendance jaxws-api 2.2.11,
  2. Déclarer une interface (SEI: Service Endpoint Interface) IHello annotée avec @WebServiceet @SOAPBinding,
  3. Déclarer l'unique méthode de cette interface annotée avec @WebMethod, @WebResult ou @WebParam,
  4. Écrire une implémentation de cette méthode avec une seule annotation,
  5. Écrire une classe permettant de publier le web service sans container JEE,
  6. Tester avec soapUI notre premier web service soap,
  7. Générer un client java standard à partir de notre premier web service soap,
  8. Écrire et exécuter le client java.

Vous voyez bien que seule l'étape 4 nécessite vraiment d'écrire du code métier.
Pour le reste ce sont des interfaces à déclarer ou une commande à lancer pour générer des classes java (étape 7). Seule une méthode main est à écrire.

L'étape 6, optionnelle, permet de tester notre web service avant de générer les classes java de l'étape 7.

Vous avez certainement remarqué que nous avons utilisé l'approche "bottom-up" puisque nous déclarons l'interface java SEI en premier.

A l'étape 3, nous allons aussi définir la seule méthode qui sera exposée en tant que service soap.

Il est bon de noter que dans le jargon jax-ws soap, SEI devient "portType" et la méthode de SEI devient "operation".

Une fois les classes java réalisées et le web service publié, nous pouvons générer le contrat WSDL du web service soap (comme à l'étape 5 ).

Passons aux détails de ces étapes. Commençons par créer un projet maven dans votre IDE préféré avec :

Etape 1. Le pom de notre premier projet

Le projet maven aura dans le pom la seule dépendance comme suit:

    <dependency>
	<groupId>javax.xml.ws</groupId>
	<artifactId>jaxws-api</artifactId>
	<version>2.2.11</version>
    </dependency>

Puisque java 8 est utilisé, par la suite, la section configuration (target et source pointent sur java 1.8) du pom est complétée ainsi:

<build>
... 
      <plugins>   
    	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-compiler-plugin</artifactId>
		<version>2.5.1</version>
		<configuration>
		  <source>1.8</source>
		  <target>1.8</target>
		</configuration>
	</plugin>
     </plugins>
  </build>

 

Etapes 2 & 3. Déclarer l'interface (SEI) et sa méthode

Notre premier exemple étant un simple HelloWorld, l'interface SEI nommée IHello:

import javax.jws.*;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style=Style.RPC)  
public  interface IHello {
	@WebMethod
	String say(@WebParam(name="nom") final String name);
}
SEI

 

Dans cette interface SEI nous déclarons les annotations:

  • @WebService sur l'interface pour indiquer que cette interface est SEI,
  • @WebMethod sur la méthode à exposer en tant que service,
  • @SOAPBinding et son argument Style.RPC afin de préciser que le web service SOAP est de type RPC (Remote Procedure Call), c'est à dire une opération à appeler à distance non orientée message. voir ici pour plus de détails,
  • @WebParam comme son nom l'indique permet de nommer le paramètre dans le contexte SOAP.

 

Etape 4. Ecrire l'implémentation (SEImpl)

Dans cet exemple l'implémentation est ridicule:

import java.time.Instant;
import javax.jws.WebService;

@WebService(endpointInterface="fr.abdou.ws.soap.IHello")
public class HelloImpl implements IHello{
	public String say(final String name){
		System.out.println("@ "+Instant.now()+" retourne Hello "+name);
		return "Hello "+name;
	}
}
SEImpl

 

Les seules choses intéressantes à relever sont:

La classe d'implémentation est annotée avec @WebService pour la lier à son interface SEI IHello.

Pour le reste on affiche sur l'écran la date et la chaîne qui vont être retournées.

 

Etape 5. Publier le web service sans container

La classe simple ci-après permet de publier le web service sans besoin de container ou serveur d'app.

import javax.xml.ws.Endpoint;
public class ServiceHelloStarter {
	final static String URL_HELLO = "http://localhost:8001/hello";
	public static void main(String[] args) {
		Endpoint.publish(URL_HELLO, new HelloImpl());
		System.out.println("Service web démarre url " + URL_HELLO);
	}
}
wsStarter

 

La méthode main ne fait que "publish" en indiquant l'url qui sera utile pour la suite. Pensez à exécuter cette méthode avant de passer à l'étape suivante.

 

Etape 6. Tester avec soapUI

Installez l'outil soapUI v5.2.x par exemple puis lancez le programme.

Depuis le menu, créez un nouveau projet SOAP puis saisissez l'url  (de l'étape précédente) http://localhost:8001/hello?wsdl

N'oubliez pas de rajouter ?wsdl à la fin et assurez vous que le programme java de l'étape précédente est lancé.

L'outil SoapUI affiche l'écran comme le montre cette capture:

 

 

SOPAUI-projetc1Hello

 

Il suffit de saisir le nom et de cliquer sur le triangle vert en haut à droite pour voir la réponse xml s'afficher à droite.

Et bien évidemment sur la console du programme java de l'étape 6 vous pouvez voir les traces qui ressemblent à:

Service web démarre url http://localhost:8001/hello
@ 2016-01-22T14:09:47.479Z retourne Hello ....!

 

Etape 7. Générer un client java

 

jax_ws_client

 

Dans cette étape, nous générons des artifacts java via la commande wsimport puis nous écrivons une méthode main à exécuter. Le plus simple est de créer un nouveau projet java maven simple nommé clientWs.

Ensuite lancez la console Dos/linux, puis se positionnez vous dans le répertoire clientWs/src/main/java et enfin lancez la commande:

wsimport -d . -p fr.package.wsclient -keep http://localhost:8001/hello?wsdl
wsimport cmd

Pensez à renommer le paramètre fr.package.wsclient comme il convient à votre contexte.

Attention avant de lancer la commande assurez-vous que le web service est publié (étape 5).

Si vous regardez dans le projet clientWs/src/main/java vous verrez deux classes java générées:

HelloImplService.java et IHello.java

Vous pouvez jeter un œil sur le code mais il n'est pas recommandé de le modifier!

Note. On aurait pu utiliser le plugin jaxws-maven-plugin pour automatiser la génération des artifacts client java.

Enfin, la méthode statique main ci-après permet de tester le webservice:

public class ClientSoapWs {
	public static void main(String[] args) {
		HelloImplService service = new HelloImplService();
		IHello hello = service.getHelloImplPort();
		String text = hello.say("Abdrrazek!");
		System.out.println(text);
	}
}
client java

 

Vous constatez à ce stade que le client est bien couplé au web service serveur. Si le contrat du web service change, il faudra régénérer les artifacts client.

En résumé, pour réaliser un web service soap, nous avons:

  • Déclaré une interface SEI (pratique bien que cela soit optionnel),
  • Écrit son implémentation en le liant avec une annotation au SEI,
  • Publié le web service,
  • Généré les artifacts java pour le client java,
  • Écris du code de la méthode statique main,
  • Exécuté la méthode main.

Voilà pour le premier volet de la première partie. Vous verrez prochainement que Spring-Boot simplifie beaucoup les choses.

7 commentaires

  1. Merci pour le tuto, très instructif.
    On attendant les autres parties, peut-être qu’il changer le titre de l’article !!

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *