Simple Web Service Using Spring

Creating Web Service Using Spring

This article will show how to create a simple web service using spring provided infrastructure.  We will also see how the dependency injection, inversion control mechanism and other features of spring can be used in web service applications.

High level steps to create our web service using spring are :

  • Use Case:

We will design a simple web service using spring which will tell if the given number if even or not.

  • Create a maven webapp project:

Change to your project directory and create a maven webapp project using the following command.

mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=com.codereq.springwsone -DartifactId=springws-one

On executing this command , a project directory springws-one will be created.

We will call this as out SWS_DIR

  • Maven POM file :

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>com.codereq.springwsone</groupId>
    <artifactId>springws-one</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>springws-one Spring-WS Application</name>
    <url>http://www.springframework.org/spring-ws</url>
    <properties>
    	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <build>
        <finalName>springws-one</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>tomcat-maven-plugin</artifactId>
                <version>1.1</version>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.1.1</version>
                <configuration>
                    <packagingExcludes>WEB-INF/web.xml</packagingExcludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ws</groupId>
            <artifactId>spring-ws-core</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
       	    <groupId>javax.xml</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
	    <groupId>jdom</groupId>
	    <artifactId>jdom</artifactId>
	    <version>2.0</version>
	</dependency>
    </dependencies>
</project>

 

  • Design Schema:

The schema for representing the request and response will be  :

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
	   xmlns:ms="http://codereq.com/mathservice/schemas" 
	   elementFormDefault="qualified" 
	   targetNamespace="http://codereq.com/mathservice/schemas">
    <xs:element name="MathServiceRequest">
        <xs:complexType>
	    <xs:sequence>
	        <xs:element name="Number" type="xs:integer"/>
	    </xs:sequence>
	</xs:complexType>
    </xs:element>
    <xs:element name="MathServiceResponse">
        <xs:complexType>
	    <xs:sequence>
	        <xs:element name="Number" type="xs:integer"/>
		<xs:element name="isEven" type="xs:boolean" />
	    </xs:sequence>
	</xs:complexType>
    </xs:element>
</xs:schema>

The schema represents two elements : MathServiceRequest and MathServiceResponse  defined in namespace http://codereq.com/mathservice/schemas

Copy the schema to <<sws_dir>>/src/main/resources folder.

  • Convert Schema to Java class:

Use the xjc tool to convert the schemas to java classes.

cd <<SWS_DIR>>/src/main/resources

xjc -d ../java MathService.xsd

On executing this command, the java classes corresponding to schemas will be created. They will be MathServiceRequest.java and MathServiceResponse.java. Apart from these classes, ObjectFactory.java and package-info.java will also be created.

MathServiceRequest.java :

package com.codereq.mathservice.schemas;

import java.math.BigInteger;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "number"
})
@XmlRootElement(name = "MathServiceRequest")
public class MathServiceRequest {

    @XmlElement(name = "Number", required = true)
    protected BigInteger number;

    /**
     * Gets the value of the number property.
     * 
     * @return
     *     possible object is
     *     {@link BigInteger }
     *     
     */
    public BigInteger getNumber() {
        return number;
    }

    /**
     * Sets the value of the number property.
     * 
     * @param value
     *     allowed object is
     *     {@link BigInteger }
     *     
     */
    public void setNumber(BigInteger value) {
        this.number = value;
    }

}
MathServiceResponse.java
package com.codereq.mathservice.schemas;

import java.math.BigInteger;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "number",
    "isEven"
})
@XmlRootElement(name = "MathServiceResponse")
public class MathServiceResponse {

    @XmlElement(name = "Number", required = true)
    protected BigInteger number;
    protected boolean isEven;

    /**
     * Gets the value of the number property.
     * 
     * @return
     *     possible object is
     *     {@link BigInteger }
     *     
     */
    public BigInteger getNumber() {
        return number;
    }

    /**
     * Sets the value of the number property.
     * 
     * @param value
     *     allowed object is
     *     {@link BigInteger }
     *     
     */
    public void setNumber(BigInteger value) {
        this.number = value;
    }

    /**
     * Gets the value of the isEven property.
     * 
     */
    public boolean isIsEven() {
        return isEven;
    }

    /**
     * Sets the value of the isEven property.
     * 
     */
    public void setIsEven(boolean value) {
        this.isEven = value;
    }
}
  • Configure the web.xml

