Total Pageviews

2018/12/12

[Spring Boot] An example to build a SOAP Web Service Provider

Here has the steps to build a SOAP web service provider:

Step 1. Go to https://start.spring.io/ download spring boot project

Step 2. Import spring boot project into your eclipse


Step 3. Add web services-related dependency into pom.xml
    <dependency>
        <groupId>wsdl4j</groupId>
        <artifactId>wsdl4j</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.ws.xmlschema</groupId>
        <artifactId>xmlschema-core</artifactId>
        <version>2.0.1</version>
    </dependency>

Step 4. Create two XML schema files
countries.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://ws/oi2/test/country"
    targetNamespace="http://ws/oi2/test/country"
    elementFormDefault="qualified">

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

    <xs:element name="getCountryResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="country" type="tns:country" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="country">
        <xs:sequence>
            <xs:element name="name" type="xs:string" />
            <xs:element name="capital" type="xs:string" />
        </xs:sequence>
    </xs:complexType>
    
</xs:schema>

employees.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://ws/oi2/test/emp"
    targetNamespace="http://ws/oi2/test/emp"
    elementFormDefault="qualified">

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

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

    <xs:element name="getEmployeeResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="employee" type="tns:employee" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="employee">
        <xs:sequence>
            <xs:element name="id" type="xs:int" />
            <xs:element name="name" type="xs:string" />
        </xs:sequence>
    </xs:complexType>
    
</xs:schema>

Step 4. Add plugin into pom.xml to generate domain class from XML schema
    <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/xsd</schemaDirectory>
            <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
            <clearOutputDir>false</clearOutputDir>
        </configuration>
    </plugin>

Step 5. execute mvn install to generate domain classes


Step 6. create employee / country repository classes
CountryRepository:
package com.example.soapWsDemo.repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import ws.oi2.test.country.Country;

@Component
public class CountryRepository {
    
    public List<Country> countries = new ArrayList<>();
    
    @PostConstruct
    public void createCountries() {
        Country taiwan = new Country();
        taiwan.setName("台灣");
        taiwan.setCapital("台北");

        Country japan = new Country();
        japan.setName("日本");
        japan.setCapital("東京");

        Country sKorea = new Country();
        sKorea.setName("韓國");
        sKorea.setCapital("首爾");

        countries = Arrays.asList(taiwan, japan, sKorea);
    }
    
    public Country findCountry(String name) {
        if (name == null || "".equals(name)) {
            throw new IllegalArgumentException("請提供國家名稱");
        }

        Country result = null;
        for (int i = 0; i < countries.size(); i++) {
            Country c = countries.get(i);
            if (c.getName().equals(name)) {
                result = c;
                break;
            }
        }
        
        if(result == null) {
            throw new IllegalArgumentException("查無資料");
        }
        return result;
    }
    
}


EmployeeRepository:

package com.example.soapWsDemo.repository;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Component;

import ws.oi2.test.emp.Employee;

@Component
public class EmployeeRepository {
    public List<Employee> employees = new ArrayList<>();

    @PostConstruct
    public void createEmployees() {
        Employee albert = new Employee();
        albert.setId(1);
        albert.setName("Albert");

        Employee mandy = new Employee();
        mandy.setId(2);
        mandy.setName("Mandy");

        employees = Arrays.asList(albert, mandy);
    }

    public Employee getEmployee(String name) {
        if (name == null || "".equals(name)) {
            throw new IllegalArgumentException("姓名不可為空");
        }

        Employee emp = null;

        for (int i = 0; i < employees.size(); i++) {
            Employee rs = employees.get(i);
            if (rs.getName().equals(name)) {
                emp = rs;
                break;
            }
        }

        if (emp == null) {
            throw new IllegalArgumentException("查無此人");
        }

        return emp;
    }

    public Employee getEmployee(Integer id) {
        if (id == null) {
            throw new IllegalArgumentException("id 不可為空");
        }

        Employee emp = null;

        for (int i = 0; i < employees.size(); i++) {
            Employee rs = employees.get(i);
            if (rs.getId() == id) {
                emp = rs;
                break;
            }
        }

        if (emp == null) {
            throw new IllegalArgumentException("查無此人");
        }

        return emp;
    }
}


Step 7. Create service endpoint

CountryEndPoint:
package com.example.soapWsDemo.endPoint;

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.example.soapWsDemo.repository.CountryRepository;

import ws.oi2.test.country.GetCountryRequest;
import ws.oi2.test.country.GetCountryResponse;

@Endpoint
public class CountryEndPoint {

    private static final String NAMESPACE_URI = "http://ws/oi2/test/country";

    @Autowired
    private CountryRepository countryRepo;

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
    @ResponsePayload
    public GetCountryResponse getCountryRequest(@RequestPayload GetCountryRequest request) {
        String name = request.getName();

        GetCountryResponse response = new GetCountryResponse();
        response.setCountry(countryRepo.findCountry(name));

        return response;
    }

}

EmployeeEndPoint:
package com.example.soapWsDemo.endPoint;

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.example.soapWsDemo.repository.EmployeeRepository;

import ws.oi2.test.emp.GetEmployeeByIdRequest;
import ws.oi2.test.emp.GetEmployeeRequest;
import ws.oi2.test.emp.GetEmployeeResponse;

@Endpoint
public class EmployeeEndPoint {

    private static final String NAMESPACE_URI = "http://ws/oi2/test/emp";
    
    @Autowired
    private EmployeeRepository empRepo;
    
    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeRequest")
    @ResponsePayload
    public GetEmployeeResponse getEmployee(@RequestPayload GetEmployeeRequest request) {
        String name = request.getName();

        GetEmployeeResponse response = new GetEmployeeResponse();
        response.setEmployee(empRepo.getEmployee(name));

        return response;
    }

    @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getEmployeeByIdRequest")
    @ResponsePayload
    public GetEmployeeResponse getEmployeeByIdRequest(@RequestPayload GetEmployeeByIdRequest request) {
        Integer id = request.getId();

        GetEmployeeResponse response = new GetEmployeeResponse();
        response.setEmployee(empRepo.getEmployee(id));

        return response;
    }
}


Step 8. Create a new class with Spring WS related beans configuration:
package com.example.soapWsDemo.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.XsdSchemaCollection;
import org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection;

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
    
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/ws/*");
    }

    @Bean
    public DefaultWsdl11Definition employees() throws Exception {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("WebServicePort");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://ws/oi2/test");
        wsdl11Definition.setSchemaCollection(getXsds());
        return wsdl11Definition;
    }

    @Bean
    public XsdSchemaCollection getXsds() throws Exception {
        CommonsXsdSchemaCollection xsds = new CommonsXsdSchemaCollection(new ClassPathResource("/xsd/employees.xsd"),
                new ClassPathResource("/xsd/countries.xsd"));
        xsds.setInline(true);
        return xsds;
    }
    
}



Step 9. launch spring boot application and use SOAP UI to do test




1 comment:

SBP said...

Very good and useful blog. Thanks