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 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.

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

We need to set-up the project  environment first. Please download the following JARs.

Versions Used :

CXF 2.2.2           Download Link : CXF Site Download Link

Spring 2.5.6       Download Link : SpringSource Download site

The following jars are required for all CXF usage: But you will be getting it through CXF Download.
– cxf.jar
– commons-logging.jar
– geronimo-activation.jar (Or the Sun equivalent) [6]
– geronimo-annotation.jar (Or the Sun equivalent) [6]
– geronimo-javamail.jar (Or the Sun equivalent) [6]
– geronimo-stax-api.jar (Or the Sun equivalent) [6]
– neethi.jar
– jaxb-api.jar  [6]
– jaxb-impl.jar
– XmlSchema.jar
– wstx-asl.jar  [6]
– wsdl4j.jar

The following jars are required for XML catalog support:
– xml-resolver.jar

For Java2WSDL and WSDL2Java:
– The above jars
– jaxb-xjc.jar
– velocity.jar
– commons-collections.jar
– commons-lang.jar

For JAX-WS support:
– geronimo-ws-metadata.jar [6]
– geronimo-jaxws_2.1_spec-1.0.jar (Or the Sun equivalent) [6]
– saaj-api.jar [6]
– saaj-impl.jar [6]
– asm.jar (semi-optional, helps with performance of wrapper types and is
        required when adding JAXB annotations onto the SEI methods and
    parameters.)

For XML Configuration support:
– aopalliance.jar
– spring-beans.jar
– spring-context.jar
– spring-core.jar
– spring.web.jar
– FastInfoset.jar

For standalone HTTP support:
– geronimo-servlet.jar
– jetty.jar
– jetty-util.jar
– sl4j.jar & sl4j-jdk14.jar (optional – but improves logging)
For Aegis support:
– jdom.jar (optional, if you want to map xsd:anyType to JDOM)

For WS-Security support:
– bcprov-jdk15.jar
– xalan.jar
– serializer.jar
– wss4j.jar
– xmlsec.jar

For HTTP Binding support:
– jra.jar
– jettison.jar (Needed for JSON services only)

For JAX-RS support:
– abdera*
– axiom*
– jsr311-api.jar
– jettison.jar (Needed for JSON services only)

For JMS transport
– geronimo-jms.jar (Or the Sun equivalent)
– spring-jms.jar

For CORBA support:
– antlr.jar

If you want to use Aegis databinding which is providing by CXF then:

Download :jdom-1.0.jar

For Spring you can download its latest version say 2.5.

Step 2: Creating a Project

  • Open your IDE ( I am using Eclipse) and create a Web project. Lets say with Name CXFExample.

Project

  • Create a package say “com.your.company.service”
  • Create a POJO class with a name say “Product”. And include some properties like productName etc.
   1: package com.your.company.service;
   2:  
   3: import org.apache.cxf.aegis.type.java5.IgnoreProperty;
   4:  
   5: public final class Product {
   6:     private String itemName;
   7:     private String category;
   8:     private double price;
   9:     private String details;
  10:  
  11:     public Product() {
  12:     }
  13:  
  14:     public Product(String itemName, String category, double price,
  15:             String details) {
  16:         this.itemName = itemName;
  17:         this.category = category;
  18:         this.price = price;
  19:         this.details = details;
  20:     }
  21:  
  22:     public String getItemName() {
  23:         return itemName;
  24:     }
  25:  
  26:     public void setItemName(String itemName) {
  27:         this.itemName = itemName;
  28:     }
  29:  
  30:     public String getCategory() {
  31:         return category;
  32:     }
  33:  
  34:     public void setCategory(String category) {
  35:         this.category = category;
  36:     }
  37:  
  38:     public double getPrice() {
  39:         return price;
  40:     }
  41:  
  42:     public void setPrice(double price) {
  43:         this.price = price;
  44:     }
  45:  
  46:     @IgnoreProperty
  47:     public String getDetails() {
  48:         return details;
  49:     }
  50:  
  51:     public void setDetails(String details) {
  52:         this.details = details;
  53:     }
  54:  
  55: }

Note that we used one Annotation from Aegis. Its just to get some idea about that annotation. As you know Aegis is using for data binding. As the annotation denotes if we are mentioning it is not needed in the WSDL file.

  • Creating the Service Interface
   1: package com.your.company.service;
   2:  
   3: import java.util.List;
   4:  
   5: import javax.jws.WebParam;
   6: import javax.jws.WebService;
   7:  
   8: @WebService
   9: public interface ProductService {
  10:  
  11:     List<Product> getProducts();
  12:  
  13:     void addProduct(@WebParam(name = "product") Product product);
  14:  
  15:     public void addProducts(@WebParam(name = "products") List<Product> products);
  16:  
  17: }

Here we are using @WebService annotation and @WebParam Annotations. They are JAX-WS annotations.

@WebService is using to denote this Interface as the Web Service Interface. So while creating WSDL file this will consider.

@WebParam is using to name the Arguments in the WSDL file. Default it will be like Arg0, Arg1 etc. But if we are giving some names then that will be more identifiable in the WSDL.

  • Create the Service Implementation class
   1: package com.your.company.service;
   2:  
   3: import java.util.ArrayList;
   4: import java.util.List;
   5:  
   6: import javax.jws.WebParam;
   7: import javax.jws.WebService;
   8:  
   9: @WebService(endpointInterface = "edu.web.service.ProductService")
  10: public final class ProductServiceImpl implements ProductService {
  11:  
  12:     public List<Product> getProducts() {
  13:         List<Product> products = new ArrayList<Product>();
  14:         products.add(new Product("SpringInAction", "Manning", 200,
  15:                 "Book about Spring"));
  16:         products.add(new Product("EJB3InAction", "Manning", 200,
  17:                 "Book about EJB3"));
  18:         return products;
  19:     }
  20:  
  21:     @Override
  22:     public void addProduct(Product product) {
  23:         System.out.println(product);
  24:     }
  25:  
  26:     @Override
  27:     public void addProducts(@WebParam(name = "products") List<Product> products) {
  28:         for (Product product : products) {
  29:             System.out.println(product);
  30:         }
  31:     }
  32: }

Here we are writing the Impls of our Interface methods. @WebService annotation is marking this class as a web service implementation

In the next PART we will be discussing about the Configurations.

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.