Since the spring web service is a web based application, we need to configure the web.xml in a way that any incoming request will be mapped to spring specific servlet. This servlet will be responsible to identify our endpoint implementations and delegate the request to them.

The location on web.xml is : <sws_dir>/src/main/resources

web.xml

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

    <servlet>
        <servlet-name>spring-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
      		<param-name>transformWsdlLocations</param-name>
      		<param-value>true</param-value>
    	</init-param>
    </servlet>

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

The web.xml is configured such that all the incoming requests will be handled by MessageDispathcherServlet class. This is spring specific class responsible to map the incoming requests to configured Endpoint annotated classes.

 

  • Develop the sever side implementation :

The endpoint implementation class is annotated with @Endpoint  which will enable the spring’s MessageDispatcherServlet to direct the incoming requests to this class.

The method which will handle the web service request will be annotated with @PayloadRoot. The @PayloadRoot will have parameters which will indicate what payload will be handled by the method. It has the following format :

@PayloadRoot(namespace = "http://codereq.com/mathservice/schemas" ,localPart="MathServiceRequest")

The attributes tell that any incoming request xml which has MathServiceRequest element in namespace ” http://codereq.com/mathservice/schemas ” will be handled by this method.

MathServiceEndpoint.java

package com.codereq.springwsone;

import org.springframework.beans.factory.annotation.Autowired;
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;

import com.codereq.mathservice.schemas.MathServiceRequest;
import com.codereq.mathservice.schemas.MathServiceResponse;

@Endpoint
public class MathServiceEndPoint {

    @Autowired
    MathService mathService ;

    @PayloadRoot(namespace = "http://codereq.com/mathservice/schemas" ,localPart="MathServiceRequest")
    public @ResponsePayload MathServiceResponse handleMathServiceRequest(@RequestPayload MathServiceRequest mathServiceRequest) {
        boolean isEven = getMathService().isEven(mathServiceRequest.getNumber().intValue());
	MathServiceResponse r = new MathServiceResponse();
	r.setIsEven(isEven);
	r.setNumber(mathServiceRequest.getNumber());
	return r;
    }

    public MathService getMathService() {
	return mathService;
    }

    public void setMathService(MathService mathService) {
	this.mathService = mathService;
    }
}

The primary method in this class is the handleMathServiceRequest which is annotated with @PayloadRoot. The parameter are annotated with @RequestPayload which tells that the parameter should be bound to request payload. Similarly, the return type MathServiceResponse is annotated with @ResponePayload which will bind the response with response payload.

The spring configuration file is named spring-ws-servlet.xml. The name is derived from name of servlet and appended with servlet. <>-servlet.xml. The file should be located at  <<sws_dir><sws_dir><sws_dir>>/src/main/resources folder:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions	xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
			xmlns:tns="http://codereq.com/MathService/" 
			xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
			xmlns:xsd="http://www.w3.org/2001/XMLSchema"
			xmlns:mathschema="http://codereq.com/mathservice/schemas" 
			name="MathService" 
			targetNamespace="http://codereq.com/MathService/">
  <wsdl:types>
  	<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
		<xsd:import namespace="http://codereq.com/mathservice/schemas" schemaLocation="MathService.xsd"/>
	</xsd:schema>
  </wsdl:types>
  <wsdl:message name="MathServiceRequest">
    <wsdl:part element="mathschema:MathServiceRequest" name="MathServiceRequest"/>
  </wsdl:message>
  <wsdl:message name="MathServiceResponse">
    <wsdl:part element="mathschema:MathServiceResponse" name="MathServiceResponse"/>
  </wsdl:message>
  <wsdl:portType name="MathServicePortType">
    <wsdl:operation name="MathServiceOperation">
      <wsdl:input message="tns:MathServiceRequest"/>
      <wsdl:output message="tns:MathServiceResponse"/>
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="MathServiceSOAPBinding" type="tns:MathServicePortType">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="MathServiceOperation">
      <soap:operation soapAction="http://www.codereq.com/MathService/MathServiceOperation"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="MathService">
    <wsdl:port binding="tns:MathServiceSOAPBinding" name="MathServiceSOAP">
      <soap:address location="http://localhost:8080/mathservice"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
  • Compile  and deploy.

Compile the application using mvn clean install from SWS_DIR . Once the war is generated in the target folder, copy the war to servlet container and deploy.

Leave a Reply

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


− one = 3

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>