Spring Web Service Example

  • Web service is medium by which, any two application can communicate with one another over internet.
  • The WSDL(Web Services Description Language) is a xml file is used to describe a web service, it specifies the service location and the operations that service exposes.
  • The system communicates using the SOAP (Simple Object Access protocol) messages. The SOAP messages are xml based and are used to send request and response messages.
  • There are two approaches for developing web services: Contract First and Contract last.
  • In the Contract First approach you first create the contract (XML) and write the Java code to implement the contract.
  • In the Contract Last approach you first write the Java code and later create a Contract (WSDL) for the code.
  • Spring Web Service is the module of Spring framework that can used to develop SOAP based Contract First Web Services.
  • While developing Contract First the focus is always on XML files, you need to think in terms of XML.

The Spring WS consists of the Core module, XML module, OXM module and the Security module.
Let’s take an example of a very simple web service to understand how web services can be implemented using Spring WS.
The following web service takes in name as an input parameter and responds with a hello message.
This example uses JiBX for marshaling and maven for running the application.
Steps for creating a web service

1. Creating the contract

The first step in contract first web service would be to define the schema for the request and the response messages

/WEB-INF/xsd/hello.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://in.javadigest/HelloService/"
  elementFormDefault="qualified">
  <xsd:element name="HelloRequest">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="in" type="xsd:string" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="HelloResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="out" type="xsd:string" />
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Example of SOAP request and response xmls for the above schema

Request.xml

<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:hel="http://in.javadigest/HelloService/">
  <soapenv:Header />
  <soapenv:Body>
    <hel:HelloRequest>
      <hel:in>User</hel:in>
    </hel:HelloRequest>
  </soapenv:Body>
</soapenv:Envelope>

Response.xml

<SOAP-ENV:Envelope
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header />
  <SOAP-ENV:Body>
    <hs:HelloResponse xmlns:hs="http://in.javadigest/HelloService/">
      <hs:out>Hello : User!</hs:out>
    </hs:HelloResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Based on the request and response schema, you also need to create a WSDL file; which can be done manually or use Spring to auto generate the WSDL file.

In this example, Spring bean to generate the WSDL file:
Use the following URL to view the WSDL file

http://localhost:8080/helloservice/HelloRequest.wsdl

The WSDL file will look like

<?xmlt;?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://in.javadigest/HelloService/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://in.javadigest/HelloService/" targetNamespace="http://in.javadigest/HelloService/">
  <wsdl:types>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://in.javadigest/HelloService/">
  <xsd:element name="HelloRequest">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="in" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="HelloResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="out" type="xsd:string"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>
  </wsdl:types>
  <wsdl:message name="HelloRequest">
    <wsdl:part element="tns:HelloRequest" name="HelloRequest">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="HelloResponse">
    <wsdl:part element="tns:HelloResponse" name="HelloResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="Hello">
    <wsdl:operation name="Hello">
      <wsdl:input message="tns:HelloRequest" name="HelloRequest">
    </wsdl:input>
      <wsdl:output message="tns:HelloResponse" name="HelloResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="HelloSoap11" type="tns:Hello">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="Hello">
      <soap:operation soapAction=""/>
      <wsdl:input name="HelloRequest">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="HelloResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="HelloService">
    <wsdl:port binding="tns:HelloSoap11" name="HelloSoap11">
      <soap:address location="http://localhost:8080/helloservice/services/HelloRequest"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

2. Create and define the service interface

The next step is to define the interface that would be exposed as the web service and implement the same
In this example we would take name as an input parameter and respond with a hello message.

Following is the HelloService interface and its implementation

HelloService.java

package in.javadigest.service;

public interface HelloService {

  String sayhello(String name);
}

HelloServiceImpl.java

package in.javadigest.service;

public class HelloServiceImpl implements HelloService {

  private boolean validate;

  @Override
  public String sayhello(String name) {

    if (validate && (name == null || name.trim().isEmpty())) {
      return "Error: The input name was empty.";
    }

    return "Hello : " + name + "!";
  }

  public boolean isValidate() {
    return validate;
  }

