1. Vue d'ensemble
Dans ce didacticiel, nous verrons comment créer un service Web basé sur SOAP avec les services Web Spring Boot Starter.
2. Services Web SOAP
Un service Web est, en bref, un service de machine à machine indépendant de la plate-forme qui permet la communication sur un réseau.
SOAP est un protocole de messagerie. Les messages (demandes et réponses) sont des documents XML sur HTTP . Le contrat XML est défini par le WSDL (Web Services Description Language). Il fournit un ensemble de règles pour définir les messages, les liaisons, les opérations et l'emplacement du service.
Le XML utilisé dans SOAP peut devenir extrêmement complexe. Pour cette raison, il est préférable d'utiliser SOAP avec un framework comme JAX-WS ou Spring, comme nous le verrons dans ce tutoriel.
3. Style de développement axé sur le contrat
Il existe deux approches possibles lors de la création d'un service Web: Contract-Last et Contract-First. Lorsque nous utilisons une approche contract-last, nous commençons avec le code Java, et nous générons le contrat de service Web (WSDL) à partir des classes. Lors de l'utilisation du contrat d'abord, nous commençons par le contrat WSDL, à partir duquel nous générons les classes Java.
Spring-WS prend uniquement en charge le style de développement contract-first.
4. Configuration du projet Spring Boot
Nous allons créer un projet Spring Boot dans lequel nous définirons notre serveur SOAP WS.
4.1. Dépendances de Maven
Commençons par ajouter le spring-boot-starter-parent à notre projet:
org.springframework.boot spring-boot-starter-parent 2.2.6.RELEASE
Ensuite, ajoutons les dépendances spring-boot-starter-web-services et wsdl4j :
org.springframework.boot spring-boot-starter-web-services wsdl4j wsdl4j
4.2. Le fichier XSD
L'approche contract-first nous oblige à créer d'abord le domaine (méthodes et paramètres) pour notre service. Nous allons utiliser un fichier de schéma XML (XSD) que Spring-WS exportera automatiquement en tant que WSDL:
Dans ce fichier, nous voyons le format de la demande de service Web getCountryRequest . Nous le définissons pour accepter un paramètre de type string .
Ensuite, nous définissons le format de la réponse, qui contient un objet de type country .
Enfin, nous voyons l' objet devise , utilisé dans l' objet pays .
4.3. Générer les classes Java de domaine
Nous allons maintenant générer les classes Java à partir du fichier XSD défini dans la section précédente. Le jaxb2-maven-plugin le fera automatiquement pendant la construction. Le plugin utilise l'outil XJC comme moteur de génération de code. XJC compile le fichier de schéma XSD en classes Java entièrement annotées.
Ajoutons et configurons le plugin dans notre pom.xml:
org.codehaus.mojo jaxb2-maven-plugin 1.6 xjc xjc ${project.basedir}/src/main/resources/ ${project.basedir}/src/main/java false
On remarque ici deux configurations importantes:
- $ {project.basedir} / src / main / resources - L'emplacement du fichier XSD
- $ {project.basedir} / src / main / java - Où nous voulons que notre code Java soit généré
Pour générer les classes Java, nous pourrions simplement utiliser l'outil xjc de notre installation Java. Bien que dans notre projet Maven, les choses soient encore plus simples, car les classes seront automatiquement générées lors de la construction habituelle de Maven:
mvn compile
4.4. Ajouter le point de terminaison du service Web SOAP
La classe de point de terminaison du service Web SOAP gérera toutes les demandes entrantes pour le service. Il lancera le traitement et renverra la réponse.
Avant de définir cela, nous créons un référentiel Pays afin de fournir des données au service Web.
@Component public class CountryRepository { private static final Map countries = new HashMap(); @PostConstruct public void initData() { // initialize countries map } public Country findCountry(String name) { return countries.get(name); } }
Ensuite, configurons le point de terminaison:
@Endpoint public class CountryEndpoint { private static final String NAMESPACE_URI = "//www.baeldung.com/springsoap/gen"; private CountryRepository countryRepository; @Autowired public CountryEndpoint(CountryRepository countryRepository) { this.countryRepository = countryRepository; } @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest") @ResponsePayload public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) { GetCountryResponse response = new GetCountryResponse(); response.setCountry(countryRepository.findCountry(request.getName())); return response; } }
Voici quelques détails à noter:
- @Endpoint - enregistre la classe avec Spring WS en tant que point de terminaison de service Web
- @PayloadRoot - définit la méthode du gestionnaire en fonction de l' espace de noms et des attributs localPart
- @ResponsePayload - indique que cette méthode renvoie une valeur à mapper à la charge utile de la réponse
- @RequestPayload - indique que cette méthode accepte un paramètre à mapper à partir de la demande entrante
4.5. Les beans de configuration du service Web SOAP
Créons maintenant une classe pour configurer le servlet du répartiteur de messages Spring pour recevoir la demande:
@EnableWs @Configuration public class WebServiceConfig extends WsConfigurerAdapter { // bean definitions }
@EnableWs active les fonctionnalités du service Web SOAP dans cette application Spring Boot. La classe WebServiceConfig étend la classe de base WsConfigurerAdapter , qui configure le modèle de programmation Spring-WS basé sur les annotations.
Créons un MessageDispatcherServlet qui est utilisé pour gérer les requêtes SOAP:
@Bean public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { MessageDispatcherServlet servlet = new MessageDispatcherServlet(); servlet.setApplicationContext(applicationContext); servlet.setTransformWsdlLocations(true); return new ServletRegistrationBean(servlet, "/ws/*"); }
Nous définissons l' objet ApplicationContext injecté du servlet afin que Spring-WS puisse trouver d'autres beans Spring.
Nous activons également la transformation de servlet d'emplacement WSDL. Cela transforme l'attribut location de soap: address dans le WSDL afin qu'il reflète l'URL de la demande entrante.
Enfin, créons un objet DefaultWsdl11Definition . Cela expose un WSDL 1.1 standard utilisant un XsdSchema. Le nom WSDL sera le même que le nom du bean.
@Bean(name = "countries") public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); wsdl11Definition.setPortTypeName("CountriesPort"); wsdl11Definition.setLocationUri("/ws"); wsdl11Definition.setTargetNamespace("//www.baeldung.com/springsoap/gen"); wsdl11Definition.setSchema(countriesSchema); return wsdl11Definition; } @Bean public XsdSchema countriesSchema() { return new SimpleXsdSchema(new ClassPathResource("countries.xsd")); }
5. Test du projet SOAP
Une fois la configuration du projet terminée, nous sommes prêts à la tester.
5.1. Construire et exécuter le projet
Il serait possible de créer un fichier WAR et de le déployer sur un serveur d'applications externe. Nous utiliserons plutôt Spring Boot, qui est un moyen plus rapide et plus simple de faire fonctionner l'application.
Tout d'abord, nous ajoutons la classe suivante pour rendre l'application exécutable:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Notez que nous n'utilisons aucun fichier XML (comme web.xml) pour créer cette application. Tout est pur Java.
Nous sommes maintenant prêts à créer et exécuter l'application:
mvn spring-boot:run
Pour vérifier si l'application fonctionne correctement, nous pouvons ouvrir le WSDL via l'URL: //localhost:8080/ws/countries.wsdl
5.2. Tester une requête SOAP
Pour tester une requête, nous créons le fichier suivant et le nommons request.xml:
Spain
Pour envoyer la demande à notre serveur de test, nous pourrions utiliser des outils externes comme SoapUI ou l'extension Google Chrome Wizdler. Une autre façon est d'exécuter la commande suivante dans notre shell:
curl --header "content-type: text/xml" -d @request.xml //localhost:8080/ws
La réponse qui en résulte peut ne pas être facile à lire sans retrait ni saut de ligne.
Pour le voir formaté, nous pouvons le copier-coller dans notre IDE ou dans un autre outil. Si nous avons installé xmllib2, nous pouvons diriger la sortie de notre commande curl vers xmllint :
curl [command-line-options] | xmllint --format -
La réponse doit contenir des informations sur l'Espagne:
Spain 46704314 Madrid EUR
6. Conclusion
Dans cet article, nous avons appris à créer un service Web SOAP à l'aide de Spring Boot. Nous avons également appris à générer du code Java à partir d'un fichier XSD, et nous avons vu comment configurer les beans Spring nécessaires pour traiter les requêtes SOAP.
Le code source complet est disponible à l'adresse over sur GitHub.