Creating Web Services using CXF (Contract first Approach) Part 2 : WSDL Creation.

What is WSDL and what its Structure?

A WSDL document defines services as collections of network endpoints, or ports. In WSDL, the abstract definition of endpoints and messages is separated from their concrete network deployment or data format bindings. This allows the reuse of abstract definitions: messages, which are abstract descriptions of the data being exchanged, and port types which are abstract collections of operations.

The concrete protocol and data format specifications for a particular port type constitutes a reusable binding. A port is defined by associating a network address with a reusable binding, and a collection of ports define a service. Hence, a WSDL document uses the following elements in the definition of network services:

WSDL document describes a web service using these major elements:

Element Defines
<types> The data types used by the web service
<message> The messages used by the web service
<portType> The operations performed by the web service
<binding> The communication protocols used by the web service
<port> A single endpoint defined as a combination of a binding and a network address.
<service> A collection of related endpoints.

The main structure of a WSDL document looks like this:

<definitions>
<types>
definition of types……..
</types>

<message>
definition of a message….
</message>
             <portType>
definition of a port…….
</portType>
           
<binding>
definition of a binding….
</binding>

              <service>
definition of services….
</service>

</definitions>

A WSDL document can also contain other elements, like extension elements and a service element that makes it possible to group together the definitions of several web services in one single WSDL document.

Creating WSDL for our Example

<types>:In the Types we are defining or configuring the Datatypes which we are using for the entire application. Here we are importing the XSD files here.

<message>:In our example we need to configure our input and our parameters/ the message which we are passing through Webservice. We are configuring request and response objects here.

<portType>: We have one operation which is called getProduct. So here we need to declare this getProduct operation.

<binding> : Here we will be providing our protocol types and we are using SOAP protocol.

<service> : Defining the Service End point. And for the ProductService we are defining it as “http://localhost:8080/ContractFirst/services/ProductService

 

   1: <?xml version="1.0" encoding="UTF-8" standalone="no"?>
   2: <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
   3:     xmlns:tns="http://com/your/company/service/ProductService/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
   4:     xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="ProductService"
   5:     targetNamespace="http://com/your/company/service/ProductService/"
   6:     xmlns:prd="http://com/your/company/service/Product/">
   7:     <wsdl:types>
   8:         <xsd:schema targetNamespace="http://com/your/company/service/ProductService/"
   9:             xmlns:prd="http://com/your/company/service/Product/">
  10:             <xsd:import namespace="http://com/your/company/service/Product/"
  11:                 schemaLocation="../Product.xsd" />
  12:             <xsd:element name="getProductRequest">
  13:                 <xsd:complexType>
  14:                     <xsd:sequence>
  15:                         <xsd:element name="productRequest" type="prd:ProductRequest" />
  16:                     </xsd:sequence>
  17:                 </xsd:complexType>
  18:             </xsd:element>
  19:             <xsd:element name="getProductResponse">
  20:                 <xsd:complexType>
  21:                     <xsd:sequence>
  22:                         <xsd:element name="productResponse" type="prd:ProductResponse" />
  23:                     </xsd:sequence>
  24:                 </xsd:complexType>
  25:             </xsd:element>
  26:         </xsd:schema>
  27:     </wsdl:types>
  28:     <wsdl:message name="ProductRequest">
  29:         <wsdl:part element="tns:getProductRequest" name="parameters" />
  30:     </wsdl:message>
  31:     <wsdl:message name="ProductResponse">
  32:         <wsdl:part element="tns:getProductResponse" name="parameters" />
  33:     </wsdl:message>
  34:     <wsdl:portType name="ProductService">
  35:         <wsdl:operation name="getProduct">
  36:             <wsdl:input message="tns:ProductRequest" />
  37:             <wsdl:output message="tns:ProductResponse" />
  38:         </wsdl:operation>
  39:     </wsdl:portType>
  40:     <wsdl:binding name="ProductServiceSOAP" type="tns:ProductService">
  41:         <soap:binding style="document"
  42:             transport="http://schemas.xmlsoap.org/soap/http" />
  43:         <wsdl:operation name="getProduct">
  44:             <soap:operation
  45:                 soapAction="http://com/your/company/service/ProductService/getProduct" />
  46:             <wsdl:input>
  47:                 <soap:body use="literal" />
  48:             </wsdl:input>
  49:             <wsdl:output>
  50:                 <soap:body use="literal" />
  51:             </wsdl:output>
  52:         </wsdl:operation>
  53:     </wsdl:binding>
  54:     <wsdl:service name="ProductService">
  55:         <wsdl:port binding="tns:ProductServiceSOAP" name="ProductServiceSOAP">
  56:             <soap:address
  57:                 location="http://localhost:8080/ContractFirst/services/ProductService" />
  58:         </wsdl:port>
  59:     </wsdl:service>
  60: </wsdl:definitions>

In our next part we will go through Skelton creation using WSDL to Java tool which is giving by CXF. We will go through class path settings and wsdl2java commands.

