DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How To Validate HTTP Post Request Body - Restful Web Services With Spring Framework | Spring Boot
  • RESTful Web Services With Spring Boot: Reading HTTP POST Request Body
  • Spring Boot - How To Use Native SQL Queries | Restful Web Services
  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)

Trending

  • Agile and Quality Engineering: A Holistic Perspective
  • A Guide to Developing Large Language Models Part 1: Pretraining
  • Stateless vs Stateful Stream Processing With Kafka Streams and Apache Flink
  • Breaking Bottlenecks: Applying the Theory of Constraints to Software Development
  1. DZone
  2. Coding
  3. Frameworks
  4. Creating a SOAP Web Service With Spring Boot Starter Web Services

Creating a SOAP Web Service With Spring Boot Starter Web Services

In this post, we cover the concepts of SOAP and REST and show you all the code you need to use SOAP web services in a Spring Boot app.

By 
Ranga Karanam user avatar
Ranga Karanam
DZone Core CORE ·
Updated Sep. 27, 18 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
154.4K Views

Join the DZone community and get the full member experience.

Join For Free

This article will help you create a SOAP Web Service with Spring Boot Starter Web Services. We will take a Contract First approach by defining an XSD and exposing a WSDL from it.

We will address the following questions:

  • What is a web service?
  • What are the different types of web services?
  • What is a SOAP Web Service?
  • What is SOAP?
  • What is a SOAP Envelope?
  • What is a SOAP Header and SOAP Body?
  • What is a WSDL (Web Service Definition Language)?
  • What are the different parts of a WSDL?
  • What is the Contract First Approach?
  • What is an XSD?
  • What is JAXB?
  • How do you configure a JAXB plugin?
  • What is an endpoint?
  • Can you show an example endpoint written with Spring Web Services?
  • What is a MessageDispatcherServlet?
  • How do you configure a MessageDispatcherServlet?
  • How do you generate a WSDL using Spring Web Services?

Resources Overview

In this post, we will create a Student Resource exposing three services using proper URIs and HTTP methods:

  • Retrieve all Students - @GetMapping(“/students”)
  • Get details about a specific student - @GetMapping(“/students/{id}”)
  • Delete a student - @DeleteMapping(“/students/{id}”)
  • Create a new student - @PostMapping(“/students”)
  • Update student details - @PutMapping(“/students/{id}”)

Project Code Structure

The following screenshot shows the structure of the project we will create. Image

A few details:

  • SpringBoot2RestServiceApplication.java - The Spring Boot Application class generated with Spring Initializer. This class acts as the launching point for the application.
  • pom.xml - Contains all the dependencies needed to build this project. We will use Spring Boot Starter AOP.
  • Student.java- Student JPA Entity
  • StudentRepository.java - Student JPA Repository. This is created using Spring Data JpaRepository.
  • StudentResource.java - Spring REST Controller exposing all services on the student's resource.
  • data.sql - Initial data for the student table. Spring Boot would execute this script after the tables are created from the entities.

Tools You Will Need

  • Maven 3.0+ is your build tool.
  • Your favorite IDE. We use Eclipse.
  • JDK 1.8+

Complete Maven Project With Code Examples

Our GitHub repository has all the code examples.

What Is a Web Service?

Service delivered over the web

Is this really a complete definition? Is everything that's delivered over the web a Web Service?

The key things to understand are:

  • Web services are designed for machine-to-machine (or application-to-application) interaction.
  • Web services should be interoperable; not platform dependent.
  • Web services should allow for communication over a network.

Types of Web Services

Not really types but a broad classification:

  • SOAP
  • REST

These are not really mutually exclusive. Some SOAP services can actually be RESTful.

SOAP

SOAP is an abbreviation for Simple Object Access Protocol. In SOAP, the request and response are in XML format. However, not all types of XML are valid SOAP requests.

SOAP defines a standard XML format. We will use WSDL (Web Service Definition Language) to define the format of request XML and the response XML.

