Home » Java » Enterprise Java » Contract First SOAP Service with Spring and Maven

About Abhimanyu Prasad

Abhimanyu Prasad
Abhimanyu is a passionate tech blogger and senior programmer, who has an extensive end-to-end development experience with wide range of technologies. He is the founder and administrator at jCombat.

Contract First SOAP Service with Spring and Maven

1. Introduction

In this tutorial, we will learn to implement a contract-first SOAP service application using JAX-WS, Spring and Maven. This is more of a design decision whether to use contract-first or code-first approach.

The most notable benefit of using applying contract-first approach in developing a SOAP based web service application, is that the contract can be shared with the consumers/clients immediately after the needed changes are done to it, so the client application and web service operation implementation can be done independently by different teams at the same time, thus saving a lot of time.

2. Implementation

Untitled-Diagram

Something like above would be the scenario, where the client/consumer application will be interacting with our sample SOAP based JAX-WS web service through a service endpoint.

To start with the implementation, first create a Maven Project in Eclipse and make sure we proceed with the directory structure close to what has been shown below.

ProjectStructure

First is to look at our pom dependencies, which should look like:

pom.xml

<dependencies>
	<!-- Spring dependencies -->
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-core</artifactId>
		<version>4.2.1.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework</groupId>
		<artifactId>spring-web</artifactId>
		<version>4.2.1.RELEASE</version>
	</dependency>
 
	<!-- JAX-WS dependencies -->
	<dependency>
		<groupId>org.jvnet.jax-ws-commons.spring</groupId>
		<artifactId>jaxws-spring</artifactId>
		<version>1.9</version>
	</dependency>
	<dependency>
		<groupId>com.sun.xml.ws</groupId>
		<artifactId>jaxws-rt</artifactId>
		<version>2.2.8</version>
	</dependency>
</dependencies>
<build>
	<finalName>SOAPWebServiceExample</finalName>
	<plugins>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>jaxws-maven-plugin</artifactId>
			<version>1.12</version>
			<configuration>
				<wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
				<packageName>com.jcombat.ws</packageName>
				<keep>true</keep>
				<sourceDestDir>${basedir}/target/generated/src/main/java</sourceDestDir>
			</configuration>
			<executions>
				<execution>
					<id>wsdl_import</id>
					<goals>
						<goal>wsimport</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
	</plugins>
</build>

Note the wsimport tool that we will be using, to generate the stub files later from the WSDL file.

Let’s now check out the web.xml file.

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
		http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
 
	<display-name>SOAPWebServiceExample</display-name>
 
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
 
	<servlet>
		<servlet-name>customer</servlet-name>
		<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>customer</servlet-name>
		<url-pattern>/customer</url-pattern>
	</servlet-mapping>
 
</web-app>

Next we create a schema file for our web service. Name it as customerService.xsd, which will basically define the building blocks for the WSDL file or web service contract, we will be creating.

customerService.xsd

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://ws.jcombat.com/"
	xmlns:tns="http://ws.jcombat.com/" elementFormDefault="qualified">
 
	<element name="CustomerServiceRequest" type="tns:CustomerServiceRequestType">
	</element>
 
	<complexType name="CustomerServiceRequestType">
		<sequence>
			<element name="customerId" type="int"></element>
		</sequence>
	</complexType>
 
	<complexType name="CustomerServiceResponseType">
		<sequence>
			<element name="customer" type="tns:Customer" maxOccurs="unbounded"
				minOccurs="0"></element>
		</sequence>
	</complexType>
 
	<element name="CustomerServiceResponse" type="tns:CustomerServiceResponseType">
	</element>
 
	<complexType name="Customer">
		<sequence>
			<element name="id" type="int" maxOccurs="1" minOccurs="1"></element>
			<element name="name" type="string" maxOccurs="1" minOccurs="1"></element>
		</sequence>
	</complexType>
</schema>

Create a valid WSDL file using the XML schema we just created.

