Acknowledgements
Technorati Profile
Before I get started I wish to acknowledge the work of others that greatly assisted me in my understanding of Spring Web Services. I encourage readers to reach out to these sources as well.
Contract Last vs Contract First
There are two development styles for developing web services using Java. With contract-last you start with your Java code and from that you generate the web service contract (WSDL – web service definition language). When using the contract first you start with the WSDL or contract and use Java to implement a service to meet this contract.
Spring-WS only supports contract-first development style.
For more information on contract-first ; much of the information paraphrased here is explored in greater detail.
Problems with Contract Last
From experience and for me the most important difficulties with Contract Last are:
- Language specific (proprietary) types can become exposed in a XSD and are not portable to other languages.
- Example Java TreeMap type would not be understood correctly by .NET or Python and would result in a different data type instantiated with differing semantics.
- Code == Contract. Increased Fragility since the WSDL contract is directly generated from the Java code thereby resulting in a change in WSDL contract with any change in the Java code. This is not desirable.
- Contracts should be as stable as long as possible
- Performance resulting from XML generated from Java code.
- XSD reuse is difficult if not impossible.
Benefits of Contract-First
- By focusing on the contract and in particular the XSD that defines the contract you implement a more robust WSDL contract that can support changes in the Java code that implements the contract. That is the WSDL contract and Java contract are loosely coupled.
- The contract is stable over a longer period of time
- By focusing on what is needed in the XML to support the WSDL contract a much better performing XML message is implemented.
- XSD components are reusable across other WSDL contracts therefore increasing the re-usability of the SOA artifacts.
- This of course is dependent upon the XML design pattern chosen to implement the XSD. For an extensive and well thought exploration of this topic refer to Roger L. Costello’s discussion of Schemas
Tools Used
For our example a number of tools are used. Briefly I mention them here.
Spring Web Services
- The contract is defined by the XML schema (XSD) of the services’ messages
- The Service contract (i.e., WSDL) will be generated from the XSD
- Each Spring-WS has an end point which handles the incoming XML documents and manages the outgoing XML response documents
- Each end point will require a business service to operate
- This business service is defined as an interface
- The business service interface_ is implemented by a business service class
- These dependencies are injected by Springs IoC with metadata defined in the spring-ws-servlet.xml
- All the components are wired together by the configurations specified in spring-ws-servlet.xml context.
Sample: Magic 8 Ball
The following example is based on the old toy Magic 8-ball which allows as question to be asked and magically 1 of 20 possible answers return as a response to the query. Our sample web service using Spring WS with JAXB will do just this.
The Contract
We focus on the data contract between our client and service and define this with in an XML Schema; our XSD. Using a simple Russian Doll design pattern we have two elements; a request and a response. The request involves a question and the reponse an answer.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://acompany.com/it/enterprise/DEPT/EightBall/v1" xmlns:tns="http://acompany.com/it/enterprise/DEPT/EightBall/v1" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
<xs:element name="eightBallRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Question" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="eightBallResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="Answer" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Marshalling/Unmarshalling:JAXB
Not only does our XSD define our data contract between the client and service it is used by JAXB to generate the marshalling and unmarshalling code that our service uses to handle the XML messages.
- With your XSD in the bin directory of you JAXB installation run the xjc tool to generate the JAVA class for marshalling and unmarshalling.
- You can us the -p switch and specify a simple package name for your JAXB JAVA code. In our example jaxb.eightball. The default package name is the XSD target namespace
C:\jaxb-ri-20070122\bin>xjc.bat -p jaxb.eightball eightball.xsd
parsing a schema…
compiling a schema…
jaxb\eightball\EightBallRequest.java
jaxb\eightball\EightBallResponse.java
jaxb\eightball\ObjectFactory.java
jaxb\eightball\package-info.java
Eclipse Project using Maven 2
- In Eclispe use File/New/Project…/Maven Project
- Select Default workspace
- Select spring-ws-archtype
- Enter eightballdemo for Group Id
- Enter eightballdemo for Artifact Id
- Select Finish
- Selecting the POM.XML under the dependencies tab add the log4j POM dependencies in the Tools Used section above
- Add spring-oxm-tiger dependency
- Add spring-ws-core-tiger dependency

