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.
Table Of Contents
1. What are Web Services?
Web service is a distributed webified application typically delivered over HTTP. The 3 key features of Web Services are:
- Open infrastructure
- Language transparency
- 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.
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:
- 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. - 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.
- 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. - binding: This tag is kind of implementation of a Java interface. Here concrete details of web service are present.
- 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:
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.
Thanks!!
Thanks, easy to understand and works at once (after adjusting file path of WSDL file in class PersonServiceImplService).
How do you deploy the application in a webserver after that?