customerService.wsdl

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
	xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
	xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"
	xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://ws.jcombat.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws.jcombat.com/"
	name="customerService">
	
	<wsdl:types>
		<xsd:schema targetNamespace="http://ws.jcombat.com/">
			<xsd:import namespace="http://ws.jcombat.com/"
				schemaLocation="../schema/customerService.xsd" />
		</xsd:schema>
	</wsdl:types>
	
	<wsdl:message name="CustomerServiceRequest">
		<wsdl:part name="CustomerServiceRequest" element="tns:CustomerServiceRequest" />
	</wsdl:message>
	<wsdl:message name="CustomerServiceResponse">
		<wsdl:part name="CustomerServiceResponse" element="tns:CustomerServiceResponse" />
	</wsdl:message>
	
	<wsdl:portType name="CustomerServicePortType">
		<wsdl:operation name="getCustomer">
			<wsdl:input name="CustomerServiceRequest" message="tns:CustomerServiceRequest" />
			<wsdl:output name="CustomerServiceResponse" message="tns:CustomerServiceResponse" />
		</wsdl:operation>
	</wsdl:portType>
	
	<wsdl:binding name="CustomerEndpointPortBinding" type="tns:CustomerServicePortType">
		<soap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="getCustomer">
			<soap:operation style="document" soapAction="getCustomer" />
			<wsdl:input name="CustomerServiceRequest">
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output name="CustomerServiceResponse">
				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	
	<wsdl:service name="customerService">
		<wsdl:port name="CustomerEndpointPort" binding="tns:CustomerEndpointPortBinding">
			<soap:address location="http://localhost:8080/SOAPWebServiceExample/customer" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>

Next is to generate the stub files from the WSDL file. To do that, run the below command in your system’s command prompt.

mvn clean install

Check out for the generated stub files in the /target directory.

stub

Let’s now create the implementation of the generated service interface CustomerServicePortType in a class named CustomerServiceImpl.

CustomerServiceImpl.java

package com.jcombat.service;
 
import javax.jws.WebService;
 
import com.jcombat.ws.Customer;
import com.jcombat.ws.CustomerServicePortType;
import com.jcombat.ws.CustomerServiceRequestType;
import com.jcombat.ws.CustomerServiceResponseType;
 
@WebService(endpointInterface="com.jcombat.ws.CustomerServicePortType")
public class CustomerServiceImpl implements CustomerServicePortType {
 
	public CustomerServiceResponseType getCustomer(
			CustomerServiceRequestType customerServiceRequest) {
		final CustomerServiceResponseType response = new CustomerServiceResponseType();
		Customer customer = new Customer();
		customer.setId(123);
		customer.setName("Ramesh");
		response.getCustomer().add(customer);
		return response;
	}
 
}

@WebService annotation must be applied to the endpoint interface implementation class to mark it as the web service endpoint. The @WebService annotation tells the server runtime environment to expose all the public methods of that class as web service methods.

We are all done with the application. Final check is if we can see the WSDL content displayed when the below endpoint URI is hit, whose location we have specified towards the bottom of the WSDL file.

  • http://localhost:8080/SOAPWebServiceExample/customer?wsdl

Below is what we see in the browser when we hit it.

wsdl-1

So yes, we did it, successfully.

3. Running the application

Setup the SOAP project in SOAP UI with the WSDL URI (http://localhost:8080/SOAPWebServiceExample/customer?wsdl).

Below is what we see when we actually hit the service in SOAP UI.

SOAP-1

4. Download the source code

Reference: Contract First SOAP Service with Spring and Maven from our JCG partner Abhimanyu Prasad at the jCombat blog.
(0 rating, 0 votes)
You need to be a registered member to rate this.
1 Comment Views Tweet it!
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

1
Leave a Reply

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Dmitriy Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
Dmitriy
Guest
Dmitriy

http://localhost:8080/SOAPWebServiceExample/customer?wsdl is incorrect.
It should be http://localhost:8080/SOAPCFWebServiceExample/customer since we have SOAPCFWebServiceExample in pom.xml