Now let's say Facebook wants to know how to call the todo service. What should I give to the Facebook developer?

I will give him a WSDL of the todo service. It will explain:

  • What are the different services (operations) exposed by the server?
  • How can a service (operation) be called? What URL should we use (also called the endpoint)?
  • How should we structure the request XML?
  • How should we structure of response XML?

The SOAP format defines a SOAP envelope which envelopes the entire document.

  • SOAP Header (optional) - Contains any information needed to identify the request. Also, part of the Header is the authentication and authorization information (signatures, encrypted information, etc).
  • SOAP Body - Contains the real XML content for requests or responses.
  • In the case of an error response, the server responds back with SOAP Fault.

REST vs SOAP

REST vs SOAP is not a great comparison. REST is an architectural style. SOAP is a message exchange format.

Let’s compare the popular implementations of REST and SOAP styles.

  • RESTful sample implementation: JSON over HTTP.
  • SOAP sample implementation: XML over SOAP over HTTP.

The following are the important things to consider:

  • REST is built over simple HTTP protocol. SOAP services are more complex to implement and more complex to consume.
  • REST has better performance and scalability. REST reads can be cached, SOAP-based reads cannot be cached.
  • REST permits many different data formats (JSON is the most popular choice) whereas SOAP only permits XML.
  • SOAP services have well defined structure and interface (WSDL) and have a set of well defined standards (WS-Security, WS-AtomicTransaction, and WS-ReliableMessaging). Documentation standards with REST are evolving (we will use Swagger in this post).

SOAP Service Examples

Request

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <getCourseDetailsRequest xmlns="http://in28minutes.com/courses">
            <id>Course1</id>
        </getCourseDetailsRequest>
    </Body>
</Envelope>

Response

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns2:getCourseDetailsResponse xmlns:ns2="http://in28minutes.com/courses">
            <ns2:course>
                <ns2:id>Course1</ns2:id>
                <ns2:name>Spring</ns2:name>
                <ns2:description>10 Steps</ns2:description>
            </ns2:course>
        </ns2:getCourseDetailsResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Fault

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <SOAP-ENV:Fault>
            <faultcode>SOAP-ENV:Server</faultcode>
            <faultstring xml:lang="en">java.lang.NullPointerException</faultstring>
        </SOAP-ENV:Fault>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

WSDL

WSDL is used to define the structure of requests and responses.

  • view-source:http://localhost:8080/ws/courses.wsdl
<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://in28minutes.com/courses" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://in28minutes.com/courses" targetNamespace="http://in28minutes.com/courses">
  <wsdl:types>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://in28minutes.com/courses">

    <xs:element name="getCourseDetailsRequest">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="id" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="getCourseDetailsResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="course" type="tns:course"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="course">
        <xs:sequence>
            <xs:element name="id" type="xs:string"/>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="description" type="xs:string"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="getCourseDetailsRequest">
    <wsdl:part element="tns:getCourseDetailsRequest" name="getCourseDetailsRequest">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="getCourseDetailsResponse">
    <wsdl:part element="tns:getCourseDetailsResponse" name="getCourseDetailsResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="CoursesPort">
    <wsdl:operation name="getCourseDetails">
      <wsdl:input message="tns:getCourseDetailsRequest" name="getCourseDetailsRequest">
    </wsdl:input>
      <wsdl:output message="tns:getCourseDetailsResponse" name="getCourseDetailsResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CoursesPortSoap11" type="tns:CoursesPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getCourseDetails">
      <soap:operation soapAction=""/>
      <wsdl:input name="getCourseDetailsRequest">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getCourseDetailsResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CoursesPortService">
    <wsdl:port binding="tns:CoursesPortSoap11" name="CoursesPortSoap11">
      <soap:address location="http://localhost:8080/ws"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Bootstrapping With Spring Initializr

Creating a SOAP Web service with Spring Initializr is a cake walk.

Spring Initializr is a great tool to bootstrap your Spring Boot projects.

You can create a wide variety of projects using Spring Initializr.

