jws

JAX-WS Web Service Example

In this example we shall learn implementing JAX-WS Web Service. JAX-WS are the API’s provided by Java for implementing Web Service.
Here, we shall start by learning what web services are, their architecture, followed by implementation of server and client. We shall also learn the different variants of XML Web Service and the WSDL file which is the contract that defines a Web Service.

1. What are Web Services?

Web service is a distributed webified application typically delivered over HTTP. The 3 key features of Web Services are:

  1. Open infrastructure
  2. Language transparency
  3. Modular design

The major appeal of Web Services are language transparency, server and client can be written in different languages. And this language transparency is the key to web service interoperability.

Web service can be divided into 2 groups, SOAP and REST.

SOAP stands for Simple Object Access Protocol and is a XML based web service. In this example, our entire focus shall be on SOAP based web service.

REST stands for REpresentational State Transfer. REST doesn’t have any standard like SOAP has and works using standard HTTP methods like PUT, GET, DELETE and POST.

Coming back to SOAP, it follows a simple architecture, client uses SOAP libraries to construct request and send it to server. Server uses SOAP libraries to decode request and construct corresponding response.

SOAP Architecture
SOAP Architecture

2. Implementing JAX-WS Web Service Server

2.1 Implementing Service Endpoint Interface

The first step in implementing Web Service server is writing Service Endpoint Interface. This interface defines the methods that shall be exposed by the web service. Let’s look at one example.

CalculatorI.java

package com.javacodegeeks.examples.jaxws;

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 CalculatorI {
	@WebMethod
	int add(int a, int b);

	@WebMethod
	int subtract(int a, int b);

	@WebMethod
	int multiply(int a, int b);

	@WebMethod
	int divide(int a, int b);
}

In the above program @SOAPBinding 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.

Also, @WebMethod annotation used above specifies that the method represents a web service operation.

2.2 Implementing Service Implementation Bean

Nest step is to write the implementation of Service Endpoint Interface which is called Service Implementation Bean.

CalculatorImpl.java

package com.javacodegeeks.examples.jaxws;

import javax.jws.WebService;

@WebService(endpointInterface = "com.javacodegeeks.examples.jaxws.CalculatorI")
public class CalculatorImpl implements CalculatorI {

	@Override
	public int add(int a, int b) {
		return a + b;
	}

	@Override
	public int subtract(int a, int b) {
		return a - b;
	}

	@Override
	public int multiply(int a, int b) {
		return a * b;
	}

	@Override
	public int divide(int a, int b) {
		return a / b;
	}

}

In the above program we can see that we have provided an optional element endpointInterface to @WebService annotation which says that this class is implementation of the mentioned Service Endpoint Interface.

2.3 Publishing Endpoint

Next step and the last step for completing and running the server for this example is running a small program that shall take the Service Implementation Bean object and shall publish this as a web service.

CalcPublisher.java

package com.javacodegeeks.examples.jaxws;

import javax.xml.ws.Endpoint;

public class CalcPublisher {

	public static void main(String[] args) {
		Endpoint ep = Endpoint.create(new CalculatorImpl());
		ep.publish("http://127.0.0.1:10000/calcServer");
	}

}

On running the above main program, web service shall be hosted at the URL passed as argument to the publish() method in the above program.

3. WSDL explained

To test the Web Service we can open a browser and view the WSDL which stands for Web Service Definition Language. For the web service published in section 2.3, the URL to access the WSDL shall be http://127.0.0.1:10000/calcServer?wsdl. This is the URL at which the Web Service was published followed by ?wsdl.

Let’s access this WSDL and save this in a file say calculator.wsdl.

calculator.wsdl

<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS 
	RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
<!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS 
	RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
