Monday, 12 August 2013

Developing Soap web service using Spring-WS framework (top down approach)

Developing web services(Spring-WS) that start with the XML Schema/WSDL contract first followed by the Java code second. Spring-WS focuses on this development style.

The most important thing when doing contract-first Web service development is to try and think in terms of XML. This means that Java-language concepts are of lesser importance. It is the XML that is sent across the wire, and you should focus on that. The fact that Java is used to implement the Web service is an implementation detail. 

Step-1
Creating dogs.xsd:-

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.gps.co.in/dogs"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
    xmlns:tns="http://www.gps.co.in/dogs" elementFormDefault="qualified">
    <!-- Customization of JAXB conversion -->
    <annotation>
        <appinfo>
            <jaxb:globalBindings>
                <jaxb:javaType name="java.util.Date" xmlType="date" />
            </jaxb:globalBindings>
        </appinfo>
    </annotation>

    <simpleType name="DogTitle">
        <restriction base="string">
            <enumeration value="Good" />
            <enumeration value="Bad" />
            <enumeration value="Dangrous" />
            <enumeration value="KKKK" />
        </restriction>
    </simpleType>

    <simpleType name="DogID">
        <restriction base="string">
            <length value="7" />
            <pattern value="D[0-9]{7}" />
        </restriction>
    </simpleType>

    <complexType name="dog">
        <sequence>
            <element name="did" type="tns:DogID" minOccurs="1" maxOccurs="1" />
            <element name="name" type="string" maxOccurs="1" minOccurs="1" />
            <element name="dtitle" type="tns:DogTitle" maxOccurs="1"
                minOccurs="1" />
            <element name="email" type="string" maxOccurs="1" minOccurs="0" />
            <element name="color" type="string" maxOccurs="1" minOccurs="1" />
            <element name="owner" type="string" maxOccurs="1" minOccurs="0" />
            <element name="address" type="string" />
            <element name="dob" type="date" maxOccurs="1" minOccurs="1" />
        </sequence>
    </complexType>

    <element name="AddDogRequest">
        <complexType>
            <sequence>
                <element name="idogs" type="tns:dog" maxOccurs="unbounded"
                    minOccurs="0" />
            </sequence>
        </complexType>
    </element>

    <element name="AddDogResponse">
        <complexType>
            <sequence>
                <element name="dresponse" type="string" />
            </sequence>
        </complexType>
    </element>

    <element name="updateDogRequest">
        <complexType>
            <sequence>
                <element name="udog" type="tns:dog" maxOccurs="1" minOccurs="1" />
            </sequence>
        </complexType>
    </element>

    <element name="updateDogResponse">
        <complexType>
            <sequence>
                <element name="uresponse" type="string" />
            </sequence>
        </complexType>
    </element>

    <!-- Creating black input means no parameter as per java -->
    <element name="findAllDogsRequest">
        <complexType>
            <sequence />
        </complexType>
    </element>

    <element name="findAllDogsResponse">
        <complexType>
            <sequence>
                <element name="rdogs" type="tns:dog" maxOccurs="unbounded"
                    minOccurs="0" />
            </sequence>
        </complexType>
    </element>


    <!-- Creating black input means no parameter as per java -->
    <element name="deleteDogByIdRequest">
        <complexType>
            <sequence>
                <element name="pdid" type="tns:DogID" nillable="false" />
            </sequence>
        </complexType>
    </element>

    <element name="deleteDogByIdResponse">
        <complexType>
            <sequence>
                <element name="drdog" type="string" />
            </sequence>
        </complexType>
    </element>

</schema> 




Step-2

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:sws="http://www.springframework.org/schema/web-services"
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/web-services                     
    http://www.springframework.org/schema/web-services/web-services-2.0.xsd">
    <!-- To generate dynamic wsdl This configuration is for WSDL generation
        as per the XSD -->


    <sws:dynamic-wsdl id="dogs" portTypeName="DogsService"
        locationUri="/dogsService" targetNamespace="http://www.gps.co.in/dogs"
        createSoap12Binding="true" serviceName="DogsServiceImpl">


        <sws:xsd location="/WEB-INF/schema/dogs.xsd" />



