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