Image

Image

The following steps have to be done for a Web Services project:

  • Launch Spring Initializr and choose the following:
    • Choose com.in28minutes.springboot.soap.web.services.example as the Group.
    • Choose spring-boot-tutorial-soap-web-services as the Artifact.
    • Choose the following dependencies:
      • Web Services
      • DevTools
  • Click 'Generate Project.'
  • Import the project into Eclipse. File -> Import -> Existing Maven Project.

Do not forget to add Web Services as a dependency.

Creating a SOAP Web Service With Spring Boot

We will use a contract first approach and first define the XSD for the request and response.

Define XSD for Request and Response

/src/main/resources/student-details.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://in28minutes.com/students" 
xmlns:tns="http://in28minutes.com/students" elementFormDefault="qualified">

  <xs:element name="GetStudentDetailsRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name= "id" type="xs:int"/>
      </xs:sequence>  
    </xs:complexType>
  </xs:element>

  <xs:element name="GetStudentDetailsResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name= "StudentDetails" type="tns:StudentDetails"/>
      </xs:sequence>  
    </xs:complexType>
  </xs:element>

  <xs:complexType name="StudentDetails">
    <xs:sequence>
      <xs:element name="id" type="xs:int"/>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="passportNumber" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

We are create a simple xsd defining the request GetStudentDetailsRequest and the response GetStudentDetailsResponse.

Example requests and responses are shown below.

Request

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <GetStudentDetailsRequest xmlns="http://in28minutes.com/students">
            <id>1</id>
        </GetStudentDetailsRequest>
    </Body>
</Envelope>

Response

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns2:GetStudentDetailsResponse xmlns:ns2="http://in28minutes.com/students">
            <ns2:StudentDetails>
                <ns2:id>1</ns2:id>
                <ns2:name>Adam</ns2:name>
                <ns2:passportNumber>E1234567</ns2:passportNumber>
            </ns2:StudentDetails>
        </ns2:GetStudentDetailsResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Java API for XML Binding (JAXB) and Configuring a JAXB 2 Maven Plugin

When we implement our code using Spring Web Services, the following steps are typically involved in processing a request:

  • Map Request XML to Java Request Objects.
  • Perform the business logic and create the Java Response Objects.
  • Map the Response Object to a Response XML and return the response.

We do the mapping from XML to Java and Java to XML. This is done using JAXB — a Java API for XML binding.

A Maven JAXB Plugin helps us in generating the Java objects based on the XSD. Let's add it to our 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>

Three important configurations:

  • <schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>- The location of XSD files.
  • <outputDirectory>${project.basedir}/src/main/java</outputDirectory> - Where do you want your Java code to be generated?
  • <clearOutputDir>false</clearOutputDir> - Should the output directory be cleaned every time? We use false because we write our Java source code in the same directory.

Configuring an Endpoint for GetCourseDetailsRequest

The endpoint is the component that receives the request, initiates the processing, and sends the response back.

Let’s first create a bean for storing the student details.

/src/main/java/com/in28minutes/springboot/soap/web/services/example/student/Student.java

package com.in28minutes.springboot.soap.web.services.example.student;

public class Student {
  private Long id;
  private String name;
  private String passportNumber;

  public Student() {
    super();
  }

  public Student(Long id, String name, String passportNumber) {
    super();
    this.id = id;
    this.name = name;
    this.passportNumber = passportNumber;
  }

  public Student(String name, String passportNumber) {
    super();
    this.name = name;
    this.passportNumber = passportNumber;
  }

  // Getters and Setters omitted

  @Override
  public String toString() {
    return String.format("Student [id=%s, name=%s, passportNumber=%s]", id, name, passportNumber);
  }

}

/src/main/java/com/in28minutes/springboot/soap/web/services/example/student/StudentDetailsEndpoint.java

package com.in28minutes.springboot.soap.web.services.example.student;

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;

import com.in28minutes.students.GetStudentDetailsRequest;
import com.in28minutes.students.GetStudentDetailsResponse;
import com.in28minutes.students.StudentDetails;