Advertisements

Creating “Contract First” – Web Services using CXF (Top Down Approach) Part 1: Creating XSDs.

Why people are interested in CODE-FIRST approach? Answer is simple. No need to go through the complexities of XML, XSD, WSDL structure. Just code in any of your favorite programming language and create the WSDL file using any of your tools/frameworks. I had taken some interviews these days for a Webservice-SOA project. Honestly it was too difficult to find out the right candidates with good knowledge in Webservices. Most of them are just consumed webservices. And if we find somebody who developed webservices then they would be just familiar with the Code first approach and have no idea about WSDL files. Becuase just seeing WSDL in that endpoint URL finishes their works.

Here in this series of Posts I would like to put a small webservice example which is doing in “CONTRACT FIRST” approach.

If you want to go through a Code-First Approach using CXF then please check my previous posts. For your convenience I am pasting it below.

  1. Creating Web services using Apache CXF (Part 1) : The Basics.
  2. Creating Web services using Apache CXF (Part 2) : Development.
  3. Creating Web services using Apache CXF (Part 3) : Configuration.
  4. Creating Web services using Apache CXF (Part 4): Testing.

Why we require CONTRACT FIRST approach?

This article from SOA world will help you to understand. A contract-first approach results in better long-term development, interoperability, and maintenance. For larger applications, long-lasting Web services, and service-oriented architecture (SOA), contract-first thinking has advantages that usually outweigh the ease of method-first thinking. I know first exposure to Web services, WSDL and Schema are very tough to grasp but when you are coming into a BIG SOA application development people will choose contract-first. At least me!

Some of the Points for this selection are:

  • Its better to define data types and all first than converting from a programming language.
  • It makes you be very clear with both the producer and consumer of the service exactly what is needed and what is expected
  • Contract-first is the generally accepted ‘best practice”.

Creating a small webservice application using CXF

Lets start our example. Want we are trying to achieve is, we want to deploy a service called “getProduct”. If we are giving a “Composite ID” as an input to our web service then it should return a Product Details to us.

First we will start with our XSD structure. Even though this is a small service and we can define it inside the WSDL itself, we will create a separate XSD for our better understanding. We can import this XSD in the types tag of WSDL.

Creating our XSD

Here I had created one ProductDetails and one ProductId types.

Product Details contains all the product related information like productname, category, price and details. ProductId type is a composite primary key with sequence number and deptcode. I am also created a request and response types here.

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <xsd:schema targetNamespace="http://com/your/company/service/Product/"
   3:     xmlns:prd="http://com/your/company/service/Product/"
   4:     elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   5:     <xsd:complexType name="productID">
   6:         <xsd:sequence>
   7:             <xsd:element minOccurs="0" name="sequenceNumber" type="xsd:int" />
   8:             <xsd:element minOccurs="0" name="deptNumber" type="xsd:string" />
   9:         </xsd:sequence>
  10:     </xsd:complexType>
  11:     <xsd:complexType name="productDetails">
  12:         <xsd:sequence>
  13:             <xsd:element name="id" nillable="false" type="prd:productID" />
  14:             <xsd:element name="productName" nillable="false" type="xsd:string" />
  15:             <xsd:element name="category" nillable="true" type="xsd:string" />
  16:             <xsd:element name="price" nillable="false" type="xsd:long" />
  17:             <xsd:element name="details" nillable="true" type="xsd:string" />
  18:         </xsd:sequence>
  19:     </xsd:complexType>
  20:     <xsd:complexType name="ProductRequest">
  21:         <xsd:sequence>
  22:             <xsd:element name="productID" type="prd:productID" />
  23:         </xsd:sequence>
  24:     </xsd:complexType>
  25:     <xsd:complexType name="ProductResponse">
  26:         <xsd:sequence>
  27:             <xsd:element name="product" type="prd:productDetails" />
  28:         </xsd:sequence>
  29:     </xsd:complexType>
  30: </xsd:schema>

In the next PART we will be creating a small WSDL file which internally using this XSD. Points we cover are WSDL Tags, XSD inclusion, NameSpaces. <Click on this link to move to that post>

Creating Web services using Apache CXF (Part 4): Testing

To test this we can follow the same client program which is given in the CXF site.

Just create a simple Java class and execute it.

 1: package com.your.company.service.client;
 2:
 3: import java.util.List;
 4:
 5: import org.apache.cxf.interceptor.LoggingInInterceptor;
 6: import org.apache.cxf.interceptor.LoggingOutInterceptor;
 7: import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
 8:
 9: import com.your.company.service.Product;
 10: import com.your.company.service.ProductService;
 11:
 12: public final class Client {
 13:
 14:     private Client() {
 15:     }
 16:
 17:     public static void main(String args[]) throws Exception {
 18:
 19:         JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
 20:
 21:         factory.getInInterceptors().add(new LoggingInInterceptor());
 22:         factory.getOutInterceptors().add(new LoggingOutInterceptor());
 23:         factory.setServiceClass(ProductService.class);
 24:         factory.setAddress("http://localhost:8080/CXFExample/productservice");
 25:         ProductService client = (ProductService) factory.create();
 26:
 27:         List<Product> products = client.getProducts();
 28:         if (products != null && products.size() > 0)
 29:             System.out.println("Product Name : "
 30:                     + products.get(0).getItemName() + ", Price: "
 31:                     + products.get(0).getPrice());
 32:         System.exit(0);
 33:
 34:     }
 35:
 36: }

