In this tutorial, we are going to see how to implement Spring Boot Soap Webservices with a simple use case.
SOAP WebServices:
SOAP stands for Simple Object Access Protocol. SOAP is an XML based protocol for accessing web services over HTTP protocol.
There are two ways to develop SOAP-based web services: Contract First Approach and Contract Last Approach. You can see more about SOAP here.
In this example, I am going to implement a Contract First Approach.
That means, first we need to create a WSDL file, from which we have to generate java binding classes. Let’s see how it works.
Spring Boot Soap WebServices:
Use Case: Creating a simple Item web service which provides the item information based on item id.
Technologies:
- Spring Boot Starter Web Services
- WSDL4J
- Jaxb2
- Maven
- Java 8
Spring Boot Soap WebServices Example:
1. Application Structure:
A typical Spring boot application structure. Some of the packages will be added when we build the application; I will make you alert when it comes.
2. Dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
</dependencies>
Maven plugin:
Add the below maven plugin to generate Java artefacts.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
Complete Maven file:
<?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.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.onlinetutorialspoint</groupId>
<artifactId>Spring-Boot-Soap-Web-Services</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring-Boot-Soap-Web-Services</name>
<description>Spring Boot Soap Web Services 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>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>
<outputDirectory>${project.basedir}/src/main/java</outputDirectory>
<clearOutputDir>false</clearOutputDir>
</configuration>
</plugin>
</plugins>
</build>
</project>
3. Create XML Schema Definition:
Creating a .xsd file under resources folder for XML request and response.
It contains a simple request (ItemRequest) and response (ItemResponse) schema definitions.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://nhk.e6a.mytemp.website/generated"
xmlns:tns="http://nhk.e6a.mytemp.website/generated" elementFormDefault="qualified">
<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>
After these steps build the application so that we could see the generated package under the com/onlinetutorialspoint package. It contains all java binding classes like below.
4. Java Bindings:
Below are the generated java resources.
ItemRequest:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.7
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.07.20 at 12:37:49 AM IST
//
package com.onlinetutorialspoint.generated;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"id"
})
@XmlRootElement(name = "ItemRequest")
public class ItemRequest {
protected int id;
/**
* Gets the value of the id property.
*
*/
public int getId() {
return id;
}
/**
* Sets the value of the id property.
*
*/
public void setId(int value) {
this.id = value;
}
}
ItemResponse:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.7
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.07.20 at 12:37:49 AM IST
//
package com.onlinetutorialspoint.generated;
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;
/**
* <p>Java class for anonymous complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType>
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
* <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="category" type="{http://www.w3.org/2001/XMLSchema}string"/>
* </sequence>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@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;
/**
* Gets the value of the id property.
*
*/
public int getId() {
return id;
}
/**
* Sets the value of the id property.
*
*/
public void setId(int value) {
this.id = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
/**
* Gets the value of the category property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getCategory() {
return category;
}
/**
* Sets the value of the category property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setCategory(String value) {
this.category = value;
}
}
ObjectFactory:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.7
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2019.07.20 at 12:37:49 AM IST
//
package com.onlinetutorialspoint.generated;
import javax.xml.bind.annotation.XmlRegistry;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the com.onlinetutorialspoint.generated package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*
*/
@XmlRegistry
public class ObjectFactory {
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.onlinetutorialspoint.generated
*
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link ItemResponse }
*
*/
public ItemResponse createItemResponse() {
return new ItemResponse();
}
/**
* Create an instance of {@link ItemRequest }
*
*/
public ItemRequest createItemRequest() {
return new ItemRequest();
}
}
5. Soap Configurations:
To make the spring boot application as a soap web service, we have to initialise certain beans while boot-strap the application.
package com.onlinetutorialspoint.config;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;
import sun.java2d.pipe.SpanShapeRenderer;
@Configuration
@EnableWs
public class SoapConfig {
@Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServletServlet(ApplicationContext applicationContext){
MessageDispatcherServlet dispatcherServlet = new MessageDispatcherServlet();
dispatcherServlet.setApplicationContext(applicationContext);
dispatcherServlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean<MessageDispatcherServlet>(dispatcherServlet,"/ws/*");
}
@Bean(name="item")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema xsdSchema){
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("Item");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://nhk.e6a.mytemp.website/generated");
wsdl11Definition.setSchema(xsdSchema);
return wsdl11Definition;
}
@Bean
public XsdSchema xsdSchema(){
return new SimpleXsdSchema(new ClassPathResource("item-details.xsd"));
}
}
MessageDispatchServlet: This Servlet for simplified dispatching of Web service messages. We have to inject Spring ApplicationContext to this servlet to let it know about other beans.
ServletRegistrationBean: To register a Servlet (Registering MessageDispatcherServlet).
DefaultWsdl11Definition: Its a convenient implementation for DefaultWsdl11Definition that creates SOAP binding based on xsdSchema (item-details.xsd). The bean name provides here; is assigned the name of the WSDL.
6. Create Web Service Endpoint:
Creating an Item endpoint.
package com.onlinetutorialspoint.endpoint;
import com.onlinetutorialspoint.generated.ItemRequest;
import com.onlinetutorialspoint.generated.ItemResponse;
import com.onlinetutorialspoint.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
@Endpoint
public class ItemEndPoint {
private static final String NAME_SPACE = "http://nhk.e6a.mytemp.website/generated";
@Autowired
ItemService itemService;
@PayloadRoot(namespace = NAME_SPACE, localPart = "ItemRequest")
@ResponsePayload
public ItemResponse getItems(@RequestPayload ItemRequest itemRequest){
return itemService.getItem(itemRequest);
}
}
@Endpoint annotation indicates that an annotated class is an endpoint. It registers the class as a Spring WS incoming soap message.
@PayloadRoot annotation marks an endpoint method as the handler for an incoming request.
@ResponsePayload annotation indicates that a method return value should be bound to the response payload.
@RequestPayload annotation indicates that a method parameter should be bound to the request payload.
7. Creating Item Service:
It is a simple service class where our actual business logic goes.
package com.onlinetutorialspoint.service;
import com.onlinetutorialspoint.generated.ItemRequest;
import com.onlinetutorialspoint.generated.ItemResponse;
import org.springframework.stereotype.Service;
@Service
public class ItemService {
public ItemResponse getItem(ItemRequest itemRequest){
ItemResponse itemResponse = new ItemResponse();
itemResponse.setId(itemRequest.getId());
itemResponse.setCategory("Sample Category_"+itemRequest.getId());
itemResponse.setName("Sample ItemName_"+itemRequest.getId());
return itemResponse;
}
}
8. Main class:
package com.onlinetutorialspoint;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootSoapWebServicesApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootSoapWebServicesApplication.class, args);
}
}
9. Build it:
$mvn clean install
D:\work\Spring-Boot-Soap-Web-Services>mvn clean install
[INFO] Scanning for projects...
[INFO]
[INFO] -------< com.onlinetutorialspoint:Spring-Boot-Soap-Web-Services >-------
[INFO] Building Spring-Boot-Soap-Web-Services 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ Spring-Boot-Soap-Web-Services ---
[INFO] Deleting D:\work\Spring-Boot-Soap-Web-Services\target
[INFO]
[INFO] --- jaxb2-maven-plugin:1.6:xjc (xjc) @ Spring-Boot-Soap-Web-Services ---
[INFO] Generating source...
[INFO] parsing a schema...
[INFO] compiling a schema...
[INFO] com\onlinetutorialspoint\generated\ItemRequest.java
[INFO] com\onlinetutorialspoint\generated\ItemResponse.java
[INFO] com\onlinetutorialspoint\generated\ObjectFactory.java
[INFO] com\onlinetutorialspoint\generated\package-info.java
....
....
10. Run it:
$mvn spring-boot:run
[INFO] --- jaxb2-maven-plugin:1.6:xjc (xjc) @ Spring-Boot-Soap-Web-Services ---
[INFO] No changes detected in schema or binding files - skipping source generation.
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ Spring-Boot-Soap-Web-Services ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ Spring-Boot-Soap-Web-Services ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] <<< spring-boot-maven-plugin:2.1.5.RELEASE:run (default-cli) < test-compile @ Spring-Boot-Soap-Web-Services <<<
[INFO]
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.5.RELEASE:run (default-cli) @ Spring-Boot-Soap-Web-Services ---
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.5.RELEASE)
2019-07-20 01:06:54.156 INFO 18868 --- [ main] c.o.SpringBootSoapWebServicesApplication : Starting SpringBootSoapWebServicesApplication on DESKTOP-RN4SMHT with PID 18868 (D:\w
ork\Spring-Boot-Soap-Web-Services\target\classes started by Lenovo in D:\work\Spring-Boot-Soap-Web-Services)
2019-07-20 01:06:54.177 INFO 18868 --- [ main] c.o.SpringBootSoapWebServicesApplication : No active profile set, falling back to default profiles: default
2019-07-20 01:06:56.361 INFO 18868 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [or
g.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$5e85ff3d] is not eligible for getting processed by
...
...
11. Let’s access the WSDL file first:
12. Access the application from Soap UI:
On the above screen, you can see the soap request. By providing the item id, you can get the corresponding response.
References:
Download Source from GIT:
Happy Learning 🙂