@Endpoint
public class StudentDetailsEndpoint {

  @PayloadRoot(namespace = "http://in28minutes.com/students", localPart = "GetStudentDetailsRequest")
  @ResponsePayload
  public GetStudentDetailsResponse processCourseDetailsRequest(@RequestPayload GetStudentDetailsRequest request) {
    GetStudentDetailsResponse response = new GetStudentDetailsResponse();

    StudentDetails studentDetails = new StudentDetails();
    studentDetails.setId(request.getId());
    studentDetails.setName("Adam");
    studentDetails.setPassportNumber("E1234567");

    response.setStudentDetails(studentDetails);

    return response;
  }

}

A few important things to note:

  • @Endpoint - Annotation to indicate that this is a Web Service Endpoint.
  • @PayloadRoot(namespace = "http://in28minutes.com/students", localPart = "GetStudentDetailsRequest") - Defines the details of the request that this method will handle. We will handle GetStudentDetailsRequest with the given namespace.
  • @ResponsePayload - This method will return a response which will need to be converted to a response XML.
  • public GetStudentDetailsResponse processCourseDetailsRequest(@RequestPayload GetStudentDetailsRequest request) - Thi method will handle the request. @RequestPayload indicates that this is obtained from the request.

Configure the Message Dispatcher Servlet to Receive the Request

/src/main/java/com/in28minutes/springboot/soap/web/services/example/WebServiceConfig.java

@EnableWs
@Configuration
public class WebServiceConfig {

  @Bean
  public ServletRegistrationBean messageDispatcherServlet(ApplicationContext context) {
    MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
    messageDispatcherServlet.setApplicationContext(context);
    messageDispatcherServlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean(messageDispatcherServlet, "/ws/*");
  }
}

Notes:

  • @EnableWs - Enable SOAP Web Service features in this Spring Boot application.
  • @Configuration - This class contains the Spring configuration.
  • @Bean public ServletRegistrationBean messageDispatcherServlet(ApplicationContext context) - We will want to create a message dispatcher servlet to act as a front controller. return new ServletRegistrationBean(messageDispatcherServlet, "/ws/*") - Configure the URL to the web services.

Spring Web Services Configuration to Generate WSDL

Let's add the wsdl4j dependency to our pom.xml.

/pom.xml

    <dependency>
      <groupId>wsdl4j</groupId>
      <artifactId>wsdl4j</artifactId>
    </dependency>

Let’s enhance the WebServiceConfig to expose the WSDL.

/src/main/java/com/in28minutes/springboot/soap/web/services/example/WebServiceConfig.java

@Bean(name = "students")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema studentsSchema) {
  DefaultWsdl11Definition definition = new DefaultWsdl11Definition();
  definition.setPortTypeName("StudentPort");
  definition.setTargetNamespace("http://in28minutes.com/students");
  definition.setLocationUri("/ws");
  definition.setSchema(studentsSchema);
  return definition;
}

@Bean
public XsdSchema studentsSchema() {
  return new SimpleXsdSchema(new ClassPathResource("student-details.xsd"));
}

Notes

  • @Bean(name = "students") - A Spring bean. The name of the bean is the name of the WSDL in the URL.
  • DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema studentsSchema)
  • definition.setTargetNamespace("http://in28minutes.com/students") - Default namespace
  • definition.setLocationUri("/ws") - The URL where we want to expose the WSDL.
  • definition.setSchema(studentsSchema) - We will create the WSDL based on the xsd defined here: new SimpleXsdSchema(new ClassPathResource("student-details.xsd"))

URL of the WSDL - http://localhost:8080/ws/students.wsdl

