Création de WebServices avec Spring Boot et CXF

Développement de WebService avec Spring Boot

Configuration des dépendances Maven requises

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>webservice-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>webservice-demo</name>
    <description>Projet de démonstration pour Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        

        <!-- Dépendances pour WebService avec CXF -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>3.2.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>3.2.7</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Code source3. Mise en place du serveur WebService

3.1 Classe d'entité Utilisateur

package com.example.demo.Entity;

import java.io.Serializable;

/**
 * Classe d'entité pour les utilisateurs
 */
public class Utilisateur implements Serializable {
    private static final long serialVersionUID = -3628469724795296287L;

    private String idUtilisateur;
    private String nomUtilisateur;
    private String email;


    public String getIdUtilisateur() {
        return idUtilisateur;
    }

    public void setIdUtilisateur(String idUtilisateur) {
        this.idUtilisateur = idUtilisateur;
    }

    public String getNomUtilisateur() {
        return nomUtilisateur;
    }

    public void setNomUtilisateur(String nomUtilisateur) {
        this.nomUtilisateur = nomUtilisateur;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "Utilisateur{" +
                "idUtilisateur='" + idUtilisateur + '\'' +
                ", nomUtilisateur='" + nomUtilisateur + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}

3.2 Interface de service

package com.example.demo.Service;


import com.example.demo.Entity.Utilisateur;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;


//@WebService(targetNamespace="http://service.demo.example.com") Sans cette annotation, l'appel dynamique invoke pourrait échouer
@WebService(targetNamespace="http://service.demo.example.com")
public interface ServiceUtilisateur {

    @WebMethod// Marque la méthode comme exposée par le webservice
    public Utilisateur recupererUtilisateur(@WebParam(name = "idUtilisateur") String idUtilisateur);

    @WebMethod
    @WebResult(name="String",targetNamespace="")
    public String recupererNomUtilisateur(@WebParam(name = "idUtilisateur") String idUtilisateur);

}

3.3 Implémentation de l'interface de service

package com.example.demo.Service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.jws.WebService;

import com.example.demo.Entity.Utilisateur;
import com.example.demo.Service.ServiceUtilisateur;
import org.springframework.stereotype.Component;

/**
 * Implémentation du service pour les utilisateurs
 */
@WebService(serviceName="ServiceUtilisateur",// Nom du service exposé
        targetNamespace="http://service.demo.example.com",// Espace de noms
        endpointInterface="com.example.demo.Service.ServiceUtilisateur")// Interface du service
@Component
public class ServiceUtilisateurImpl implements ServiceUtilisateur {

    private Map<String, Utilisateur> repertoireUtilisateurs = new HashMap<String, Utilisateur>();
    public ServiceUtilisateurImpl() {
        System.out.println("Initialisation des données utilisateur");
        Utilisateur utilisateur = new Utilisateur();
        utilisateur.setIdUtilisateur(UUID.randomUUID().toString().replace("-", ""));
        utilisateur.setNomUtilisateur("user01");
        utilisateur.setEmail("user01@example.com");
        repertoireUtilisateurs.put(utilisateur.getIdUtilisateur(), utilisateur);

        utilisateur = new Utilisateur();
        utilisateur.setIdUtilisateur(UUID.randomUUID().toString().replace("-", ""));
        utilisateur.setNomUtilisateur("user02");
        utilisateur.setEmail("user02@example.com");
        repertoireUtilisateurs.put(utilisateur.getIdUtilisateur(), utilisateur);

        utilisateur = new Utilisateur();
        utilisateur.setIdUtilisateur(UUID.randomUUID().toString().replace("-", ""));
        utilisateur.setNomUtilisateur("user03");
        utilisateur.setEmail("user03@example.com");
        repertoireUtilisateurs.put(utilisateur.getIdUtilisateur(), utilisateur);
    }
    @Override
    public String recupererNomUtilisateur(String idUtilisateur) {
        return "ID utilisateur : " + idUtilisateur;
    }
    @Override
    public Utilisateur recupererUtilisateur(String idUtilisateur) {
        System.out.println("Répertoire utilisateurs :"+repertoireUtilisateurs);
        return repertoireUtilisateurs.get(idUtilisateur);
    }

}

3.4 Cnofiguration pour publier le WebService

package com.example.demo.config;

import com.example.demo.Service.ServiceUtilisateur;
import com.example.demo.Service.impl.ServiceUtilisateurImpl;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBus;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.xml.ws.Endpoint;

@Configuration
public class ConfigurationCxf {

