By kswaughs | Thursday, November 30, 2017

Spring Boot Soap Web Service Client Example

This post explains how to consume a soap web service with Spring Boot using org.springframework.ws.client.core.WebServiceTemplate class.

In this example, we will call Book Store web service which is already explained in the following post.

Spring Boot Soap Web Service Example

Step 1: Maven setup

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.kswaughs.spring</groupId>
    <artifactId>spring-boot-soap-service-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-boot-soap-service-client</name>
    <description>Demo project for Spring Boot SOAP Web service Client</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.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>
        <maven-jaxb2-plugin.version>0.13.2</maven-jaxb2-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jvnet.jaxb2.maven2</groupId>
                <artifactId>maven-jaxb2-plugin</artifactId>
                <version>${maven-jaxb2-plugin.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaDirectory>
                       ${project.basedir}/src/main/resources/wsdl
                    </schemaDirectory>
                    <schemaIncludes>
                        <include>*.wsdl</include>
                    </schemaIncludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Step 2: To consume a web service, we need a WSDL file. Copy your WSDL file to resources folder.

src/main/resources/wsdl/books.wsdl
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:sch="http://com/kswaughs/services/bookSvc"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://com/kswaughs/services/bookSvc"
    targetNamespace="http://com/kswaughs/services/bookSvc">
    <wsdl:types>
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified"
            targetNamespace="http://com/kswaughs/services/bookSvc">
            <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>
    </wsdl:types>
    <wsdl:message name="getBookRequest">
        <wsdl:part element="tns:getBookRequest" name="getBookRequest">
        </wsdl:part>
    </wsdl:message>
    <wsdl:message name="addBookRequest">
        <wsdl:part element="tns:addBookRequest" name="addBookRequest">
        </wsdl:part>
    </wsdl:message>
    <wsdl:message name="addBookResponse">
        <wsdl:part element="tns:addBookResponse" name="addBookResponse">
        </wsdl:part>
    </wsdl:message>
    <wsdl:message name="getBookResponse">
        <wsdl:part element="tns:getBookResponse" name="getBookResponse">
        </wsdl:part>
    </wsdl:message>
    <wsdl:portType name="BooksPort">
        <wsdl:operation name="getBook">
            <wsdl:input message="tns:getBookRequest" name="getBookRequest">
            </wsdl:input>
            <wsdl:output message="tns:getBookResponse" name="getBookResponse">
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="addBook">
            <wsdl:input message="tns:addBookRequest" name="addBookRequest">
            </wsdl:input>
            <wsdl:output message="tns:addBookResponse" name="addBookResponse">
            </wsdl:output>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="BooksPortSoap11" type="tns:BooksPort">
        <soap:binding style="document"
            transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="getBook">
            <soap:operation soapAction="" />
            <wsdl:input name="getBookRequest">
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output name="getBookResponse">
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="addBook">
            <soap:operation soapAction="" />
            <wsdl:input name="addBookRequest">
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output name="addBookResponse">
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="BooksPortService">
        <wsdl:port binding="tns:BooksPortSoap11" name="BooksPortSoap11">
            <soap:address location="http://localhost:8088/MyApp/ws" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

Step 3: Generate Domain classes based on Schema defined. When you run Maven build, maven-jaxb2-plugin will generate the java files and stores in target/generated-sources/xjc folder. Configure this folder as source folder in your eclipse IDE.

Step 4: Create Web Service Client Configuration class.

WebSvcClientConfig.java
package com.kswaughs.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.core.WebServiceTemplate;

@Configuration
public class WebSvcClientConfig {
    
    @Value("${books.svc.url}")
    private String url;

    @Bean
    Jaxb2Marshaller jaxb2Marshaller() {
    
        Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
        jaxb2Marshaller.setContextPath("com.kswaughs.services.booksvc");

        return jaxb2Marshaller;
    }

    @Bean
    public WebServiceTemplate webServiceTemplate() {
    
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
        webServiceTemplate.setMarshaller(jaxb2Marshaller());
        webServiceTemplate.setUnmarshaller(jaxb2Marshaller());
        webServiceTemplate.setDefaultUri(url);

        return webServiceTemplate;
    }

}

Step 5: Create a Service Client class which will consume the web service through above configured WebServiceTemplate class.

BookServiceClient.java
package com.kswaughs.services;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.core.WebServiceTemplate;

import com.kswaughs.services.booksvc.AddBookRequest;
import com.kswaughs.services.booksvc.AddBookResponse;
import com.kswaughs.services.booksvc.Book;
import com.kswaughs.services.booksvc.GetBookRequest;
import com.kswaughs.services.booksvc.GetBookResponse;
import com.kswaughs.services.booksvc.ObjectFactory;

@Component
public class BookServiceClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(BookServiceClient.class);

    @Autowired
    private WebServiceTemplate webServiceTemplate;

    public String addBook(String name, String author, String price) {
        
        ObjectFactory factory = new ObjectFactory();
        
        AddBookRequest req = factory.createAddBookRequest();

        Book book = new Book();
        book.setAuthor(author);
        book.setName(name);
        book.setPrice(price);

        req.setBook(book);

        LOGGER.info("Client sending book[Name={},", book.getName());

        AddBookResponse resp = (AddBookResponse) webServiceTemplate.marshalSendAndReceive(req);

        LOGGER.info("Client received status='{}'", resp.getStatus());
        
        return resp.getStatus();
    }

    public Book getBook(String name) {
        
        ObjectFactory factory = new ObjectFactory();
        
        GetBookRequest req = factory.createGetBookRequest();

        req.setName(name);

        LOGGER.info("Client sending book[Name={},", name);

        GetBookResponse resp = (GetBookResponse) webServiceTemplate.marshalSendAndReceive(req);

        LOGGER.info("Client received book='{}'", resp.getBook());
        
        return resp.getBook();
    }

}