<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://in28minutes.com/students" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://in28minutes.com/students" targetNamespace="http://in28minutes.com/students">
  <wsdl:types>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://in28minutes.com/students">

  <xs:element name="GetStudentDetailsRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="id" type="xs:int"/>
      </xs:sequence>  
    </xs:complexType>
  </xs:element>

  <xs:element name="GetStudentDetailsResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="StudentDetails" type="tns:StudentDetails"/>
      </xs:sequence>  
    </xs:complexType>
  </xs:element>

  <xs:complexType name="StudentDetails">
    <xs:sequence>
      <xs:element name="id" type="xs:int"/>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="passportNumber" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
  </wsdl:types>
  <wsdl:message name="GetStudentDetailsResponse">
    <wsdl:part element="tns:GetStudentDetailsResponse" name="GetStudentDetailsResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="GetStudentDetailsRequest">
    <wsdl:part element="tns:GetStudentDetailsRequest" name="GetStudentDetailsRequest">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="StudentPort">
    <wsdl:operation name="GetStudentDetails">
      <wsdl:input message="tns:GetStudentDetailsRequest" name="GetStudentDetailsRequest">
    </wsdl:input>
      <wsdl:output message="tns:GetStudentDetailsResponse" name="GetStudentDetailsResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="StudentPortSoap11" type="tns:StudentPort">
    <soap:binding  transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="GetStudentDetails">
      <soap:operation soapAction=""/>
      <wsdl:input name="GetStudentDetailsRequest">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="GetStudentDetailsResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="StudentPortService">
    <wsdl:port binding="tns:StudentPortSoap11" name="StudentPortSoap11">
      <soap:address location="http://localhost:8080/ws"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Executing a Request Using Wizdler

Install the Chrome plugin Wizdler.

Once you install Wizdler and launch the WSDL URL, http://localhost:8080/ws/students.wsdl, you will see a small icon at the corner of the Chrome browser, which you can click to see the services that are part of the WSDL. Go ahead and click the Wizdler icon and click the service GetStudentDetailsImage

This will launch a window to execute the request. Change the ID to 1. Click the 'Go' button at the top right corner of the screen. Image

You should see the response as shown below. Image

Request

<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
    <Body>
        <GetStudentDetailsRequest xmlns="http://in28minutes.com/students">
            <id>1</id>
        </GetStudentDetailsRequest>
    </Body>
</Envelope>

Response

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
        <ns2:GetStudentDetailsResponse xmlns:ns2="http://in28minutes.com/students">
            <ns2:StudentDetails>
                <ns2:id>1</ns2:id>
                <ns2:name>Adam</ns2:name>
                <ns2:passportNumber>E1234567</ns2:passportNumber>
            </ns2:StudentDetails>
        </ns2:GetStudentDetailsResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

More SOAP Methods

You can enhance the endpoint to expose more operations. The steps would be:

  • Define the structure for request and response in XSD.
  • Enhance the endpoint to process the request.
  • Go ahead and test it.

Another thing you can work on is to remove the hardcoding and add business logic and persistence stuff using JPA.

Good Luck!

Next Steps

  • Learn Basics of Spring Boot - Spring Boot vs Spring vs Spring MVC, Auto Configuration, Spring Boot Starter Projects, Spring Boot Starter Parent, Spring Boot Initializr
  • Learn RESTful and SOAP Web Services with Spring Boot
  • Learn Microservices with Spring Boot and Spring Cloud

Complete Code Example

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

  <groupId>com.in28minutes.springboot.soap.web.services.example</groupId>
  <artifactId>spring-boot-tutorial-soap-web-services</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>spring-boot-tutorial-soap-web-services</name>
  <description>SOAP Web Services with Spring Boot</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.0.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <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>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </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>

  <repositories>
    <repository>
      <id>spring-snapshots</id>
      <name>Spring Snapshots</name>
      <url>https://repo.spring.io/snapshot</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>spring-snapshots</id>
      <name>Spring Snapshots</name>
      <url>https://repo.spring.io/snapshot</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </pluginRepository>
    <pluginRepository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </pluginRepository>
  </pluginRepositories>


</project>

<!-- http://localhost:8080/ws/students.wsdl -->

/src/main/java/com/in28minutes/springboot/soap/web/services/example/SpringBootTutorialSoapWebServicesApplication.java