Other related posts:

1. Creating Web services using Apache CXF (Part 1) : The Basics.

2. Creating Web services using Apache CXF (Part 2) : Development.

3. Creating Web services using Apache CXF (Part 3) : Configuration.

4. Creating Web services using Apache CXF (Part 4): Testing.

Creating Web services using Apache CXF (Part 3): Configurations

  • Web.xml Declarations

We have to declare Spring Context Listener, CXF Servlet, Spring Context Location and URL Mapping.

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <web-app id="services" version="2.5"
   3:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
   4:     xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   5:     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   6:         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   7:     
   8:     <!-- Adding the Spring Context Listener. It will help to init Spring Context -->
   9:     <listener>
  10:         <listener-class> org.springframework.web.context.ContextLoaderListener 
  11:         </listener-class>
  12:     </listener>
  13:     
  14:     <!-- Context file location of Spring -->
  15:     <context-param>
  16:         <param-name>contextConfigLocation</param-name>
  17:         <param-value>/WEB-INF/applicationContext.xml</param-value>
  18:     </context-param>
  19:     
  20:     <!-- CXF Servlet -->
  21:     <servlet>
  22:         <servlet-name>CXFServlet</servlet-name>
  23:         <servlet-class> org.apache.cxf.transport.servlet.CXFServlet 
  24:         </servlet-class>
  25:     </servlet>
  26:     
  27:     <!-- Mapping with a URL Pattern -->
  28:     <servlet-mapping>
  29:         <servlet-name>CXFServlet</servlet-name>
  30:         <url-pattern>/*</url-pattern>
  31:     </servlet-mapping>
  32: </web-app>

  • Application Context configurations
   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <beans xmlns="http://www.springframework.org/schema/beans"
   3:     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   4:     xmlns:cxf="http://cxf.apache.org/core" xmlns:jaxws="http://cxf.apache.org/jaxws"
   5:     xsi:schemaLocation="http://www.springframework.org/schema/beans
   6:         http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   7:         http://www.springframework.org/schema/context
   8:         http://www.springframework.org/schema/context/spring-context-2.5.xsd
   9:         http://cxf.apache.org/core
  10:         http://cxf.apache.org/schemas/core.xsd
  11:         http://cxf.apache.org/jaxws
  12:         http://cxf.apache.org/schemas/jaxws.xsd"
  13:     default-autowire="byName">
  14:  
  15:     <!-- Load CXF modules from cxf.jar -->
  16:     <import resource="classpath:META-INF/cxf/cxf.xml" />
  17:     <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
  18:     <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
  19:         
  20:     <!-- The service bean -->
  21:     <bean id="productServiceImpl" class="com.your.company.service.ProductServiceImpl" />
  22:  
  23:     <!-- Aegis data binding -->
  24:     <bean id="aegisBean" class="org.apache.cxf.aegis.databinding.AegisDatabinding"
  25:         scope="prototype" />
  26:     <bean id="aegis-service" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean"
  27:         scope="prototype">
  28:         <property name="dataBinding" ref="aegisBean" />
  29:         <property name="serviceConfigurations">
  30:             <list>
  31:                 <bean class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration" />
  32:                 <bean class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration" />
  33:                 <bean class="org.apache.cxf.service.factory.DefaultServiceConfiguration" />
  34:             </list>
  35:         </property>
  36:     </bean>
  37:     
  38:     <!-- Service endpoint -->
  39:     <jaxws:endpoint id="productService"
  40:         implementorClass="com.your.company.service.ProductServiceImpl"
  41:         implementor="#productServiceImpl" address="/productservice">
  42:         <jaxws:serviceFactory>
  43:             <ref bean="aegis-service" />
  44:         </jaxws:serviceFactory>
  45:     </jaxws:endpoint>
  46:     
  47:         <!-- Enable message logging using the CXF logging feature -->
  48:     <cxf:bus>
  49:         <cxf:features>
  50:             <cxf:logging />
  51:         </cxf:features>
  52:     </cxf:bus>
  53: </beans>

Create a WAR out of this Project and deploy it in Apache Tomcat. And try to access the WSDL URL

 http://localhost:8080/CXFExample/ProductService?wsdl.

Other related posts:

1. Creating Web services using Apache CXF (Part 1) : The Basics.

2. Creating Web services using Apache CXF (Part 2) : Development.

3. Creating Web services using Apache CXF (Part 3) : Configuration.

4. Creating Web services using Apache CXF (Part 4): Testing.