jws

JAX-WS Annotations Example

In this example we shall learn some important JAX-WS annotations provided by Java. To understand this tutorial, following is the prerequisite knowledge required:

  1. Basic knowledge of how to use annotations
  2. Basic SOAP Architecture

1. JAX-WS annotations

1.1 @WebService

This JAX-WS annotation can be used in 2 ways. If we are annotating this over a class, it means that we are trying to mark the class as the implementing the Web Service, in other words Service Implementation Bean (SIB). Or we are marking this over an interface, it means that we are defining a Web Service Interface (SEI), in other words Service Endpoint Interface.

Now lets see the java program demonstrating both of the mentioned ways:

WSAnnotationWebServiceI.java

package com.javacodegeeks.examples.jaxWsAnnotations.webservice;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style=Style.RPC)
public interface WSAnnotationWebServiceI {
	@WebMethod
	float celsiusToFarhenheit(float celsius);
}

In the above program we can see that we haven’t provided any optional element along with the @WebService annotation. And here it is used to define SEI. Regarding the other annotations used in the above program, we shall see their description a little ahead.

WsAnnotationsWebServiceImpl.java

package com.javacodegeeks.examples.jaxWsAnnotations.webservice;

import javax.jws.WebService;

@WebService(endpointInterface="com.javacodegeeks.examples.jaxWsAnnotations.webservice.WSAnnotationWebServiceI")
public class WsAnnotationsWebServiceImpl implements WSAnnotationWebServiceI {
	@Override
	public float celsiusToFarhenheit(float celsius) {
		return ((celsius - 32)*5)/9;
	}
}

In the above program we can see that we have provided an optional element endpointInterface along with the @WebService annotation. And here it is used to define SIB. endpointInterface optional element describes the SEI that the said SIB is implementing.

While implementing a web service as in above example, it is not mandatory for WsAnnotationsWebServiceImpl to implement WSAnnotationWebServiceI, this just serves as a check. Also, it is not mandatory to use an SEI, however, as a basic design principle “We should program to interface”, hence we have adapted this methodology in above program.

Other optional elements to @WebService can be like wsdlLocation that defines location of pre-defined wsdl defining the web service, name that defines name of the web service etc.

1.2 @SOAPBinding

Demonstration of @SOAPBinding JAX-WS annotation has already been shown in first program in 1.1. This annotation is used to specify the SOAP messaging style which can either be RPC or DOCUMENT. This style represents the encoding style of message sent to and fro while using the web service.

With RPC style a web service is capable of only using simple data types like integer or string. However, DOCUMENT style is capable of richer data types for a class let’s say Person, which can have attributes like String name, Address address etc.

Document style indicates that in the underlying web service, underlying message shall contain full XML documents, whereas in the RPC style, the underlying message contains parameters and return values in request and response message respectively. By default the style is Document.

The other important optional attribute is use. It represents the formatting style of the web service message. Its value can either be literal or encoded.

Example usage of @SOAPBinding:

@SOAPBinding(style=Style.DOCUMENT, use=Use.LITERAL)

1.3 @WebMethod

@WebMethod JAX-WS annotation can be applied over a method only. This specified that the method represents a web service operation. For its demonstration, please refer to first program in 1.1.

1.4 @WebResult

To understand this JAX-WS annotation, let’s write SEI & SIB again:

WSAnnotationsWebResultI.java

package com.javacodegeeks.examples.jaxWsAnnotations.webresult;

import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface WSAnnotationsWebResultI {
	@WebMethod
	@WebResult(partName="farhenheitResponse")
	float celsiusToFarhenheit(float celsius);
}

WSAnnotationsWebResultImpl.java

package com.javacodegeeks.examples.jaxWsAnnotations.webresult;

import javax.jws.WebService;

@WebService(endpointInterface="com.javacodegeeks.examples.jaxWsAnnotations.webresult.WSAnnotationsWebResultI")
public class WSAnnotationsWebResultImpl implements WSAnnotationsWebResultI {
	@Override
	public float celsiusToFarhenheit(float celsius) {
		return ((celsius - 32)*5)/9;
	}
}

Now let’s publish this endpoint:

WSPublisher.java

package com.javacodegeeks.examples.jaxWsAnnotations.webresult;

import javax.xml.ws.Endpoint;

public class WSPublisher {
	public static void main(String[] args) {
		Endpoint.publish("http://127.0.0.1:9999/ctf", new WSAnnotationsWebResultImpl());
	}
}