package com.in28minutes.springboot.soap.web.services.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootTutorialSoapWebServicesApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringBootTutorialSoapWebServicesApplication.class, args);
  }
}

/src/main/java/com/in28minutes/springboot/soap/web/services/example/student/Student.java

package com.in28minutes.springboot.soap.web.services.example.student;

public class Student {
  private Long id;
  private String name;
  private String passportNumber;

  public Student() {
    super();
  }

  public Student(Long id, String name, String passportNumber) {
    super();
    this.id = id;
    this.name = name;
    this.passportNumber = passportNumber;
  }

  public Student(String name, String passportNumber) {
    super();
    this.name = name;
    this.passportNumber = passportNumber;
  }

  public Long getId() {
    return id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getPassportNumber() {
    return passportNumber;
  }

  public void setPassportNumber(String passportNumber) {
    this.passportNumber = passportNumber;
  }

  @Override
  public String toString() {
    return String.format("Student [id=%s, name=%s, passportNumber=%s]", id, name, passportNumber);
  }

}

/src/main/java/com/in28minutes/springboot/soap/web/services/example/student/StudentDetailsEndpoint.java

package com.in28minutes.springboot.soap.web.services.example.student;

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;

import com.in28minutes.students.GetStudentDetailsRequest;
import com.in28minutes.students.GetStudentDetailsResponse;
import com.in28minutes.students.StudentDetails;

@Endpoint
public class StudentDetailsEndpoint {

  @PayloadRoot(namespace = "http://in28minutes.com/students", localPart = "GetStudentDetailsRequest")
  @ResponsePayload
  public GetStudentDetailsResponse processCourseDetailsRequest(@RequestPayload GetStudentDetailsRequest request) {
    GetStudentDetailsResponse response = new GetStudentDetailsResponse();

    StudentDetails studentDetails = new StudentDetails();
    studentDetails.setId(request.getId());
    studentDetails.setName("Adam");
    studentDetails.setPassportNumber("E1234567");

    response.setStudentDetails(studentDetails);

    return response;
  }

}

/src/main/java/com/in28minutes/springboot/soap/web/services/example/WebServiceConfig.java

package com.in28minutes.springboot.soap.web.services.example;
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;

@EnableWs
@Configuration
public class WebServiceConfig {

  @Bean
  public ServletRegistrationBean messageDispatcherServlet(ApplicationContext context) {
    MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
    messageDispatcherServlet.setApplicationContext(context);
    messageDispatcherServlet.setTransformWsdlLocations(true);
    return new ServletRegistrationBean(messageDispatcherServlet, "/ws/*");
  }

  @Bean(name = "students")
  public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema studentsSchema) {
    DefaultWsdl11Definition definition = new DefaultWsdl11Definition();
    definition.setPortTypeName("StudentPort");
    definition.setTargetNamespace("http://in28minutes.com/students");
    definition.setLocationUri("/ws");
    definition.setSchema(studentsSchema);
    return definition;
  }

  @Bean
  public XsdSchema studentsSchema() {
    return new SimpleXsdSchema(new ClassPathResource("student-details.xsd"));
  }
}

/src/main/java/com/in28minutes/students/GetStudentDetailsRequest.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: 2017.11.28 at 02:57:40 PM IST 
//


package com.in28minutes.students;

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 = "GetStudentDetailsRequest")
public class GetStudentDetailsRequest {

    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;
    }

}

/src/main/java/com/in28minutes/students/GetStudentDetailsResponse.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: 2017.11.28 at 02:57:40 PM IST 
//


package com.in28minutes.students;

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="StudentDetails" type="{http://in28minutes.com/students}StudentDetails"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "studentDetails"
})
@XmlRootElement(name = "GetStudentDetailsResponse")
public class GetStudentDetailsResponse {

    @XmlElement(name = "StudentDetails", required = true)
    protected StudentDetails studentDetails;

