This post explains how to develop a soap based web service with Spring Boot. In this Book Store example, We will create a web service that allows to add books information and get the book information.
Step 1: Maven setup
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.1.RELEASE</version>
</parent>
<groupId>com.kswaughs.spring</groupId>
<artifactId>spring_boot_soapwebsvc</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>spring_boot_soapwebsvc</name>
<description>Spring Boot SOAP WEB Service Example</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<version>1.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<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>
Step 2: Create an XML Schema to define the WebService domain. This book store web service provides two operations to add & get Book details.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://com/kswaughs/services/bookSvc"
targetNamespace="http://com/kswaughs/services/bookSvc"
elementFormDefault="qualified">
<xs:element name="getBookRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="getBookResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="book" type="tns:book" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="addBookRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="book" type="tns:book" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="addBookResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="status" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="book">
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element name="author" type="xs:string" />
<xs:element name="price" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Step 3: Generate Domain classes based on Schema defined. When you run Maven build, jaxb2-maven-plugin will generate the java files and stores in src/main/java folder.
Step 4: Create a book repository class to store books details and Initialise the list with few books.
package com.kswaughs.repo;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import com.kswaughs.services.booksvc.Book;
@Component
public class BookRepository {
private static final List<Book> books = new ArrayList<Book>();
@PostConstruct
public void initData() {
Book book1 = new Book();
book1.setName("The Family Way");
book1.setAuthor("Tony Parsons");
book1.setPrice("10 $");
books.add(book1);
Book book2 = new Book();
book2.setName("Count To Ten");
book2.setAuthor("Karen Rose");
book2.setPrice("12 $");
books.add(book2);
}
public Book findBook(String name) {
Assert.notNull(name);
Book result = null;
for (Book book : books) {
if (name.equals(book.getName())) {
result = book;
}
}
return result;
}
public void addBook(Book book) {
books.add(book);
}
}
Step 5: Create BookService EndPoint class to handle the incoming SOAP requests.
package com.kswaughs.services;
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;
import com.kswaughs.repo.BookRepository;
import com.kswaughs.services.booksvc.AddBookRequest;
import com.kswaughs.services.booksvc.AddBookResponse;
import com.kswaughs.services.booksvc.GetBookRequest;
import com.kswaughs.services.booksvc.GetBookResponse;
@Endpoint
public class BookEndPoint {
private static final String NAMESPACE_URI = "http://com/kswaughs/services/bookSvc";
private BookRepository bookRepository;
@Autowired
public BookEndPoint(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
// To handle getBookRequest
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "getBookRequest")
@ResponsePayload
public GetBookResponse getBook(@RequestPayload GetBookRequest request) {
GetBookResponse response = new GetBookResponse();
response.setBook(bookRepository.findBook(request.getName()));
return response;
}
// To handle addBookRequest
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "addBookRequest")
@ResponsePayload
public AddBookResponse addBook(@RequestPayload AddBookRequest request) {
AddBookResponse response = new AddBookResponse();
bookRepository.addBook(request.getBook());
response.setStatus("SUCCESS");
return response;
}
}
Step 6: Configure Web Service Spring beans
package com.kswaughs.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.config.annotation.WsConfigurerAdapter;
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 SpringWebConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(
ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "books")
public DefaultWsdl11Definition defaultBookWsdl11Definition(XsdSchema countriesSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("BooksPort");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://com/kswaughs/services/bookSvc");
wsdl11Definition.setSchema(booksSchema());
return wsdl11Definition;
}
@Bean
public XsdSchema booksSchema() {
return new SimpleXsdSchema(new ClassPathResource("books.xsd"));
}
}
Step 7: Create Spring Boot Main Application Class
package com.kswaughs.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan({ "com.kswaughs.*" })
public class BootApp {
public static void main(String[] args) {
SpringApplication.run(BootApp.class, args);
}
}
Step 8: Define application Context path & port in application.properties
server.contextPath=/MyApp server.port=8088
Testing the Application
WSDL Url : http://localhost:8088/MyApp/ws/books.wsdl
SOAP URL : http://localhost:8088/MyApp/ws
Test 1 : addBookRequest
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:book="http://com/kswaughs/services/bookSvc">
<soapenv:Header/>
<soapenv:Body>
<book:addBookRequest>
<book:book>
<book:name>Revolution 2020</book:name>
<book:author>Chetan Bhagat</book:author>
<book:price>11 $</book:price>
</book:book>
</book:addBookRequest>
</soapenv:Body>
</soapenv:Envelope>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:addBookResponse xmlns:ns2="http://com/kswaughs/services/bookSvc">
<ns2:status>SUCCESS</ns2:status>
</ns2:addBookResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Test 2 : getBookRequest
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:book="http://com/kswaughs/services/bookSvc">
<soapenv:Header/>
<soapenv:Body>
<book:getBookRequest>
<book:name>Revolution 2020</book:name>
</book:getBookRequest>
</soapenv:Body>
</soapenv:Envelope>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ns2:getBookResponse xmlns:ns2="http://com/kswaughs/services/bookSvc">
<ns2:book>
<ns2:name>Revolution 2020</ns2:name>
<ns2:author>Chetan Bhagat</ns2:author>
<ns2:price>11 $</ns2:price>
</ns2:book>
</ns2:getBookResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>