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.

Spring Boot Soap WebServices Example 2-min

2. Dependencies:

pom.xml
<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.

pom.xml
<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:

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.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.

resources/item-details.xsd
<?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.

Spring Boot Soap WebServices Example-min

4. Java Bindings:

Below are the generated java resources.

Note: These resources will be lost upon recompilation of the source schema.

ItemRequest:

src/java/com/onlinetutorialspoint/generated/ItemRequest.java
//
// 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>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/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:

src/java/com/onlinetutorialspoint/generated/ItemResponse.java
//
// 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>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}int"/>
 *         &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="category" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/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:

src/java/com/onlinetutorialspoint/generated/ObjectFactory.java
//
// 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.

src/java/com/onlinetutorialspoint/SoapConfig.java
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.

src/java/com/onlinetutorialspoint/endpoint/ItemEndPoint.java
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.

src/java/com/onlinetutorialspoint/service/ItemService.java
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:

SpringBootSoapWebServicesApplication.java
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:

Terminal
$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:

Terminal
$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:

Spring Boot Soap WebServices Example WSDL-min

12. Access the application from Soap UI:

Spring Boot Soap WebServices Example SOUP UI-min

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 🙂