    /**
     * Gets the value of the studentDetails property.
     * 
     * @return
     *     possible object is
     *     {@link StudentDetails }
     *     
     */
    public StudentDetails getStudentDetails() {
        return studentDetails;
    }

    /**
     * Sets the value of the studentDetails property.
     * 
     * @param value
     *     allowed object is
     *     {@link StudentDetails }
     *     
     */
    public void setStudentDetails(StudentDetails value) {
        this.studentDetails = value;
    }

}

/src/main/java/com/in28minutes/students/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: 2017.11.28 at 02:57:40 PM IST 
//


package com.in28minutes.students;

import javax.xml.bind.annotation.XmlRegistry;


/**
 * This object contains factory methods for each 
 * Java content interface and Java element interface 
 * generated in the com.in28minutes.students 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.in28minutes.students
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link GetStudentDetailsResponse }
     * 
     */
    public GetStudentDetailsResponse createGetStudentDetailsResponse() {
        return new GetStudentDetailsResponse();
    }

    /**
     * Create an instance of {@link StudentDetails }
     * 
     */
    public StudentDetails createStudentDetails() {
        return new StudentDetails();
    }

    /**
     * Create an instance of {@link GetStudentDetailsRequest }
     * 
     */
    public GetStudentDetailsRequest createGetStudentDetailsRequest() {
        return new GetStudentDetailsRequest();
    }

}

/src/main/java/com/in28minutes/students/package-info.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: 2017.11.28 at 02:57:40 PM IST 
//

@javax.xml.bind.annotation.XmlSchema(namespace = "http://in28minutes.com/students", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.in28minutes.students;

/src/main/java/com/in28minutes/students/StudentDetails.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: 2017.11.28 at 02:57:40 PM IST 
//


package com.in28minutes.students;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for StudentDetails complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="StudentDetails">
 *   &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="passportNumber" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "StudentDetails", propOrder = {
    "id",
    "name",
    "passportNumber"
})
public class StudentDetails {

    protected int id;
    @XmlElement(required = true)
    protected String name;
    @XmlElement(required = true)
    protected String passportNumber;

    /**
     * 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 passportNumber property.
     * 
     * @return
     *     possible object is
     *     {@link String }
     *     
     */
    public String getPassportNumber() {
        return passportNumber;
    }

    /**
     * Sets the value of the passportNumber property.
     * 
     * @param value
     *     allowed object is
     *     {@link String }
     *     
     */
    public void setPassportNumber(String value) {
        this.passportNumber = value;
    }

}

/src/main/resources/student-details.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
targetNamespace="http://in28minutes.com/students" 
xmlns:tns="http://in28minutes.com/students" elementFormDefault="qualified">

  <xs:element name="GetStudentDetailsRequest">
    <xs:complexType>
      <xs:sequence>
        <xs:element name= "id" type="xs:int"/>
      </xs:sequence>  
    </xs:complexType>
  </xs:element>

  <xs:element name="GetStudentDetailsResponse">
    <xs:complexType>
      <xs:sequence>
        <xs:element name= "StudentDetails" type="tns:StudentDetails"/>
      </xs:sequence>  
    </xs:complexType>
  </xs:element>

  <xs:complexType name="StudentDetails">
    <xs:sequence>
      <xs:element name="id" type="xs:int"/>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="passportNumber" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>

/src/test/java/com/in28minutes/springboot/soap/web/services/example/SpringBootTutorialSoapWebServicesApplicationTests.java

package com.in28minutes.springboot.soap.web.services.example;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTutorialSoapWebServicesApplicationTests {

  @Test
  public void contextLoads() {
  }

}
SOAP Web Protocols Spring Framework Web Service Spring Boot microservice Requests

Opinions expressed by DZone contributors are their own.

Related

  • How To Validate HTTP Post Request Body - Restful Web Services With Spring Framework | Spring Boot
  • RESTful Web Services With Spring Boot: Reading HTTP POST Request Body
  • Spring Boot - How To Use Native SQL Queries | Restful Web Services
  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!