<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://jaxws.examples.javacodegeeks.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.examples.javacodegeeks.com/"
	name="CalculatorImplService">
	<types />
	<message name="add">
		<part name="arg0" type="xsd:int" />
		<part name="arg1" type="xsd:int" />
	</message>
	<message name="addResponse">
		<part name="return" type="xsd:int" />
	</message>
	<message name="divide">
		<part name="arg0" type="xsd:int" />
		<part name="arg1" type="xsd:int" />
	</message>
	<message name="divideResponse">
		<part name="return" type="xsd:int" />
	</message>
	<message name="subtract">
		<part name="arg0" type="xsd:int" />
		<part name="arg1" type="xsd:int" />
	</message>
	<message name="subtractResponse">
		<part name="return" type="xsd:int" />
	</message>
	<message name="multiply">
		<part name="arg0" type="xsd:int" />
		<part name="arg1" type="xsd:int" />
	</message>
	<message name="multiplyResponse">
		<part name="return" type="xsd:int" />
	</message>
	<portType name="CalculatorI">
		<operation name="add" parameterOrder="arg0 arg1">
			<input
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/addRequest"
				message="tns:add" />
			<output
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/addResponse"
				message="tns:addResponse" />
		</operation>
		<operation name="divide" parameterOrder="arg0 arg1">
			<input
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/divideRequest"
				message="tns:divide" />
			<output
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/divideResponse"
				message="tns:divideResponse" />
		</operation>
		<operation name="subtract" parameterOrder="arg0 arg1">
			<input
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/subtractRequest"
				message="tns:subtract" />
			<output
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/subtractResponse"
				message="tns:subtractResponse" />
		</operation>
		<operation name="multiply" parameterOrder="arg0 arg1">
			<input
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/multiplyRequest"
				message="tns:multiply" />
			<output
				wsam:Action="http://jaxws.examples.javacodegeeks.com/CalculatorI/multiplyResponse"
				message="tns:multiplyResponse" />
		</operation>
	</portType>
	<binding name="CalculatorImplPortBinding" type="tns:CalculatorI">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="rpc" />
		<operation name="add">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</input>
			<output>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</output>
		</operation>
		<operation name="divide">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</input>
			<output>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</output>
		</operation>
		<operation name="subtract">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</input>
			<output>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</output>
		</operation>
		<operation name="multiply">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</input>
			<output>
				<soap:body use="literal" namespace="http://jaxws.examples.javacodegeeks.com/" />
			</output>
		</operation>
	</binding>
	<service name="CalculatorImplService">
		<port name="CalculatorImplPort" binding="tns:CalculatorImplPortBinding">
			<soap:address location="http://127.0.0.1:10000/calcServer" />
		</port>
	</service>
</definitions>

This WSDL file is an XML format describing the web service. This is a strict contract and describes messages and operations at an abstract level. Let’s understand each tag of the WSDL file to get clear picture:

  1. types: This optional tag represents data types in an XSD. This tag might hold or point to an XSD. If we find this tag as empty as in above WSDL, then it means that the Web Service uses simple data types. For complex data types, DOCUMENT style web services are implemented which is explained in next section.
  2. message: This tag defines the messages that implement the web service. These messages are constructed from messages that are defined in types section, also it defines in out order of messages that represents request response pattern of web service operation.
  3. portType: This tag represents service as named operations, with each operation using one ore more messages. These operations are defined after method names defined against @WebMethods annotation. It is a kind of Java Interface defining the web service at an abstract level.
  4. binding: This tag is kind of implementation of a Java interface. Here concrete details of web service are present.
  5. service: This tag contains information about one or more endpoints where web service functionality is available.

4. Document style Web Services

Notice that the web service that we implemented in section 2 is using simple or primitive data types. But think of a scenario if we want to return Person object based on id. In this case we use Document style web services.

First let’s implement POJO class Person.

Person.java

package com.javacodegeeks.examples.jaxws;

public class Person {
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Person(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Person() {
		super();
	}
}

Next we shall implement a PersonUtil class. This utility class shall help in managing Person data. In production environment, we might be fetching data from the database.

PersonUtil.java

package com.javacodegeeks.examples.jaxws;

import java.util.HashMap;
import java.util.Map;

public class PersonUtil {
	private static Map map;
	
	static {
		map = new HashMap();
		map.put(1, new Person(1, "A"));
		map.put(2, new Person(2, "B"));
		map.put(3, new Person(3, "C"));
		map.put(4, new Person(4, "D"));
		map.put(5, new Person(5, "E"));
	}

	private PersonUtil() {
	}

	public static Person getPerson(Integer id) {
		return map.get(id);
	}
}

Next we shall implement Service Endpoint Inteface for DOCUMENT style web service.

PersonServiceI.java

package com.javacodegeeks.examples.jaxws;

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

@WebService
@SOAPBinding(style = Style.DOCUMENT)
public interface PersonServiceI {
	@WebMethod
	Person getPerson(Integer id);
}

Notice here that in the @SOAPBinding annotation, style attribute has just been changed to DOCUMENT.

Service Implementation Bean for the above interface shall be like:

PersonServiceImpl.java

package com.javacodegeeks.examples.jaxws;

import javax.jws.WebService;

@WebService(endpointInterface = "com.javacodegeeks.examples.jaxws.PersonServiceI")
public class PersonServiceImpl implements PersonServiceI {

	@Override
	public Person getPerson(Integer id) {
		return PersonUtil.getPerson(id);
	}

}

Next task is to publish the web service.

PersonPublisher.java

package com.javacodegeeks.examples.jaxws;

import javax.xml.ws.Endpoint;

public class PersonPublisher {

