In this tutorial, we are going to see how to implement a simple Spring Boot SOAP Consumer Example.
Spring Boot SOAP Consumer:
As part of this example, I am going to consume a SOAP web service; you can follow our previous tutorials to get it.
Pre-requisites:
- To run the Spring Boot SOAP client – Initially, you should have your running SOAP web service on your local or remote machine.
- If you do not have in your local, you can follow our previous article on Spring boot SOAP web service.
- Take the WSDL file handy to build java classes
Technologies:
- Spring Boot Starter Web Service 2.1.6 RELEASE
- Java 8
- Maven
- Maven Javb2 plugin
Spring Boot SOAP Client Example:
Create a Spring boot application with the following structure.
Application Structure:
Project Dependencies:
This application requires a single dependency – spring-boot-starter-web-service
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
</dependencies>
Required Maven Plugin:
Add the below maven jaxb2 plugin in pom.xml to generate the java binding classes using WSDL file.
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>com.onlinetutorialspoint.soap.bindings</generatePackage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>
Complete pom.xml:
<?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.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.onlinetutorialspoint</groupId>
<artifactId>Spring-Boot-SOAP-Consumer-Example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring-Boot-SOAP-Consumer-Example</name>
<description>Spring Boot SOAP Consumer Example</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<generatePackage>com.onlinetutorialspoint.soap.bindings</generatePackage>
<generateDirectory>${project.basedir}/src/main/java</generateDirectory>
<schemaDirectory>${project.basedir}/src/main/resources/wsdl</schemaDirectory>
<schemaIncludes>
<include>*.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Configure the WSDL file:
Take the WSDL file from the SOAP web service provider. In our case, we have our SOAP web service running on our machine, and here is the WSDL.
Create a file under resources/wsdl folder with the name of items.wsdl and paste the above content init.
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://nhk.e6a.mytemp.website/generated" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://nhk.e6a.mytemp.website/generated" targetNamespace="http://nhk.e6a.mytemp.website/generated">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://nhk.e6a.mytemp.website/generated">
<xs:element name="ItemRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ItemResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="id" type="xs:int"/>
<xs:element name="name" type="xs:string"/>
<xs:element name="category" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
<wsdl:message name="ItemRequest">
<wsdl:part element="tns:ItemRequest" name="ItemRequest"> </wsdl:part>
</wsdl:message>
<wsdl:message name="ItemResponse">
<wsdl:part element="tns:ItemResponse" name="ItemResponse"> </wsdl:part>
</wsdl:message>
<wsdl:portType name="Item">
<wsdl:operation name="Item">
<wsdl:input message="tns:ItemRequest" name="ItemRequest"> </wsdl:input>
<wsdl:output message="tns:ItemResponse" name="ItemResponse"> </wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ItemSoap11" type="tns:Item">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="Item">
<soap:operation soapAction=""/>
<wsdl:input name="ItemRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="ItemResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ItemService">
<wsdl:port binding="tns:ItemSoap11" name="ItemSoap11">
<soap:address location="http://localhost:8080/ws"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
After this step, you just build the application, then you could see the binding classes under src/main/soap/bindings package. Because we configured this under the plugins section in pom.xml.
Let’s have a look at binding classes:
ItemRequest:
package com.onlinetutorialspoint.soap.bindings;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id"
})
@XmlRootElement(name = "ItemRequest")
public class ItemRequest {
protected int id;
public int getId() {
return id;
}
public void setId(int value) {
this.id = value;
}
}
ItemResponse:
package com.onlinetutorialspoint.soap.bindings;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id",
"name",
"category"
})
@XmlRootElement(name = "ItemResponse")
public class ItemResponse {
protected int id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true)
protected String category;
public int getId() {
return id;
}
public void setId(int value) {
this.id = value;
}
public String getName() {
return name;
}
public void setName(String value) {
this.name = value;
}
public String getCategory() {
return category;
}
public void setCategory(String value) {
this.category = value;
}
}
ObjectFactory:
package com.onlinetutorialspoint.soap.bindings;
import javax.xml.bind.annotation.XmlRegistry;
@XmlRegistry
public class ObjectFactory {
public ObjectFactory() {
}
public ItemRequest createItemRequest() {
return new ItemRequest();
}
public ItemResponse createItemResponse() {
return new ItemResponse();
}
}
Application.properties
Making this application port to 8081. As I have a SOAP service running on 8080 port.
server.port=8081
Create Soap Configuration:
Creating Jaxb2Marshaller object and given the binding classes to scan while loading the application.
package com.onlinetutorialspoint.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@Configuration
public class SoapConfig {
@Bean
public Jaxb2Marshaller marshaller(){
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setPackagesToScan("com.onlinetutorialspoint.soap.bindings");
return jaxb2Marshaller;
}
}
Creating a SOAP client:
The SOAP client class, which is responsible for communicating with the SOAP service and getting the response using WebServiceTemplate object.
package com.onlinetutorialspoint.client;
import com.onlinetutorialspoint.soap.bindings.ItemRequest;
import com.onlinetutorialspoint.soap.bindings.ItemResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Service;
import org.springframework.ws.client.core.WebServiceTemplate;
@Service
public class SoapClient {
@Autowired
private Jaxb2Marshaller jaxb2Marshaller;
private WebServiceTemplate webServiceTemplate;
public ItemResponse getItemInfo(ItemRequest itemRequest){
webServiceTemplate = new WebServiceTemplate(jaxb2Marshaller);
return (ItemResponse) webServiceTemplate.marshalSendAndReceive("http://localhost:8080/ws",itemRequest);
}
}
On the above example, we have given the WSDL URI (http://localhost:8080/ws) to marshalSendAndReceive method. As I am running the service application on my local, I gave the local WSDL URI. If you wanted to access any remote WSDL, you could provide the remote URI here.
Creating a Rest Controller:
I am creating a RestController to access this SOAP client.
package com.onlinetutorialspoint.controller;
import com.onlinetutorialspoint.client.SoapClient;
import com.onlinetutorialspoint.soap.bindings.ItemRequest;
import com.onlinetutorialspoint.soap.bindings.ItemResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ItemController {
@Autowired
SoapClient soapClient;
@PostMapping("/item")
public ItemResponse item(@RequestBody ItemRequest itemRequest){
return soapClient.getItemInfo(itemRequest);
}
}
Run the Application:
$mvn clean install
$mvn spring-boot:run
[INFO] --- spring-boot-maven-plugin:2.1.6.RELEASE:run (default-cli) @ Spring-Boot-SOAP-Consumer-Example ---
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2019-07-27 00:36:29.644 INFO 23148 --- [ main] SpringBootSoapConsumerExampleApplication : Starting SpringBootSoapConsumerExampleApplication on DESKTOP-RN4SMHT with PID 23148 (
D:\work\Spring-Boot-SOAP-Consumer-Example\target\classes started by Lenovo in D:\work\Spring-Boot-SOAP-Consumer-Example)
2019-07-27 00:36:29.657 INFO 23148 --- [ main] SpringBootSoapConsumerExampleApplication : No active profile set, falling back to default profiles: default
2019-07-27 00:36:31.723 INFO 23148 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [or
g.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$c255fca6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligi
ble for auto-proxying)
2019-07-27 00:36:31.797 INFO 23148 --- [ main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0]
2019-07-27 00:36:32.760 INFO 23148 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http)
2019-07-27 00:36:32.811 INFO 23148 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
....
....
Access the Application from Postman:
Done!