    /**
     * Cette méthode modifie le préfixe du nom de service dans le projet.
     * Si cette méthode est commentée : wsdl est accessible à http://127.0.0.1:8080/services/utilisateur?wsdl
     * Si décommentée : wsdl est accessible à : http://127.0.0.1:8080/soap/utilisateur?wsdl
     * @return
     */
    @SuppressWarnings("all")
    @Bean
    public ServletRegistrationBean servletEnregistrement() {
        return new ServletRegistrationBean(new CXFServlet(), "/soap/*");
    }

    @Bean(name = Bus.DEFAULT_BUS_ID)
    public SpringBus busSpring()
    {
        return  new SpringBus();
    }

    @Bean
    public ServiceUtilisateur serviceUtilisateur()
    {
        return  new ServiceUtilisateurImpl();
    }

    @Bean
    public Endpoint pointFinal() {
        EndpointImpl pointFinal=new EndpointImpl(busSpring(), serviceUtilisateur());// Service à publier
        pointFinal.publish("/utilisateur"); // Nom de publication
        return pointFinal;
    }
}

  1. Informatoins WSDL après démarrage du projet

  1. Deux méthodes d'appel

package com.example.demo.client;

import com.example.demo.Service.ServiceUtilisateur;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;

/**
 * Client WebService:
 * Cette classe propose deux différentes méthodes pour appeler un service WebService
 * 1 : Méthode par fabrique de proxy
 * 2 : Appel dynamique du WebService
 */
public class ClientCxf {


    public static void main(String[] args) {
//        ClientCxf.methode1();
        ClientCxf.methode2();
    }

    /**
     * 1. Méthode par fabrique de proxy, nécessite l'adresse de l'interface distante
     */
    public static void methode1() {
        try {
            // Adresse de l'interface
            String adresse = "http://127.0.0.1:8080/soap/utilisateur?wsdl";
            // Fabrique de proxy
            JaxWsProxyFactoryBean fabriqueProxy = new JaxWsProxyFactoryBean();
            // Configuration de l'adresse du proxy
            fabriqueProxy.setAddress(adresse);
            // Configuration du type d'interface
            fabriqueProxy.setServiceClass(ServiceUtilisateur.class);
            // Création d'une implémentation de proxy d'interface
            ServiceUtilisateur su = (ServiceUtilisateur) fabriqueProxy.create();
            // Préparation des données
            String idUtilisateur = "test";
            // Appel de la méthode du proxy et récupération du résultat
            String resultat = su.recupererNomUtilisateur(idUtilisateur);
            System.out.println("Résultat : " + resultat);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 2 : Appel dynamique
     */
    public static void methode2() {
        // Création d'un client dynamique
        JaxWsDynamicClientFactory fabriqueDynamique = JaxWsDynamicClientFactory.newInstance();
        Client client = fabriqueDynamique.createClient("http://127.0.0.1:8080/soap/utilisateur?wsdl");
        // Cas nécessitant une authentification
        // client.getOutInterceptors().add(new ClientLoginInterceptor(UTILISATEUR, MOT_DE_PASSE));
        Object[] resultats = new Object[0];
        try {
            // invoke("nomMethode",parametre1,parametre2,parametre3....);
            resultats = client.invoke("recupererNomUtilisateur", "test");
            System.out.println("Données retournées :" + resultats[0]);
        } catch (java.lang.Exception e) {
            e.printStackTrace();
        }
    }
}

  1. Points importants

Comme mentionné précédemment, si l'annotation d'inetrface n'inclut pas targetNamespace, un erreur se produira lors de l'appel dynamique, comme indiqué ci-dessous.

Étiquettes: Spring Boot CXF WebService JAX-WS Maven

Publié le 21 juin à 23h41