Step 6: To test this application, I am creating a sample class which will reads the user entered commands from console and calls the service client methods.

BookCommandLineListener.java
package com.kswaughs.services;

import java.util.Arrays;
import java.util.Scanner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.kswaughs.services.booksvc.Book;

@Component
public class BookCommandLineListener  {

    private static final Logger LOGGER = LoggerFactory
        .getLogger(BookCommandLineListener.class);

    @Autowired
    private BookServiceClient bookSvcClient;

    @Scheduled(fixedDelay=1000)
    public void run() throws Exception {

        try (Scanner scanner = new Scanner(System.in)) {

            while (true) {

                LOGGER.info("Enter your command");
                String text = scanner.nextLine();

                LOGGER.info("you entered :{}", text);
                String[] args = text.split("\\s+");

                LOGGER.info("args :{}", Arrays.toString(args));

                if ("ADD".equalsIgnoreCase(args[0])) {

                    String name = args[1];
                    String author = args[2];
                    String price = args[3];

                    String status = bookSvcClient.addBook(name, author, price);

                    LOGGER.info("Book Added Status :{}", status);

                } else if ("GET".equalsIgnoreCase(args[0])) {
                    String name = args[1];

                    Book book = bookSvcClient.getBook(name);

                    if(book != null) {
                        LOGGER.info("GET Book Details : Name:{}, Author:{}, Price:{}", 
                                book.getName(), book.getAuthor(), book.getPrice());
                    }

                } else {
                    
                    LOGGER.info("Invalid Command."); 
                }
            }
        }
    }
}

Step 7: Create Spring Boot Main Application Class

SpringBootSoapServiceClientApplication.java
package com.kswaughs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class SpringBootSoapServiceClientApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(SpringBootSoapServiceClientApplication.class, args);
    }
    
}

Step 8: Configure web service url in application.properties

src/main/resources/application.properties
books.svc.url=http://localhost:8088/MyApp/ws

Testing the Application

Test Add method
2017-12-01 11:19:13.376  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : Enter your command
ADD SpringGuide kswaughs 10
2017-12-01 11:20:27.922  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : you entered :ADD SpringGuide kswaughs 10
2017-12-01 11:20:27.922  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : args :[ADD, SpringGuide, kswaughs, 10]
2017-12-01 11:20:27.922  INFO 10440 --- [pool-1-thread-1] com.kswaughs.services.BookServiceClient  : Client sending book[Name=SpringGuide,
2017-12-01 11:20:28.930  INFO 10440 --- [pool-1-thread-1] com.kswaughs.services.BookServiceClient  : Client received status='SUCCESS'
2017-12-01 11:20:28.930  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : Book Added Status :SUCCESS

Test Get method
2017-12-01 11:20:28.930  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : Enter your command
GET SpringGuide
2017-12-01 11:20:43.711  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : you entered :GET SpringGuide
2017-12-01 11:20:43.711  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : args :[GET, SpringGuide]
2017-12-01 11:20:43.720  INFO 10440 --- [pool-1-thread-1] com.kswaughs.services.BookServiceClient  : Client sending book[Name=SpringGuide,
2017-12-01 11:20:43.740  INFO 10440 --- [pool-1-thread-1] com.kswaughs.services.BookServiceClient  : Client received book='com.kswaughs.services.booksvc.Book@fa6b61e'
2017-12-01 11:20:43.740  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : GET Book Details : Name:SpringGuide, Author:kswaughs, Price:10

Test invalid command
2017-12-01 11:20:43.740  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : Enter your command
ABCD
2017-12-01 11:20:56.944  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : you entered :ABCD
2017-12-01 11:20:56.944  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : args :[ABCD]
2017-12-01 11:20:56.956  INFO 10440 --- [pool-1-thread-1] c.k.services.BookCommandLineListener     : Invalid Command.

Recommend this on


4 comments:

  1. avg168 สล็อต ไม่ต้องลงทุน pg slot เว็บไซต์ ตรง เป็นเกมที่คนไทยเป็นที่นิยม ที่พึงพอใจเล่นกันเป็นจำเป็นต้องเวลาเป็นเวลานานมาก เหตุเพราะเป็น เกมสล็อต ออนไลน์ ได้เงินจริง

    ReplyDelete
  2. ปากทางเข้า pg galaxy688 บริการเกมสล็อตในแบบต่างๆซึ่งผู้เล่นสามารถร่วมสนุกสนานกับพวกเรา พร้อมทำเงินให้ได้มากที่สุด PG SLOT อย่างไม่ต้องสงสัย ด้วยวิถีทางการเข้าถึงที่นานัปการ

    ReplyDelete
  3. riches888pg เกมสล็อตออนไลน์ บริษัทตรงไม่ผ่านผู้แทนเล่นง่าย สมัครง่าย ผ่านระบบ อัตโนมัติ แบบเร็ว ข้างใน 15 วินาที pg slot เกมสล็อตออนไลน์ที่ยอดเยี่ยมในไทยเลือกใช้บริการเรา

    ReplyDelete