JAVA Tutorials

What is the Top-Down Bottom-up Approach?

Web Services can be implemented using two approaches top-down bottom-up Approach:

  1. Top-Down
  2. Bottom-up

Top-Down:

In Top-down Approach, the service contract that is WSDL is defined first. Thus, this approach is also known as the contract-first approach. WSDL contains all the information regarding the service, such as service definition, message format, security details, etc. Here the WSDL  is written fist and then the service code.

TopDown Approach

Let us implement the Top-down approach. 

Step 1: Create Maven Dependencies.

First, add the spring-boot-starter-parent to your project.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
</parent>
Then, add the spring-boot-starter-web-services and wsdl4j dependencies.
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
</dependency>

Step 2: Create XSD File

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="https://www.w3.org/2001/XMLSchema" xmlns:tns="https://www.example.com/springsoap/gen"
           targetNamespace="http://www.example.com/springsoap/gen" 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="population" type="xs:int"/>
            <xs:element name="capital" type="xs:string"/>
            <xs:element name="currency" type="tns:currency"/>
        </xs:sequence>
    </xs:complexType>
 
    <xs:simpleType name="currency">
        <xs:restriction base="xs:string">
            <xs:enumeration value="GBP"/>
            <xs:enumeration value="EUR"/>
            <xs:enumeration value="PLN"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Step 3: We will now generate the Java classes from the XSD file defined. The jaxb2-maven-plugin uses the XJC tool as code generation engine, and XJC compiles the XSD schema file into fully annotated Java classes.

We will add and configure the plugin in 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>

Step 4: Add the SOAP Web Service Endpoint

@Component
public class CountryRepository {
     private static final Map<String, Country> countries = new HashMap<>();
     @PostConstruct
    public void initData() {
        // initialize countries map
    }
     public Country findCountry(String name) {
        return countries.get(name);
    }
}
@Endpoint
public class CountryEndpoint {
     private static final String NAMESPACE_URI = "https://www.example.com/springsoap/gen";
     private CountryRepository countryRepository;
     @Autowired
    public CountryEndpoint(CountryRepository countryRepository) {
        this.countryRepository = countryRepository;
    }
     @PayloadRoot(namespace = NAMESPACE_URI, localPart = "getCountryRequest")
    @ResponsePayload
    public GetCountryResponse getCountry(@RequestPayload GetCountryRequest request) {
        GetCountryResponse response = new GetCountryResponse();
        response.setCountry(countryRepository.findCountry(request.getName()));
         return response;
    }
}

Step 5: Create SOAP Web Service Configuration Beans.

First, create a class to configure the Spring message dispatcher servlet for receiving the request.

@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
    // bean definitions
}

@EnableWs will enable the SOAP Web Service features in this Spring Boot application. The WebServiceConfig class will then extend the WsConfigurerAdapter base class, which configures the annotation-driven Spring-WS programming model.

Now create a MessageDispatcherServlet, which is used for handling SOAP requests.

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

Finally, we will create a DefaultWsdl11Definition object that exposes a standard WSDL using an XsdSchema. The WSDL name will be the same as of the bean name.

@Bean(name = "countries")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("CountriesPort");
    wsdl11Definition.setLocationUri("/ws");
    wsdl11Definition.setTargetNamespace("http://www.example.com/springsoap/gen");
    wsdl11Definition.setSchema(countriesSchema);
    return wsdl11Definition;
}
 @Bean
public XsdSchema countriesSchema() {
    return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
}

Bottom-Up:

This approach is exactly the reverse of the Top-down Approach. In this approach, WSDL is created last. Thus, this approach is also known as the contract-last approach. Here the service code is written fist and then the WSDL.

BottomUp Approach

Let us implement the Bottom-up approach.

Step 1: Create a maven project.

Fig - New Maven project

Provide the details about the maven project.

Fig - Creating New Maven Project

Select the maven-archetype-web app and click on Next.

Fig - select maven-archetype-web app

Fill the fields, and click on the Finish button.

Fig - Provide Group Id, Artifact Id, version and Package information

Step 2: Default POM file will get generated.

Fig - default POM file generated

Add the below jars as a dependency.

  • Spring-core
  • Spring-web
  • Spring-context
  • cxf-rt-frontend-jaxws
  • Cxf-Rt-transports-http

Step 3: Define the POJO class.

Fig - Define POJO class

Declare the methods in an interface.

Define methods in Interface

Provide Class implementation.

Fig - class implementation for the interface

Define cxf bean in XML file and declare this file in web.xml.

Fig - endpoint implementation of the web service

Listing of web.xml is shown as:

Fig - The cxf servlet is mapped to url pattern as services

Step 4: Deploy the web service using the below URL:

http://localhost:8080/CustomerService/services/

The page will display the details about the service:

Fig - Service and the link to get WSDL file

The generated WSDL file will be:

<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://cxf.ws.example.com/"xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="CustomerServiceImplService" targetNamespace="http://cxf.ws.example.com/"> 
<wsdl:types> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://cxf.ws.example.com/" elementFormDefault="unqualified" targetNamespace="http://cxf.ws.example.com/"version="1.0">
<xs:element name="addCustomer" type="tns:addCustomer"/>
<xs:element name="addCustomerResponse" type="tns:addCustomerResponse"/> 
<xs:complexType name="addCustomer"> 
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="tns:customerVO"/>
</xs:sequence>a 
</xs:complexType> 
<xs:complexType name="customerVO"> 
<xs:sequence>
<xs:element name="custId" type="xs:int"/>
<xs:element minOccurs="0" name="custName" type="xs:string"/>
</xs:sequence> 
</xs:complexType> 
<xs:complexType name="addCustomerResponse"> 
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence> 
</xs:complexType> 
</xs:schema> 
</wsdl:types> 
<wsdl:message name="addCustomerResponse">
<wsdl:part element="tns:addCustomerResponse" name="parameters"></wsdl:part>
</wsdl:message> 
<wsdl:message name="addCustomer">
<wsdl:part element="tns:addCustomer" name="parameters"></wsdl:part>
</wsdl:message> 
<wsdl:portType name="ICustomerService"> 
<wsdl:operation name="addCustomer">
<wsdl:input message="tns:addCustomer" name="addCustomer"></wsdl:input>
<wsdl:output message="tns:addCustomerResponse" name="addCustomerResponse"></wsdl:output>
</wsdl:operation> 
</wsdl:portType> 
<wsdl:binding name="CustomerServiceImplServiceSoapBinding" type="tns:ICustomerService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
<wsdl:operation name="addCustomer">
<soap:operation soapAction="" style="document"/> 
<wsdl:input name="addCustomer">
<soap:body use="literal"/>
</wsdl:input> 
<wsdl:output name="addCustomerResponse">
<soap:body use="literal"/>
</wsdl:output> 
</wsdl:operation> 
</wsdl:binding> 
<wsdl:service name="CustomerServiceImplService">
<wsdl:port binding="tns:CustomerServiceImplServiceSoapBinding" name="CustomerServiceImplPort">
<soap:address location="http://localhost:8080/CustomerService/services/CustomerServiceImpl"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

Facebook Comments
Tags

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back to top button
Close
Close