  public void setValidate(boolean validate) {
    this.validate = validate;
  }

}

 3. Creating the Object/XML binding

Rather than handling XML directly, you can convert the XML message into a Request Object and vice versa. This conversion of XML document to and from a Java Object is known as Marshalling, or XML Serialization. A marshaller serializes an object to XML, and an unmarshaller deserializes XML stream to an object.
This example uses JiBX for the purpose of marshalling and unmarshalling.

To create the Object/XML binding, we need to first create the POJO classes for the request and response

HelloRequest.java

package in.javadigest.message;

public class HelloRequest {

  private String name;

  public HelloRequest() {
    super();
  }

  public HelloRequest(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

)

HelloResponse.java

package in.javadigest.message;

public class HelloResponse {

  private String message;

  public HelloResponse() {
    super();
  }

  public HelloResponse(String message) {
    this.message = message;
  }

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }

}

And next step would be to define /XML JiBX binding for the above model classes (can also be generated usin JiBX)

helloservice_jibx_binding.xml

<?xml version="1.0" encoding="UTF-8"?>
<binding>
  <mapping name="HelloRequest" class="in.javadigest.message.HelloRequest">
    <namespace prefix="hs"
      uri="http://in.javadigest/HelloService/" default="all" />
    <value name="in" field="name" />
  </mapping>

  <mapping name="HelloResponse"
    class="in.javadigest.message.HelloResponse">
    <namespace prefix="hs"
      uri="http://in.javadigest/HelloService/" default="all" />
    <value name="out" field="message" />
  </mapping>
</binding>

Spring WS provides support for many Marshellers like JAXB, Castor, XMLBeans, and JiBX

4. Define the Endpoint

Endpoint is the components that are used to handle incoming XML messages. There are two types of endpoints: message endpoints and payload endpoints. Message endpoints give access to the entire XML message, including SOAP headers and the Payload endpoints provides access to the content of the SOAP body.
To define the endpoint you can either implement the MessageEndpoint/PayloadEndpoint interface, extend any of the abstract classes provided by the Spring WS.
In the following example we have used AbstractMarshallingPayloadEndpoint class

HelloServiceEndpoint.java

package in.javadigest.endpoint;

import in.javadigest.message.HelloRequest;
import in.javadigest.message.HelloResponse;
import in.javadigest.service.HelloService;

import org.springframework.ws.server.endpoint.AbstractMarshallingPayloadEndpoint;

public class HelloServiceEndpoint extends AbstractMarshallingPayloadEndpoint {

  private HelloService helloService;

  protected Object invokeInternal(Object requestObject) throws Exception {
    HelloRequest request = (HelloRequest) requestObject;
    String name = request.getName();
    return new HelloResponse(helloService.sayhello(name));
  }

  public HelloService getHelloService() {
    return helloService;
  }

  public void setHelloService(HelloService helloService) {
    this.helloService = helloService;
  }

}

5. Configuring deployment descriptor

The Spring’s MessageDispatcherServlet is used to dispatch incoming XML messages to endpoints. All the web service requests should be mapped to this servlet.

Web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>MemberService</display-name>
  <servlet>
    <servlet-name>helloservice</servlet-name>
    <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:/applicationContext.xml</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>helloservice</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>helloservice</servlet-name>
    <url-pattern>*.wsdl</url-pattern>
  </servlet-mapping>
</web-app>

