Pages

Thursday 25 October 2012

Contract First or WSDL First Web Service (Top-Down Approach)

In the Contract first approach, we take first like schema, wsdl contract creation and followed by business logic of service in code, therefore in the contract first approach, the focus is creating schema associated with wsdl. WSDL and Schema has to define message format, operations, interface name and other information for the web service. After creating the WSDL and schema, we can create service from wsdl/schema using some web service framework. All major Web service frameworks allow service generation from WSDLs, and the all Service code is generated by the service framework, only the necessary business logic would need to be writing in Implement Class.

Contract First Web Service:
Contract first web Service,we need to follows the step

1-First write a schema  xsd and wsdl file.
2-Generate Interface and other code using service engine from wsdl.
3-Add business logic of service interface Implementation.
4- Expose interface with business logic as web services.
5-Service would be available for client,We can use Soap UI tool or other tools for client.

POC of Contract First Web Service:
I have been going to be create Contract first web service using Eclipse IDE and Apache CXF Service Framework.
So we need eclipse with Apache CXF engine.
For setup of eclipse for web service creation, you can refer my previous blog "Code First",URL is http://dtechtalkcenter.blogspot.in/2012/10/creating-code-first-web-service-bottom.html

Create a Dynamic Web Project:

Project Name:  ContractFirstService
Target Runtime:  tomcat 7          
Configuration:  Click on modify button and select check box of Apache CXF.


Designing XSD schema:
I create a simple xsd schema(productservice_schema.xsd) with two requests like addProduct and getProduct with respective response addProductResponse and getProductResponse.Also define the Product object in xsd.

<?xml version="1.0" encoding="utf-8"?>
<!--Define the document element first -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.dtechtalkcenter.com/" elementFormDefault="unqualified" targetNamespace="http://service.dtechtalkcenter.com/" version="1.0">
<!--Define the element first like addProduct,addProductResponse and getProducts,getProductsResponse -->
<xs:element name="addProduct" type="tns:addProduct"/>
<xs:element name="addProductResponse" type="tns:addProductResponse"/>
<xs:element name="getProducts" type="tns:getProducts"/>
<xs:element name="getProductsResponse" type="tns:getProductsResponse"/>

<!-- getProducts complex type -->
<xs:complexType name="getProducts">
    <xs:sequence/>
  </xs:complexType>

  <!-- getProductsResponse complex type and return type is product-->
<xs:complexType name="getProductsResponse">
    <xs:sequence>
      <xs:element maxOccurs="unbounded" minOccurs="0" name="return" type="tns:product"/>
    </xs:sequence>
  </xs:complexType>
  
 <!-- product complex type and The element of product object type are cast,productCategory,productDetails and productName are double,-->
<xs:complexType name="product">
    <xs:sequence>
      <xs:element name="cast" type="xs:double"/>
      <xs:element minOccurs="0" name="productCategory" type="xs:string"/>
      <xs:element minOccurs="0" name="productDetails" type="xs:string"/>
      <xs:element minOccurs="0" name="productName" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>

  <!-- addProduct complex type -->
<xs:complexType name="addProduct">
    <xs:sequence>
      <xs:element minOccurs="0" name="product" type="tns:product"/>
    </xs:sequence>
  </xs:complexType>

    <!-- addProductResponse complex type and there is no return -->
<xs:complexType name="addProductResponse">
    <xs:sequence/>
  </xs:complexType>
</xs:schema>

Service Contract OR WSDL Designing:
WSDL file is generally defined as service contract.So I have created a wsdl document(productserviceimpl.wsdl) with two operation getProducts and addProducts.

<?xml version="1.0" encoding="UTF-8"?>
<!--DOCTYPE wsdl:definitions PUBLIC "  give serviceName,targeNameSpace and diffrent nameSpace like wsdl,soap,schema etc.-->
<wsdl:definitions name="ProductServiceImplService" targetNamespace="http://service.dtechtalkcenter.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://service.dtechtalkcenter.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

  <!-- import the schema in the wsdl:type tag -->
  <wsdl:types>
    <schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://service.dtechtalkcenter.com/" schemaLocation="productservice_schema.xsd"/>
</schema>
  </wsdl:types>

  <!-- We define the addProduct request message, which gets used in the portType(ProductService) and The addProduct request type is defined in the schema. -->
  <wsdl:message name="addProduct">
    <wsdl:part name="parameters" element="tns:addProduct">
    </wsdl:part>
  </wsdl:message>

  <!-- We define the getProducts request message, which gets used in the portType(ProductService) and The getProducts request type is defined in the schema. -->
  <wsdl:message name="getProducts">
    <wsdl:part name="parameters" element="tns:getProducts">
    </wsdl:part>
  </wsdl:message>

  <!-- We define response of respective request -->
  <wsdl:message name="getProductsResponse">
    <wsdl:part name="parameters" element="tns:getProductsResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="addProductResponse">
    <wsdl:part name="parameters" element="tns:addProductResponse">
    </wsdl:part>
  </wsdl:message>

  <!-- We define the ProductService Interface port type, which gets used in the binding. -->
  <wsdl:portType name="ProductService">
    <wsdl:operation name="getProducts">
      <wsdl:input name="getProducts" message="tns:getProducts">
    </wsdl:input>
      <wsdl:output name="getProductsResponse" message="tns:getProductsResponse">
    </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="addProduct">
      <wsdl:input name="addProduct" message="tns:addProduct">
    </wsdl:input>
      <wsdl:output name="addProductResponse" message="tns:addProductResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  
  <!-- We use a document/literal style and The literal http://schemas.xmlsoap.org/soap/http signifies a HTTP transport. -->
  <!-- We define the ProductServiceImplServiceSoapBinding binding, which gets used in the port.. -->  
    <wsdl:binding name="ProductServiceImplServiceSoapBinding" type="tns:ProductService">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getProducts">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="getProducts">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getProductsResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="addProduct">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="addProduct">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="addProductResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>

  <!-- The http://localhost:8080/ContractFirstService/services/ProductServiceImplPort address is the URL where the Web service can be invoked. -->
  <wsdl:service name="ProductServiceImplService">
    <wsdl:port name="ProductServiceImplPort" binding="tns:ProductServiceImplServiceSoapBinding">
      <soap:address location="http://localhost:8080/ContractFirstService/services/ProductServiceImplPort"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Generate Service From WSDL Document:
Just we need to right click on the project and select web service from eclipse wizard.
Web Service Type:  Top down Java Bean web service
Service definition : Select wsdl document like productserviceimpl.wsdl
Select Service runtime : apache CXF
then click next.


Select Apache CXF here and click on ok default Axis is selected.


Then Click on next button of web services wizard and select different option
Output directory :  \ContractFirstService\src
Package Name :  com.dtechtalkcenter.service
select the check box of Specify  wsdl.....and click finish button.



Now service is generated with java code from wsdl and deployed service.

Add business logic:
Generated code through the wsdl in show screen shot below.


Added business logic of service interface implementation 


/**
 * Please modify this class to meet your needs
 * This class is not complete
 */

package com.dtechtalkcenter.service;

import java.util.logging.Logger;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * This class was generated by Apache CXF 2.6.2
 * 2012-10-25T10:46:28.508+05:30
 * Generated source version: 2.6.2
 * 
 */

@javax.jws.WebService(
                      serviceName = "ProductServiceImplService",
                      portName = "ProductServiceImplPort",
                      targetNamespace = "http://service.dtechtalkcenter.com/",
                      wsdlLocation = "http://localhost:8080/ContractFirstService/services/ProductServiceImplPort?wsdl",
                      endpointInterface = "com.dtechtalkcenter.service.ProductService")
                      
public class ProductServiceImpl implements ProductService {

    private static final Logger LOG = Logger.getLogger(ProductServiceImpl.class.getName());

    /* (non-Javadoc)
     * @see com.dtechtalkcenter.service.ProductService#getProducts(*
     */
    public java.util.List<com.dtechtalkcenter.service.Product> getProducts() { 
        LOG.info("Executing operation getProducts");
        try {
            java.util.List<com.dtechtalkcenter.service.Product> retproducts = new java.util.ArrayList<com.dtechtalkcenter.service.Product>();
            com.dtechtalkcenter.service.Product product = new com.dtechtalkcenter.service.Product();
           /* _returnVal1.setCast(0.7524456455666023);
            _returnVal1.setProductCategory("ProductCategory1751630664");
            _returnVal1.setProductDetails("ProductDetails1256153209");
            _returnVal1.setProductName("ProductName1328378982");
            _return.add(_returnVal1);*/
            
            //We need to write business logic of service interface."Here i have written the sample business logic //for getProduct opertaion"
            product.setCast(200);
            product.setProductCategory("OS");
            product.setProductDetails("Linux server");
            product.setProductName("Linux");
            retproducts.add(product);
            
            com.dtechtalkcenter.service.Product product1 = new com.dtechtalkcenter.service.Product();
            product1.setCast(2000);
            product1.setProductCategory("Database");
            product1.setProductDetails("oracle data for production");
            product1.setProductName("Oracle10");
            retproducts.add(product1);

            
            return retproducts;
        } catch (java.lang.Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

    /* (non-Javadoc)
     * @see com.dtechtalkcenter.service.ProductService#addProduct(com.dtechtalkcenter.service.Product  product )*
     */
    public void addProduct(com.dtechtalkcenter.service.Product product) { 
        LOG.info("Executing operation addProduct");
        System.out.println(product);
        try {
        } catch (java.lang.Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }
}

 Expose Interface as web services:
After addition of the business logic the interface would be deployed as service on the web server.
Wsdl url is for that service 

Client of Service using Soap UI:
If you can view WSDL and XSD, you are finish to deploy Web Service on application server. We can use soapUI to simulate Web Service Client

Download address: http://sourceforge.net/projects/soapui/files/

Please select installable file to download. When you installed sopaUI, please follow below step to simulate Web Service Client.

    File -> New soapUI Project
    Project name : ContractFirstService
 and click ok button.

Now, you can see two web service function name in the tree. Open addProduct and getProducts to get request 1. Left window will display below XML content:


click on the request of service and just submit the request through soap ui to service.


In this screen shot you can see the response of the service in the red box.


2 comments:

  1. Have been looking all over the web for a good top-down cxf implementation. Finally found here. I now understand how to implement top down cxf impl which is what most real world apps use not bottom up.

    Thank you for the simple elegant tutorial.

    ReplyDelete
  2. The Best Tutorial I have seen on the web for contract first web service development.

    ReplyDelete