	public static void main(String[] args) {
		Endpoint ep = Endpoint.create(new PersonServiceImpl());
		ep.publish("http://127.0.0.1:10000/personServer");
	}

}

On executing this program we can check the WSDL at URL http://127.0.0.1:10000/personServer?wsdl. Let’s save this WSDL file as personService.wsdl.

personService.wsdl

<!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS 
	RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
<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://jaxws.examples.javacodegeeks.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://jaxws.examples.javacodegeeks.com/"
	name="PersonServiceImplService">
	<types>
		<xsd:schema>
			<xsd:import namespace="http://jaxws.examples.javacodegeeks.com/"
				schemaLocation="http://127.0.0.1:10000/personServer?xsd=1" />
		</xsd:schema>
	</types>
	<message name="getPerson">
		<part name="parameters" element="tns:getPerson" />
	</message>
	<message name="getPersonResponse">
		<part name="parameters" element="tns:getPersonResponse" />
	</message>
	<portType name="PersonServiceI">
		<operation name="getPerson">
			<input
				wsam:Action="http://jaxws.examples.javacodegeeks.com/PersonServiceI/getPersonRequest"
				message="tns:getPerson" />
			<output
				wsam:Action="http://jaxws.examples.javacodegeeks.com/PersonServiceI/getPersonResponse"
				message="tns:getPersonResponse" />
		</operation>
	</portType>
	<binding name="PersonServiceImplPortBinding" type="tns:PersonServiceI">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="document" />
		<operation name="getPerson">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" />
			</input>
			<output>
				<soap:body use="literal" />
			</output>
		</operation>
	</binding>
	<service name="PersonServiceImplService">
		<port name="PersonServiceImplPort" binding="tns:PersonServiceImplPortBinding">
			<soap:address location="http://127.0.0.1:10000/personServer" />
		</port>
	</service>
</definitions>

Notice the change here in types tag and messages tag. The types tag here says that it is importing schema from URL http://127.0.0.1:10000/personServer?xsd=1.

personService.xsd

<xs:schema xmlns:tns="http://jaxws.examples.javacodegeeks.com/"
	xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
	targetNamespace="http://jaxws.examples.javacodegeeks.com/">
	<xs:element name="getPerson" type="tns:getPerson" />
	<xs:element name="getPersonResponse" type="tns:getPersonResponse" />
	<xs:complexType name="getPerson">
		<xs:sequence>
			<xs:element name="arg0" type="xs:int" minOccurs="0" />
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="getPersonResponse">
		<xs:sequence>
			<xs:element name="return" type="tns:person" minOccurs="0" />
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="person">
		<xs:sequence>
			<xs:element name="id" type="xs:int" />
			<xs:element name="name" type="xs:string" minOccurs="0" />
		</xs:sequence>
	</xs:complexType>
</xs:schema>

5. Testing Web Service

In this section we shall implement web service client for the service implemented in section 4 to test the same. On the same pattern web service implemented in section 2 can be tested.

We shall use Java provided wsimport utility that helps in generating this client support code using the WSDL document.

Go to command prompt/bash, browse to the location where personService.wsdl was saved, and enter following command:

$ wsimport -keep -p client personService.wsdl

This command shall generated following client support code:

wsimport Generated Code
wsimport Generated Code

Now we shall use this code in client project and call and check the web service.

PersonServiceClient.java

package com.javacodegeeks.examples.jaxws.client;

import client.PersonServiceI;
import client.PersonServiceImplService;

public class PersonServiceClient {

	public static void main(String[] args) {
		PersonServiceImplService service = new PersonServiceImplService();
		PersonServiceI pService = service.getPersonServiceImplPort();
		
		System.out.println(pService.getPerson(1).getName());
		System.out.println(pService.getPerson(2).getName());
		System.out.println(pService.getPerson(3).getName());
		System.out.println(pService.getPerson(4).getName());
		System.out.println(pService.getPerson(5).getName());
	}

}

Output of this client program shall be:

A
B
C
D
E

6. Download the source code

This example has 2 eclipse projects (server and client) for demonstrating example of JAX-WS Web Service.

Download
You can download the full source code of this example here: JAX-WS Web Service Example

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.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Jesus Villalba
Jesus Villalba
5 years ago

Thanks!!

Bernhard Fischer
Bernhard Fischer
4 years ago

Thanks, easy to understand and works at once (after adjusting file path of WSDL file in class PersonServiceImplService).

Daniel
4 years ago

How do you deploy the application in a webserver after that?

Back to top button