jakub holý

building the right thing, building it right, fast

Tip: Multiple webservice implementation classes available at the same time under WAS7

2010-12-29j2ee

If you want to experiment with webservices by providing several alternative implementations of the same webservice (represented by the <wsdl:service> element), each having its own URL, and you're using Websphere 7 and JAX-WS, then:
  1. For each alternative implementation, add <wsdl:port> with a unique name under the <wsdl:service> element in the WSDL file. Beware: This is essential to enable multiple implementations.
  2. For each alternative implementation, define a servlet and servlet mapping in web.xml like this:
    <servlet id="$IMPLEMENTATION_CLASS_NAME$">
    		<servlet-name>$IMPLEMENTATION_CLASS_NAME$</servlet-name>
    		<servlet-class>$IMPLEMENTATION_CLASS_NAME$</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>$IMPLEMENTATION_CLASS_NAME$</servlet-name>
    		<url-pattern>/$DESIRED_UNIQUE_URL$</url-pattern>
    	</servlet-mapping>
  3. Create the implementations - likely as POJOs denoted with the @WebService annotation - and set the corresponding portName for each of them (@WebService(portName="<unique port name>", ...))
  4. Deploy and use

1. Define a unique wsdl:port for each implementation

As mentioned, it's necessary to define a unique wsdl:port for each implementation.

We define two ports, LearningActivityPort1 and LearningActivityPort2, using the same port type (i.e. the same transport protocol etc.).

LearningActivity.wsdl:


<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ...>
	<wsdl:types>...</wsdl:types>
	<wsdl:message ...>...</wsdl:message>
	<wsdl:portType name="DefaultPortType">...</wsdl:portType>
	<wsdl:binding name="LearningActivityHttpBinding" type=...>...</wsdl:binding>
	<wsdl:service name="LearningActivityHttpService">
		<wsdl:port binding="tns:LearningActivityHttpBinding" name="LearningActivityPort1">
			<soap:address location="http://example.com/myApp/LearningActivityHttpService" />
		</wsdl:port>
		<wsdl:port binding="tns:LearningActivityHttpBinding" name="LearningActivityPort2">
			<soap:address location="http://example.com/myApp/LearningActivityRawXmlService" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>

2. Define a servlet and servlet mapping for each implementation

Next we need to declare each of the webservice implementation classes as a servlet and define a servlet mapping to assign a unique URL to that implementation as described in WAS help: web.xml:


<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<display-name>pokusWeb4was7</display-name>

<servlet id="LearningActivityHttpBindingImpl"> <servlet-name>LearningActivityHttpBindingImpl</servlet-name> <servlet-class>example.LearningActivityHttpBindingImpl</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>LearningActivityHttpBindingImpl</servlet-name> <url-pattern>/LearningActivityJaxbService</url-pattern> </servlet-mapping>

<servlet id="LearningActivityRawXmlServiceImpl"> <servlet-name>LearningActivityRawXmlServiceImpl</servlet-name> <servlet-class>example.LearningActivityRawXmlServiceImpl</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>LearningActivityRawXmlServiceImpl</servlet-name> <url-pattern>/LearningActivityRawXmlService</url-pattern> </servlet-mapping>

<welcome-file-list>...</welcome-file-list> </web-app>


When deployed, the two implementation will be thus available under http://localhost:9080/pokusWeb4was7/LearningActivityHttpService and http://localhost:9080/pokusWeb4was7/LearningActivityRawXmlService.

3. Create each implementation linking it to its port name

Finally we write the two implementation, each being assigned to a different port name: example.LearningActivityHttpBindingImpl:


@javax.jws.WebService (serviceName="LearningActivityHttpService", portName="LearningActivityPort1")
public class LearningActivityHttpBindingImpl{

public TransactionResponseMessage updateLearningActivity(LearningActivityMessage learningActivityMsg) { //... return response; } }


example.LearningActivityRawXmlServiceImpl:


@javax.jws.WebService (serviceName="LearningActivityHttpService", portName="LearningActivityPort2")
public class LearningActivityRawXmlServiceImpl{

public TransactionResponseMessage updateLearningActivity(LearningActivityMessage learningActivityMsg) { //... return response; } }

Closing notes

Notice that with JAX-WS
  • You don't need webservice.xml - all the necessary information is (may be) provided via annotations
  • You don't need to declare the web services in web.xml unless you need some special configuration (as we do here)