</sws:dynamic-wsdl>

</beans>    


id- represent the name of WSDL file i.e. wsdl file name would be = dogs.wsdl

DogsService= name of the interface


dogsService=location URL where web service would be published



Step-3 

Creating Web Service Endpoint

package com.spring.ws.endpoint;

import in.co.gps.dogs.AddDogRequest;
import in.co.gps.dogs.AddDogResponse;
import in.co.gps.dogs.Dog;
import in.co.gps.dogs.DogTitle;
import in.co.gps.dogs.FindAllDogsRequest;
import in.co.gps.dogs.FindAllDogsResponse;

import javax.annotation.PostConstruct;

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;

@Endpoint //marking this class as a web service endpoint
public class DogsEndpoint {
   

   @PayloadRoot(localPart = "AddDogRequest", namespace = "http://www.gps.co.in/dogs")
  
@ResponsePayload
       public AddDogResponse  addDog(@RequestPayload AddDogRequest request) {
           AddDogResponse addDogResponse =new AddDogResponse();
           addDogResponse.setDresponse("I am fine here!!!");
           return addDogResponse;
       }
  

 @PayloadRoot(localPart = "findAllDogsRequest", namespace = "http://www.gps.co.in/dogs")
  @ResponsePayload
       public FindAllDogsResponse  findAllDogs(@RequestPayload FindAllDogsRequest request) {
           FindAllDogsResponse findAllDogsResponse =new FindAllDogsResponse();
           Dog dog1=new Dog();
           dog1.setDid("G8282");
           dog1.setName("D1");
           dog1.setColor("white");
           dog1.setDtitle(DogTitle.GOOD);
           findAllDogsResponse.getRdogs().add(dog1);
           return findAllDogsResponse;
       }

}



Step - 4

pom.xml
 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>apache</groupId>
  <artifactId>spring-ws-it</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>spring-ws-it Maven Webapp</name>
  <url>http://maven.apache.org</url>
 <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>2.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.ws.commons.schema</groupId>
            <artifactId>XmlSchema</artifactId>
            <version>1.4.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <scope>compile</scope>
            <version>1.2.16</version>
        </dependency>
        <!--  Spring ws specific dependency 

        -->
        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.0.5.RELEASE</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.0.5.RELEASE</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <!-- Hibernate dependency -->
        <dependency>
            <groupId>commons-digester</groupId>
            <artifactId>commons-digester</artifactId>
            <version>2.1</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.3.2.GA</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.1</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-annotations</artifactId>
            <version>3.4.0.GA</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>jboss</groupId>
            <artifactId>javassist</artifactId>
            <version>3.7.ga</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.14</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
    </dependencies>
   
     <build>
    <finalName>spring-ws-it</finalName>
     <plugins>
         <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <schemaDirectory>src/main/webapp/WEB-INF/schema</schemaDirectory>
                     <generatePackage>com.spring.ws.jaxb</generatePackage>
                    <generateDirectory>src/main/java</generateDirectory>
                </configuration>
            </plugin>
    
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.0.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                  <artifactId>maven-eclipse-plugin</artifactId>
                  <configuration>
                         <downloadSources>false</downloadSources> 
                   </configuration>     
             </plugin>
        </plugins>
  </build>
</project>





 
For the WSDL generation, the web.xml has to be modified as well, just add the init-param lines:



<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">

    <display-name>Archetype Created Web Application</display-name>
   
     <context-param>
             <param-name>contextConfigLocation</param-name>
             <param-value>/WEB-INF/applicationContext.xml</param-value>
       </context-param>
      
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


  <!-- Controller for Spring -WS web service -->
    <servlet>
        <servlet-name>spring-ws-vehicle</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
       
        <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>/WEB-INF/spring-ws-vehicle-servlet.xml</param-value>
        </init-param>
         <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
        </init-param>

  </servlet>

    <servlet-mapping>
        <servlet-name>spring-ws-vehicle</servlet-name>
        <url-pattern>/ws/*</url-pattern>
    </servlet-mapping>

</web-app>


 

1 comment: