Web Service – Spring/JAX-WS Example
This post contains notes on how to deploy a web service with Spring Dependency Injection on the Apache Geronimo Application Server. It is not a step-by-step tutorial, but does include the full source.
Source download: webservice-1.0
Software
Requirements:
- Java JDK 1.6
- Apache Maven 2
- Apache Geronimo 2.1 (Jetty)
- Eclipse 3.4.2 Ganymede
- Geronimo v21 Server Tools Eclipse Integration
Optional:
- Sonatype Nexus
- Maven 2 Eclipse Integration
- Subversion
Getting Started
This project was started using the maven-archetype-webapp template which generates a basic file structure and pom.xml file:
mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:generate -DgroupId=com.chibidungeon.test -DartifactId=webservice -DarchetypeArtifactId=maven-archetype-webapp -DarchetypeGroupId=org.apache.maven.archetypes
To get the webservice to work jax-ws and spring dependencies were added to the pom.xml:
- spring-2.5.6
- spring-core-2.5.6
- spring-beans-2.5.6
- spring-context-2.5.6
- spring-context-support-2.5.6
- spring-web-2.5.6
- spring-aspects-2.5.6
- jaxws-rt-2.1.3
- jaxws-spring-1.8
Note: For some reason the spring bundle was required in addition to the separate components; something to do with the xsd schemas.
The pom.xml also needed to be configured to use version 1.6 of the jdk, by adding the following to the build profile:
... <build> ... <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> ... </build>
Moving to Eclipse
The following maven command will generate the required Eclipse project files:
mvn -Dwtpversion=2.0 eclipse:eclipse
Note: This command needs to be run after any changes to the pom.xml dependencies.
It may be necessary to run the following command first if dependencies are removed or versions are changed:
mvn eclipse:clean
The project can now be imported into the Eclipse Workspace.
Configuring the Web Service
web.xml – Deployment Descriptor
...
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<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>/hello</url-pattern>
</servlet-mapping>
...
applicationContext.xml – Spring Config
... <context:spring-configured /> <context:annotation-config /> <wss:binding url="/hello" service="#helloServicePortType"></wss:binding> <ws:service id="helloServicePortType" bean="#helloServicePortTypeImpl"></ws:service> <bean id="helloServicePortTypeImpl" class="com.chibidungeon.test.webservice.HelloServicePortTypeImpl"></bean> <bean id="greetService" class="com.chibidungeon.test.logic.GreetServiceImpl"></bean> ...
Constructing the Web Service
If you add all the WebMethod and WebParam annotations to the interface, then you don’t need to add them to the implementation.
HelloServicePortType.java – Web Service Interface
package com.chibidungeon.test.webservice;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
@WebService(portName="HelloServicePort")
@SOAPBinding(style = Style.RPC, use = Use.LITERAL)
public interface HelloServicePortType {
@WebMethod
String sayHello(@WebParam(name="name")String name);
}
HelloServicePortTypeImpl.java – Web Service Implementation
package com.chibidungeon.test.webservice;
import javax.jws.WebService;
import org.springframework.beans.factory.annotation.Autowired;
import com.chibidungeon.test.logic.GreetService;
@WebService(serviceName = "HelloService"
, endpointInterface = "com.chibidungeon.test.webservice.HelloServicePortType"
, portName = "HelloServicePort")
public class HelloServicePortTypeImpl implements HelloServicePortType {
@Autowired
private GreetService greetService;
public String sayHello(String name) {
return greetService.getGreeting(name);
}
}
Geronimo
Geronimo will automatically detect web service annotations and deploy by default. Unfortunately these services know nothing about Spring dependency injection, and should be disabled
Add this line to the Server VM Arguments to turn off web service detection:
-Dorg.apache.geronimo.jaxws.builder.useSimpleFinder=true
For jax-ws with spring dependency injection to work, certain libraries that come with Geronimo need to be blocked by changing the Deployment Descriptor.
geronimo-web.xml – Geronimo Deployment Descriptor
...
<dep:hidden-classes>
<dep:filter>org.springframework.</dep:filter>
<dep:filter>META-INF/spring</dep:filter>
<dep:filter>com.sun.xml.</dep:filter>
</dep:hidden-classes>
...
References
http://jgeeks.blogspot.com/2008/09/exposing-jax-ws-web-service-using.html
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>