Exposing the Contract
- Import eightball.xsd in src/main/webapp/WEB-INF
- Edit spring-ws-servlet.xml and add the following for Spring to generate the WSDL at runtime from the XSD file:
<!-- Add automatic WSDL generation support -->
<bean id="eightball" class="org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition">
<property name="schema" ref="schema" />
<property name="portTypeName" value="eightball" />
<property name="locationUri" value="http://localhost:8080/eightball/" />
<property name="targetNamespace" value="http://acompany.com/it/enterprise/DEPT/EightBall/v1" />
</bean>
<bean id="schema" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="/WEB-INF/eightball.xsd" />
</bean>
Preparing for Code
- Add a Source Folder to your project: src/main/java
- Add the following packages to this Source Folder
- ws – web service end point
- jaxb.eightball – JAXB marshalling and unmarshalling classes
- service – interface for class that contains service logic
- service.impl – class that implements service logic
- Import the JAXB Java files generated under the jaxb.eightball package.

EndPoint
First Part
- In spring-ws-servlet.xml define the web service endpoint using annotations along with the service interface and implementation.
<!-- Register PayloadRootAnnotationMethodEndpointMapping -->
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping" />
<!-- Register Endpoint -->
<bean id="eightBallEndpoint" class="ws.EightBallEndpoint">
<description>
This endpoint handles requests.
</description>
<property name="eightBallService" ref="eightBallService"/>
</bean>
<bean id="eightBallService" class="service.impl.EightBallServiceImpl">
<description>
This bean is our "business" service.
</description>
</bean>
Now create the end point class EightBallEndPoint in the ws package
package ws;
import service.EightBallService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import jaxb.eightball.EightBallRequest;
import jaxb.eightball.EightBallResponse;
@Endpoint
public class EightBallEndpoint {
private EightBallService eightBallService;
protected final Log logger = LogFactory.getLog(getClass());
/**
* Sets the "business service" to delegate to.
*/
public void setEightBallService(EightBallService eightBallService) {
this.eightBallService = eightBallService;
}....
Service: EightBallService
- Define the interface EightBallService in the package service
package service;
public interface EightBallService {
String question (String s);
}
Wire In the JAXB
- In spring-ws-servlet.xml add the following wiring for the JAXB marshalling and unmarshalling.
<!-- Configure XML Marshaller -->
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
<constructor-arg ref="marshaller" />
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>jaxb.eightball.EightBallRequest</value>
<value>jaxb.eightball.EightBallResponse</value>
</list>
</property>
</bean>
In EightBallEndPoint add the following annotation based section for marshalling and unmarshalling.
@PayloadRoot(localPart= "eightBallRequest", namespace="http://acompany.com/it/enterprise/DEPT/EightBall/v1")
public EightBallResponse doit(EightBallRequest request){
String question = request.getQuestion();
System.out.println("The question is " + question);
logger.info("The question is " + question);
String answer = eightBallService.question(question);
logger.info("The answer is " + answer);
EightBallResponse response = new EightBallResponse();
response.setAnswer(answer);
return response;
}
}
EightBallServiceImpl
- Create the Class EightBallServiceImpl implementing the interface EightBallService
package service.impl;
import java.util.ArrayList;
import java.util.Random;
import service.EightBallService;
public class EightBallServiceImpl implements EightBallService {
public String question (String s) {
Random rand = new Random();
ArrayList<String> answers = new ArrayList<String>(20);
answers.add(0, "As I see it, yes");
answers.add(1, "It is certain");
answers.add(2,"It is decidedly so" );
answers.add(3,"Most likely");
answers.add(4,"Outlook good");
answers.add(5, "Signs point to yes");
answers.add(6, "Without a doubt");
answers.add(7, "Yes");
answers.add(8, "Yes - definitely");
answers.add(9, "You may rely on it");
answers.add(10,"Reply hazy, try again");
answers.add(11,"Better not tell you now");
answers.add(12,"Cannot predict now");
answers.add(13,"Concentrate and ask again");
answers.add(14,"Don't count on it");
answers.add(15,"My reply is no");
answers.add(16,"My sources say no");
answers.add(17,"Outlook not so good");
answers.add(18,"Very doubtful");
answers.add(19, "Ask again later");
int iNum = rand.nextInt(20);
return answers.get(iNum).toString();
}
}
Package and Test
We are now done should be ready to compile, package and test our service. I strongly recommended using SoapUI for testing your web service.
Project Code
You can download Eclipse Project Zip file