Step 1
Download and Install JDK 1.6, Maven and your favorite web application container(tomcat,jboss,glassfish).
Step 2
Create a maven application with archetype "maven-archetype-webapp". Ask Google if you need help running this archetype.
Step 3
Add maven repository for JBoss and dependencies for junit, spring, jaxb, and jvnet's jaxws-spring. Since spring is already configured exclude spring from jvnet.
pom.xml
.
.
<repositories>
<repository>
<id>jboss</id>
<name>JBoss Maven Repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<properties>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.jvnet.jax-ws-commons.spring</groupId>
<artifactId>jaxws-spring</artifactId>
<version>1.8</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
.
.
Step 4
Develop the webservice class using JAX-WS annotations
CalculatorServiceImpl.java
@WebService
@SOAPBinding(style = Style.RPC, use = Use.LITERAL)
public class CalculatorServiceImpl implements CalculatorService {
public double addNumbers(double a, double b) {
return a + b;
}
public double subtractNumbers(double a, double b) {
return a - b;
}
}
Step 5
Configure spring context loader and jvnet's WSSpringServlet in web.xml.
web.xml
. . <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>jaxws-servlet</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>jaxws-servlet</servlet-name> <url-pattern>/calculator</url-pattern> </servlet-mapping> . .Step 6
Configure calculator service as a bean in spring's context. Next, add this service to the web URL that we configured earlier in web.xml.
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:ws="http://jax-ws.dev.java.net/spring/core" xmlns:wss="http://jax-ws.dev.java.net/spring/servlet" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd"> <bean id="calculatorService" class="com.ingeniouscamel.springjaxws.service.CalculatorServiceImpl" /> <wss:binding url="/calculator"> <wss:service> <ws:service bean="#calculatorService" /> </wss:service> </wss:binding> </beans>
Step 7
Run the application in your webapp container and test it using the following URL
http://localhost:<Port>/<WebAppContext>/calculator?WSDL
Step 8
In order to develop a client, first develop a webservice client interface. You can cheat this step by running wsimport command on the WSDL and using the generated source file.
CalculatorServiceImpl.java
@WebService(name = "CalculatorServiceImpl", targetNamespace = "http://service.springjaxws.ingeniouscamel.com/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface CalculatorServiceImpl {
@WebMethod
@WebResult(partName = "return")
public double addNumbers(
@WebParam(name = "arg0", partName = "arg0") double arg0,
@WebParam(name = "arg1", partName = "arg1") double arg1);
@WebMethod
@WebResult(partName = "return")
public double subtractNumbers(
@WebParam(name = "arg0", partName = "arg0") double arg0,
@WebParam(name = "arg1", partName = "arg1") double arg1);
}
Step 9
Configure client's spring context to bind the above interface to the web service using spring's JaxWsPortProxyFactoryBean bean (you will find this file in src/main/resources folder of my project).
applicationClientContext.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="calculatorWebService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean"> <property name="serviceInterface" value="com.ingeniouscamel.springjaxws.client.CalculatorServiceImpl"/> <property name="wsdlDocumentUrl" value="http://localhost:8080/SpringJaxWSApp/calculator?WSDL"/> <property name="namespaceUri" value="http://service.springjaxws.ingeniouscamel.com/"/> <property name="serviceName" value="CalculatorServiceImplService"/> <property name="portName" value="CalculatorServiceImplPort"/> </bean> </beans>
Step 10
You can now load the above client's context (applicationClientContext.xml) and call methods on the web service client directly.
CalculatorWebServiceClientTest.java
public class CalculatorWebServiceClientTest {
private CalculatorServiceImpl calculatorWebService;
@Before
public void setUp() throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationClientContext.xml");
calculatorWebService = (CalculatorServiceImpl)context.getBean("calculatorWebService");
}
@Test
public void testAddNumbers() {
Assert.isTrue(calculatorWebService.addNumbers(3, 5) == 8);
}
@Test
public void testSubtractNumbers() {
Assert.isTrue(calculatorWebService.subtractNumbers(7, 4) == 3);
}
}
Download Project
You can download my project from google code. SVN URL is http://ingenious-camel.googlecode.com/svn/trunk/SpringJaxWSApp/

This comment has been removed by the author.
ReplyDeleteHow would one annotate the CalculatorServiceImpl interface if both the parameter and the return type was a complex type?
ReplyDeleteHi - Please see the sample below. I have also checked in this sample to SVN.
ReplyDelete1. My Pojo's
public class Dept {
private int deptId;
private String location;
....
}
public class Manager {
private int empId;
private String name;
private int deptId;
private String location;
....
}
2. Webservice class
@WebService
@SOAPBinding(style = Style.RPC, use = Use.LITERAL)
public class DeptServiceImpl {
public Manager getDeptManager(Dept dept) {
// perform some logic to retrieve manager using dept
return manager;
}
}
3. Webservice client interface
@WebService(name = "DeptServiceImpl", targetNamespace = "http://service.springjaxws.ingeniouscamel.com/")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface DeptServiceImpl {
@WebMethod
@WebResult(partName = "return")
public Manager getDeptManager(
@WebParam(name = "arg0", partName = "arg0") Dept arg0);
}
4. Spring client config
Great!
ReplyDeleteGreat article!!! Works perfectly
ReplyDelete