On publishing the generated WSDL (at URL: http://127.0.0.1:9999/ctf?wsdl) would be like:

<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://webresult.jaxWsAnnotations.examples.javacodegeeks.com/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/"
	targetNamespace="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/"
	name="WSAnnotationsWebResultImplService">
	<types />
	<message name="celsiusToFarhenheit">
		<part name="arg0" type="xsd:float" />
	</message>
	<message name="celsiusToFarhenheitResponse">
		<part name="farhenheitResponse" type="xsd:float" />
	</message>
	<portType name="WSAnnotationsWebResultI">
		<operation name="celsiusToFarhenheit">
			<input
				wsam:Action="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/WSAnnotationsWebResultI/celsiusToFarhenheitRequest"
				message="tns:celsiusToFarhenheit" />
			<output
				wsam:Action="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/WSAnnotationsWebResultI/celsiusToFarhenheitResponse"
				message="tns:celsiusToFarhenheitResponse" />
		</operation>
	</portType>
	<binding name="WSAnnotationsWebResultImplPortBinding" type="tns:WSAnnotationsWebResultI">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="rpc" />
		<operation name="celsiusToFarhenheit">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal"
					namespace="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/" />
			</input>
			<output>
				<soap:body use="literal"
					namespace="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/" />
			</output>
		</operation>
	</binding>
	<service name="WSAnnotationsWebResultImplService">
		<port name="WSAnnotationsWebResultImplPort" binding="tns:WSAnnotationsWebResultImplPortBinding">
			<soap:address location="http://127.0.0.1:9999/ctf" />
		</port>
	</service>
</definitions>

Refer to the highlighted line in above wsdl, the part name has been changed to “farhenheitResponse” as was defined using @WebResult. What interest here is that @WebResult can be used to determine what the generated WSDL shall look like.

If we comment out the @WebResult, the WSDL (at URL: http://127.0.0.1:9999/ctf?wsdl) shall be like:

<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://webresult.jaxWsAnnotations.examples.javacodegeeks.com/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/"
	targetNamespace="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/"
	name="WSAnnotationsWebResultImplService">
	<types />
	<message name="celsiusToFarhenheit">
		<part name="arg0" type="xsd:float" />
	</message>
	<message name="celsiusToFarhenheitResponse">
		<part name="return" type="xsd:float" />
	</message>
	<portType name="WSAnnotationsWebResultI">
		<operation name="celsiusToFarhenheit">
			<input
				wsam:Action="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/WSAnnotationsWebResultI/celsiusToFarhenheitRequest"
				message="tns:celsiusToFarhenheit" />
			<output
				wsam:Action="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/WSAnnotationsWebResultI/celsiusToFarhenheitResponse"
				message="tns:celsiusToFarhenheitResponse" />
		</operation>
	</portType>
	<binding name="WSAnnotationsWebResultImplPortBinding" type="tns:WSAnnotationsWebResultI">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="rpc" />
		<operation name="celsiusToFarhenheit">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal"
					namespace="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/" />
			</input>
			<output>
				<soap:body use="literal"
					namespace="http://webresult.jaxWsAnnotations.examples.javacodegeeks.com/" />
			</output>
		</operation>
	</binding>
	<service name="WSAnnotationsWebResultImplService">
		<port name="WSAnnotationsWebResultImplPort" binding="tns:WSAnnotationsWebResultImplPortBinding">
			<soap:address location="http://127.0.0.1:9999/ctf" />
		</port>
	</service>
</definitions>

In the above program, part name has value return.

Other elements to @WebResult are WebParam.Mode that defines the direction in which parameter is flowing, targetNamespace to define XML namespace for the parameter.

1.5 @WebServiceClient

To understand @WebServiceClient JAX-WS annotation, let us first publish the endpoint written in 1.1 using below program:

WSPublisher.java

package com.javacodegeeks.examples.jaxWsAnnotations.webservice;

import javax.xml.ws.Endpoint;

public class WSPublisher {
	public static void main(String[] args) {
		Endpoint.publish("http://127.0.0.1:9999/ctf", new WsAnnotationsWebServiceImpl());
	}
}

Before moving further we should understand wsimport utility provided by Java that eases the task of writing client for a SOAP based web service. We won’t go into much detail here about wsimport, instead let’s first save the wsdl file with name ‘ctf.wsdl’ and then write following command on the command prompt:

wsimport -keep -p client ctf.wsdl

The generated code shall have following classes generated:

Client files generated
Client files generated

Now let’s open WsAnnotationsWebServiceImplService.java. It shall be like:

WsAnnotationsWebServiceImplService.java

package client;

import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;

/**
 * This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035
 * Generated source version: 2.2
 * 
 */
@WebServiceClient(name = "WsAnnotationsWebServiceImplService", targetNamespace = "http://webservice.jaxWsAnnotations.examples.javacodegeeks.com/", wsdlLocation = "file:/Users/saurabharora123/Downloads/ctf.wsdl")
public class WsAnnotationsWebServiceImplService extends Service {

	private final static URL WSANNOTATIONSWEBSERVICEIMPLSERVICE_WSDL_LOCATION;
	private final static WebServiceException WSANNOTATIONSWEBSERVICEIMPLSERVICE_EXCEPTION;
	private final static QName WSANNOTATIONSWEBSERVICEIMPLSERVICE_QNAME = new QName(
			"http://webservice.jaxWsAnnotations.examples.javacodegeeks.com/", "WsAnnotationsWebServiceImplService");

	static {
		URL url = null;
		WebServiceException e = null;
		try {
			url = new URL("file:/Users/saurabharora123/Downloads/ctf.wsdl");
		} catch (MalformedURLException ex) {
			e = new WebServiceException(ex);
		}
		WSANNOTATIONSWEBSERVICEIMPLSERVICE_WSDL_LOCATION = url;
		WSANNOTATIONSWEBSERVICEIMPLSERVICE_EXCEPTION = e;
	}

	public WsAnnotationsWebServiceImplService() {
		super(__getWsdlLocation(), WSANNOTATIONSWEBSERVICEIMPLSERVICE_QNAME);
	}

	public WsAnnotationsWebServiceImplService(WebServiceFeature... features) {
		super(__getWsdlLocation(), WSANNOTATIONSWEBSERVICEIMPLSERVICE_QNAME, features);
	}

	public WsAnnotationsWebServiceImplService(URL wsdlLocation) {
		super(wsdlLocation, WSANNOTATIONSWEBSERVICEIMPLSERVICE_QNAME);
	}

	public WsAnnotationsWebServiceImplService(URL wsdlLocation, WebServiceFeature... features) {
		super(wsdlLocation, WSANNOTATIONSWEBSERVICEIMPLSERVICE_QNAME, features);
	}

	public WsAnnotationsWebServiceImplService(URL wsdlLocation, QName serviceName) {
		super(wsdlLocation, serviceName);
	}

	public WsAnnotationsWebServiceImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
		super(wsdlLocation, serviceName, features);
	}

	/**
	 * 
	 * @return returns WSAnnotationWebServiceI
	 */
	@WebEndpoint(name = "WsAnnotationsWebServiceImplPort")
	public WSAnnotationWebServiceI getWsAnnotationsWebServiceImplPort() {
		return super.getPort(new QName("http://webservice.jaxWsAnnotations.examples.javacodegeeks.com/",
				"WsAnnotationsWebServiceImplPort"), WSAnnotationWebServiceI.class);
	}

	/**
	 * 
	 * @param features
	 *            A list of {@link javax.xml.ws.WebServiceFeature} to configure
	 *            on the proxy. Supported features not in the
	 *            features parameter will have their default
	 *            values.
	 * @return returns WSAnnotationWebServiceI
	 */
	@WebEndpoint(name = "WsAnnotationsWebServiceImplPort")
	public WSAnnotationWebServiceI getWsAnnotationsWebServiceImplPort(WebServiceFeature... features) {
		return super.getPort(new QName("http://webservice.jaxWsAnnotations.examples.javacodegeeks.com/",
				"WsAnnotationsWebServiceImplPort"), WSAnnotationWebServiceI.class, features);
	}

	private static URL __getWsdlLocation() {
		if (WSANNOTATIONSWEBSERVICEIMPLSERVICE_EXCEPTION != null) {
			throw WSANNOTATIONSWEBSERVICEIMPLSERVICE_EXCEPTION;
		}
		return WSANNOTATIONSWEBSERVICEIMPLSERVICE_WSDL_LOCATION;
	}

}

Refer to the highlighted line in the above generated program that has the annotation @WebServiceClient. The information specified in this annotation helps in identifying a wsdl:service element inside a WSDL document. This element represents the Web service for which the generated service interface provides a client view.

1.6 @RequestWrapper

@RequestWrapper JAX-WS annotation is used to annotate methods in the Service Endpoint Interface with the request wrapper bean to be used at runtime. It has 4 optional elements; className that represents the request wrapper bean name, localName that represents element’s local name, partName that represent the part name of the wrapper part in the generated WSDL file, and targetNamespace that represents the element’s namespace.

Example usage: WSRequestWrapperInterface.java

package com.javacodegeeks.examples.jaxWsAnnotations.wrapper;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.RequestWrapper;

@WebService
@SOAPBinding(style=Style.RPC)
public interface WSRequestWrapperInterface {
	@WebMethod
	@RequestWrapper(localName="CTF", 
	targetNamespace="http://javacodegeeks.com/tempUtil", 
	className="com.javacodegeeks.examples.jaxWsAnnotations.webservice.CTF")
	float celsiusToFarhenheit(float celsius);
}

1.7 @ResponseWrapper

@ResponseWrapper JAX-WS annotation is used to annotate methods in the Service Endpoint Interface with the response wrapper bean to be used at runtime. It has 4 optional elements; className that represents the response wrapper bean name, localName that represents element’s local name, partName that represent the part name of the wrapper part in the generated WSDL file, and targetNamespace that represents the element’s namespace.

Example usage: WSRequestWrapperInterface.java

package com.javacodegeeks.examples.jaxWsAnnotations.wrapper;

import javax.jws.WebMethod;
import javax.xml.ws.ResponseWrapper;

public interface WSResponseWrapperInterfaceI {
	@WebMethod
	@ResponseWrapper(localName="CTFResponse", 
	targetNamespace="http://javacodegeeks.com/tempUtil", 
	className="com.javacodegeeks.examples.jaxWsAnnotations.webservice.CTFResponse")
	float celsiusToFarhenheit(float celsius);
}

1.8 @Oneway

@Oneway JAX-WS annotation is applied to WebMethod which means that method will have only input and no output. When a @Oneway method is called, control is returned to calling method even before the actual operation is performed. It means that nothing will escape method neither response neither exception.

Example usage: WSAnnotationsOnewayI.java

package com.javacodegeeks.examples.jaxWsAnnotations.oneway;

import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface WSAnnotationsOnewayI {
	@WebMethod
	@Oneway
	void sayHello();
}

1.9 @HandlerChain

Web Services and their clients may need to access the SOAP message for additional processing of the message request or response. A SOAP message handler provides a mechanism for intercepting the SOAP message during request and response.

A handler at server side can be a validator. Let’s say we want to validate the temperature before the actual service method is called. To do this our validator class shall implement interface SOAPHandler

TemperatureValidator.java

package com.javacodegeeks.examples.jaxWsAnnotations.handler;

import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class TemperatureValidator implements SOAPHandler {

	@Override
	public boolean handleMessage(SOAPMessageContext context) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean handleFault(SOAPMessageContext context) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void close(MessageContext context) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Set getHeaders() {
		// TODO Auto-generated method stub
		return null;
	}

}

Next we shall implement SOAP handler xml file that may also contain sequence of handlers.

soap-handler.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>com.javacodegeeks.examples.jaxWsAnnotations.handler.TemperatureValidator
			</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
</javaee:handler-chains>

After this we shall configure @HandlerChain JAX-WS annotation in SEI:

WSAnnotationsHandlerChainI.java

package com.javacodegeeks.examples.jaxWsAnnotations.handler;

import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface WSAnnotationsHandlerChainI {
	@HandlerChain(file = "soap-handler.xml")
	@WebMethod
	float celsiusToFarhenheit(float celsius);
}

2. Directory structure of this example

The directory structure of the above example in eclipse shall look like:

Directory Structure
Directory Structure

3. Download the source code

This was an example of JAX-WS annotations.

Download
You can download the full source code of this example here: JaxWSAnnotationsExample

Saurabh Arora

Saurabh graduated with an engineering degree in Information Technology from YMCA Institute of Engineering, India. He is SCJP, OCWCD certified and currently working as Technical Lead with one of the biggest service based firms and is involved in projects extensively using Java and JEE technologies. He has worked in E-Commerce, Banking and Telecom domain.
Subscribe
Notify of
guest

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

0 Comments
Inline Feedbacks
View all comments
Back to top button