6. Configuring Spring’s Application Context

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="endpoint"
    class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
    <property name="endpointMap">
      <map>
        <entry
          key="{http://in.javadigest/HelloService/}HelloRequest"
          value-ref="helloServiceEndpoint" />
      </map>
    </property>
  </bean>

  <bean id="helloService" class="in.javadigest.service.HelloServiceImpl">
    <property name="validate" value="true" />
  </bean>

  <bean id="helloServiceEndpoint"
    class="in.javadigest.endpoint.HelloServiceEndpoint">
    <property name="marshaller" ref="marshaller" />
    <property name="unmarshaller" ref="unmarshaller" />
    <property name="helloService" ref="helloService" />
  </bean>

  <bean id="marshaller"
    class="org.springframework.oxm.jibx.JibxMarshaller">
    <property name="targetClass"
      value="in.javadigest.message.HelloResponse" />
  </bean>

  <bean id="unmarshaller"
    class="org.springframework.oxm.jibx.JibxMarshaller">
    <property name="targetClass"
      value="in.javadigest.message.HelloRequest" />
  </bean>

  <bean id="HelloRequest"
    class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
    <property name="schema" ref="schema" />
    <property name="portTypeName" value="Hello" />
    <property name="locationUri"
      value="http://localhost:8080/helloservice/services/HelloRequest" />
  </bean>

  <bean id="schema"
    class="org.springframework.xml.xsd.SimpleXsdSchema">
    <property name="xsd" value="/WEB-INF/xsd/Hello.xsd" />
  </bean>

</beans>

The above configuration file contains
• Endpoint Mapping: The MessageDispatcherServlet would direct the incoming request to the bean and this would select an appropriate endpoint and forward the request to that endpoint. (You can also configure interceptors here, which will be processed before the request is processed).
• Spring bean for the service implementation.
• Spring bean for the endpoint, which requires marhaller and unmarshaller.

7. Running the example

The following maven code can be used to run this example (it would also download all the dependencies)

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>in.javadigest</groupId>
  <artifactId>helloservice</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>Hello Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.springframework.ws</groupId>
      <artifactId>spring-ws</artifactId>
      <version>${spring-ws.version}</version>
      <classifier>all</classifier>
    </dependency>
    <dependency>
      <groupId>org.springframework.ws</groupId>
      <artifactId>spring-ws-core</artifactId>
      <version>${spring-ws.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jibx</groupId>
      <artifactId>jibx-run</artifactId>
      <version>${jibx.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jibx</groupId>
      <artifactId>jibx-extras</artifactId>
      <version>${jibx.version}</version>
    </dependency>
    <dependency>
      <groupId>xpp3</groupId>
      <artifactId>xpp3</artifactId>
      <version>${xpp3.version}</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>stringreversalservice</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.10</version>
        <configuration>
          <scanIntervalSeconds>60</scanIntervalSeconds>
          <webAppSourceDirectory>${basedir}/WebContent</webAppSourceDirectory>
          <webXml>${basedir}/WebContent/WEB-INF/web.xml</webXml>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.jibx</groupId>
        <artifactId>maven-jibx-plugin</artifactId>
        <version>1.2.1</version>
        <configuration>
          <directory>src/main/resources</directory>
          <includes>
            <includes>*binding.xml</includes>
          </includes>
          <verbose>true</verbose>
        </configuration>
        <executions>
          <execution>
            <goals>
              <goal>bind</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>
  <properties>
    <spring.version>2.5.6</spring.version>
    <spring-ws.version>1.5.6</spring-ws.version>
    <jibx.version>1.2.1</jibx.version>
    <xpp3.version>1.1.3.3</xpp3.version>
  </properties>

</project>

Use the following command to run the application.

mvn jetty:run

8. Writing the client code

Tools like SOAPUI can be used to test any webservice application, once it up and running

Alternatively you can use the following Java application to test it.

package in.javadigest.client;

import java.io.StringReader;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.ws.client.core.WebServiceTemplate;

public class HelloServiceClient {
  public static void main(String[] args) throws Exception {
    String xmlRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        + "<hs:HelloRequest xmlns:hs=\"http://in.javadigest/HelloService/\">"
        + "<hs:in>test</hs:in>" + "</hs:HelloRequest>";
    String wsdlUrl = "http://localhost:8080/helloservice/services/HelloRequest";
    StreamSource requestMessage = new StreamSource(new StringReader(xmlRequest));
    StreamResult responseMessage = new StreamResult(System.out);
    WebServiceTemplate template = new WebServiceTemplate();
    template.sendSourceAndReceiveToResult(wsdlUrl, requestMessage,
        responseMessage);
  }
}
}

Download this example.

About these ads

6 thoughts on “Spring Web Service Example

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s