Archive

Posts Tagged ‘Spring Web Services’

10 Minute Guide to Spring Web Services

October 5th, 2012 1 comment

Spring Web Services simplifies creation of contract-first SOAP based web services. In this blog post, I will create a hello world web service using Spring Web Services. The service will take a string as a parameter, prepends “Hello ” and returns it. Here are the steps for creating the service:

1. We start by creating a maven based web project. Spring Web Services provides an archetype that can be used to simplify creation of web service project.

2. Add Spring Web Services and its dependent jars to the project. Here is the maven dependency that you need to add:

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

3. Since we are developing contract first web service, we create a data contract that defines the input and output messages the service accepts. Create a helloworld.xsd file under WEB-INF folder with the following content:

	
	<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified"
        targetNamespace="http://blog.inflinx.com/ws/helloworld"
        xmlns:tns="http://blog.inflinx.com/ws/helloworld">

     <element name="helloworldRequest" type="string"/>

    <element name="helloworldResponse" type="string"/>
</schema>
	
	

4. The next step is to create an Endpoint that handles incoming XML messages. Here is the HelloWorldEndpoint implementing hello world service:

package com.inflinx.blog.helloworld;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

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 org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

@Endpoint
public class HelloWorldEndpoint {
	
	 private static final String NAMESPACE_URI = "http://blog.inflinx.com/ws/helloworld";
	
	 private static final String REQUEST_LOCAL_NAME = "helloworldRequest";
	 
	 private static final String RESPONSE_LOCAL_NAME = "helloworldResponse";
	 
	 
	 @PayloadRoot(localPart = REQUEST_LOCAL_NAME, namespace = NAMESPACE_URI)
	 @ResponsePayload
	 public Element handleRequest(@RequestPayload Element requestElement) throws Exception {
		 
		 // Get the submitted text value
		 String text = requestElement.getChildNodes().item(0).getNodeValue();
		 
		 System.out.println("Request Pay Load: " + text);
		 
		 // Create a response Element
		 DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		 DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
	     Document document = documentBuilder.newDocument();
	     Element responseElement = document.createElementNS(NAMESPACE_URI, RESPONSE_LOCAL_NAME);
	     Text responseText = document.createTextNode("Hello "+ text);
	     responseElement.appendChild(responseText);
		 
		 return responseElement;
	 }
}

As you can see, the class is annotated with @EndPoint enabling it for component scanning. The @PayloadRoot annotation tells Spring that handleRequest method can handle XML messages. The method implementation is self explanatory: we get the submitted text, create a new response element and return the text with Hello prepended.

5. The next step is to add a Spring Web Service MessageDispatcherServlet to web.xml and map all the incoming requests to it. Here is the modified web.xml file:


<?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>Hello World Web Service</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>

6. The MessageDispatcherServlet is named spring-ws. Hence the servlet will look for a Spring configuration file named spring-ws-servlet.xml under WEB-INF folder. Here is the spring-ws-servlet.xml file:


<?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:sws="http://www.springframework.org/schema/web-services"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<context:component-scan base-package="com.inflinx.blog.helloworld"/>
	
    <sws:annotation-driven/>

	 <sws:dynamic-wsdl id="helloworld" portTypeName="helloworld" locationUri="http://localhost:8080/hello-world">
        <sws:xsd location="/WEB-INF/helloworld.xsd"/>
    </sws:dynamic-wsdl>

</beans>

The dynamic-wsdl element generates a WSDL automatically for the web service.

7. Deploy the application to a container such as Tomcat or Glassfish. Once deployed, the WSDL can be accessed using the URL: http://localhost:8080/helloworld/helloworld.wsdl

8. Finally, using SOAP UI submit the following request:


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hel="http://blog.inflinx.com/ws/helloworld">
   <soapenv:Header/>
   <soapenv:Body>
      <hel:helloworldRequest>World</hel:helloworldRequest>
   </soapenv:Body>
</soapenv:Envelope>

You should see the following response from the service:


<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header/>
   <SOAP-ENV:Body>
      <helloworldResponse xmlns="http://blog.inflinx.com/ws/helloworld">Hello World</helloworldResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>