JAX-WS Tutorial

Filed Under: Java

Welcome to JAX-WS Tutorial. Web Services work on client-server model where they communicate over the network. Server side component provides the endpoint URL where service is located and client application can invoke different methods.

There are two types of web services:

  1. SOAP Web Services
  2. Restful Web Services

JAX-WS Tutorial

jax-ws tutorial, jax-ws, jax ws tutorial, jax-ws example

In this JAX-WS tutorial, we will use JAX-WS to create SOAP based web services. But first we will go through some of the jargon words used in SOAP web services.

SOAP

SOAP stands for Simple Object Access Protocol. SOAP is an XML based industry standard protocol for designing and developing web services. Since it’s XML based, it’s platform and language independent. So our server can be based on JAVA and client can be on .NET, PHP etc. and vice versa.

WSDL

WSDL stands for Web Service Description Language. WSDL is an XML based document that provides technical details about the web service. Some of the useful information in WSDL document are: method name, port types, service end point, binding, method parameters etc.

UDDI

UDDI is acronym for Universal Description, Discovery and Integration. UDDI is a directory of web services where client applications can lookup for web services. Web Services can register to the UDDI server and make them available to client applications.

Advantages of Web Services

Some of the advantages of web services are:

  • Interoperability: Because web services work over network and use XML technology to communicate, it can be developed in any programming language supporting web services development.
  • Reusability: One web service can be used by many client applications at the same time. For example, we can expose a web service for technical analysis of a stock and it can be used by all the banks and financial institutions.
  • Loose Coupling: Web services client code is totally independent with server code, so we have achieved loose coupling in our application. This leads to easy maintenance and easy to extend.
  • Easy to deploy and integrate
  • Multiple service versions can be running at same time.

JAX-WS

JAX-WS stands for Java API for XML Web Services. JAX-WS is XML based Java API to build web services server and client application. It’s part of standard Java API, so we don’t need to include anything else which working with it.

JAX-WS Example

Now that we have gone through the web services terminologies, let’s go ahead and create a JAX-WS web service. We will create a web service that will expose methods to add, delete and get person objects. So first of all we will create a model bean for our data.

Person.java


package com.journaldev.jaxws.beans;

import java.io.Serializable;

public class Person implements Serializable{

	private static final long serialVersionUID = -5577579081118070434L;
	
	private String name;
	private int age;
	private int id;

	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	
	@Override
	public String toString(){
		return id+"::"+name+"::"+age;
	}

}

Now we will have to create an interface where we will declare the methods we will expose in our JAX-WS example web services.

PersonService.java


package com.journaldev.jaxws.service;

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

import com.journaldev.jaxws.beans.Person;

@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface PersonService {

	@WebMethod
	public boolean addPerson(Person p);
	
	@WebMethod
	public boolean deletePerson(int id);
	
	@WebMethod
	public Person getPerson(int id);
	
	@WebMethod
	public Person[] getAllPersons();
}

Notice the use of @WebService and @SOAPBinding annotations from JAX-WS API. We can create SOAP web services in RPC style or Document style. We can use any of these styles to create web services, the different is seen in the way WSDL file is generated.

Now we will write the implementation class as shown below.

PersonServiceImpl.java


package com.journaldev.jaxws.service;

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

import javax.jws.WebService;

import com.journaldev.jaxws.beans.Person;

@WebService(endpointInterface = "com.journaldev.jaxws.service.PersonService")  
public class PersonServiceImpl implements PersonService {

	private static Map<Integer,Person> persons = new HashMap<Integer,Person>();
	
	@Override
	public boolean addPerson(Person p) {
		if(persons.get(p.getId()) != null) return false;
		persons.put(p.getId(), p);
		return true;
	}

	@Override
	public boolean deletePerson(int id) {
		if(persons.get(id) == null) return false;
		persons.remove(id);
		return true;
	}

	@Override
	public Person getPerson(int id) {
		return persons.get(id);
	}

	@Override
	public Person[] getAllPersons() {
		Set<Integer> ids = persons.keySet();
		Person[] p = new Person[ids.size()];
		int i=0;
		for(Integer id : ids){
			p[i] = persons.get(id);
			i++;
		}
		return p;
	}

}

Most important part is the @WebService annotation where we are providing endpointInterface value as the interface we have for our web service. This way JAX-WS know the class to use for implementation when web service methods are invoked.

Our web service business logic is ready, let’s go ahead and publish it using JAX-WS Endpoint class.

SOAPPublisher.java


package com.journaldev.jaxws.service;

import javax.xml.ws.Endpoint;

public class SOAPPublisher {

	public static void main(String[] args) {
		 Endpoint.publish("http://localhost:8888/ws/person", new PersonServiceImpl());  
	}

}

Just run the above program and your web service will be published at the given endpoint in the program. We can access it’s WSDL document by adding ?wsdl to the endpoint url as shown in below image.

JAX WS WSDL Document, JAX-WS Tutorial, JAX-WS

Here is the WSDL code, we will use some of the values from these while writing the client code.

person.wsdl


<?xml version="1.0" encoding="UTF-8"?><!-- 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://service.jaxws.journaldev.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://service.jaxws.journaldev.com/" name="PersonServiceImplService">
<types>
<xsd:schema>
<xsd:import namespace="http://service.jaxws.journaldev.com/" schemaLocation="http://localhost:8888/ws/person?xsd=1"></xsd:import>
</xsd:schema>
</types>
<message name="addPerson">
<part name="arg0" type="tns:person"></part>
</message>
<message name="addPersonResponse">
<part name="return" type="xsd:boolean"></part>
</message>
<message name="deletePerson">
<part name="arg0" type="xsd:int"></part>
</message>
<message name="deletePersonResponse">
<part name="return" type="xsd:boolean"></part>
</message>
<message name="getPerson">
<part name="arg0" type="xsd:int"></part>
</message>
<message name="getPersonResponse">
<part name="return" type="tns:person"></part>
</message>
<message name="getAllPersons"></message>
<message name="getAllPersonsResponse">
<part name="return" type="tns:personArray"></part>
</message>
<portType name="PersonService">
<operation name="addPerson">
<input wsam:Action="http://service.jaxws.journaldev.com/PersonService/addPersonRequest" message="tns:addPerson"></input>
<output wsam:Action="http://service.jaxws.journaldev.com/PersonService/addPersonResponse" message="tns:addPersonResponse"></output>
</operation>
<operation name="deletePerson">
<input wsam:Action="http://service.jaxws.journaldev.com/PersonService/deletePersonRequest" message="tns:deletePerson"></input>
<output wsam:Action="http://service.jaxws.journaldev.com/PersonService/deletePersonResponse" message="tns:deletePersonResponse"></output>
</operation>
<operation name="getPerson">
<input wsam:Action="http://service.jaxws.journaldev.com/PersonService/getPersonRequest" message="tns:getPerson"></input>
<output wsam:Action="http://service.jaxws.journaldev.com/PersonService/getPersonResponse" message="tns:getPersonResponse"></output>
</operation>
<operation name="getAllPersons">
<input wsam:Action="http://service.jaxws.journaldev.com/PersonService/getAllPersonsRequest" message="tns:getAllPersons"></input>
<output wsam:Action="http://service.jaxws.journaldev.com/PersonService/getAllPersonsResponse" message="tns:getAllPersonsResponse"></output>
</operation>
</portType>
<binding name="PersonServiceImplPortBinding" type="tns:PersonService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"></soap:binding>
<operation name="addPerson">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</output>
</operation>
<operation name="deletePerson">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</output>
</operation>
<operation name="getPerson">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</output>
</operation>
<operation name="getAllPersons">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</input>
<output>
<soap:body use="literal" namespace="http://service.jaxws.journaldev.com/"></soap:body>
</output>
</operation>
</binding>
<service name="PersonServiceImplService">
<port name="PersonServiceImplPort" binding="tns:PersonServiceImplPortBinding">
<soap:address location="http://localhost:8888/ws/person"></soap:address>
</port>
</service>
</definitions>

Here is a client program where we are invoking our JAX-WS example web service.

SOAPPublisherClient.java


package com.journaldev.jaxws.service;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import com.journaldev.jaxws.beans.Person;

public class SOAPPublisherClient {

	public static void main(String[] args) throws MalformedURLException {
		URL wsdlURL = new URL("http://localhost:8888/ws/person?wsdl");
		//check above URL in browser, you should see WSDL file
		
		//creating QName using targetNamespace and name
		QName qname = new QName("http://service.jaxws.journaldev.com/", "PersonServiceImplService"); 
		
		Service service = Service.create(wsdlURL, qname);  
		
		//We need to pass interface and model beans to client
		PersonService ps = service.getPort(PersonService.class);
		
		Person p1 = new Person(); p1.setName("Pankaj"); p1.setId(1); p1.setAge(30);
		Person p2 = new Person(); p2.setName("Meghna"); p2.setId(2); p2.setAge(25);
		
		//add person
		System.out.println("Add Person Status="+ps.addPerson(p1));
		System.out.println("Add Person Status="+ps.addPerson(p2));
		
		//get person
		System.out.println(ps.getPerson(1));
		
		//get all persons
		System.out.println(Arrays.asList(ps.getAllPersons()));
		
		//delete person
		System.out.println("Delete Person Status="+ps.deletePerson(2));
		
		//get all persons
		System.out.println(Arrays.asList(ps.getAllPersons()));
		
	}

}

When we execute above JAX-WS client program, we get this output.


Add Person Status=true
Add Person Status=true
1::Pankaj::30
[1::Pankaj::30, 2::Meghna::25]
Delete Person Status=true
[1::Pankaj::30]

When I run the program again, we get this output.


Add Person Status=false
Add Person Status=true
1::Pankaj::30
[1::Pankaj::30, 2::Meghna::25]
Delete Person Status=true
[1::Pankaj::30]

Notice that in the second run, add person status is false because it was already added in the first run.

JAX-WS Client Program

If you look at the above program, we are using the server code itself. However web services just expose WSDL and third party applications don’t have access to these classes. So in that case, we can use wsimport utility to generate the client stubs. This utility comes with standard installation of JDK. Below image shows what all java classes we get when we run this utility.

wsimport utility parse wsdl, wsimport

Just copy these classes into your client project, the only change would be the way we get PersonService instance.

Below is the program for this, the output will be same as above client program. Notice the use of PersonServiceImplService class and it’s method getPersonServiceImplPort to get the PersonService instance.

TestPersonService.java


package com.journaldev.jaxws.service.test;

import java.util.Arrays;

import com.journaldev.jaxws.service.Person;
import com.journaldev.jaxws.service.PersonService;
import com.journaldev.jaxws.service.PersonServiceImplService;

public class TestPersonService {

	public static void main(String[] args) {
		
		PersonServiceImplService serviceImpl = new PersonServiceImplService();
		
		PersonService service = serviceImpl.getPersonServiceImplPort();
		
		Person p1 = new Person(); p1.setName("Pankaj"); p1.setId(1); p1.setAge(30);
        Person p2 = new Person(); p2.setName("Meghna"); p2.setId(2); p2.setAge(25);
        
        System.out.println("Add Person Status="+service.addPerson(p1));
        System.out.println("Add Person Status="+service.addPerson(p2));
        
      //get person
        System.out.println(service.getPerson(1));
         
        //get all persons
        System.out.println(Arrays.asList(service.getAllPersons()));
         
        //delete person
        System.out.println("Delete Person Status="+service.deletePerson(2));
         
        //get all persons
        System.out.println(Arrays.asList(service.getAllPersons()));
        
	}

}

That’s all for a quick JAX-WS tutorial.

Comments

  1. Praful Anand says:

    Hi Pankaj,

    Above soap web service working fine with soap request and its content type as text/xml. Please help me to write soap web service with content type of soap request as application/xml. Above web service not working with content type of soap request as application/xml.

    SEVERE: Unsupported Content-Type: application/xml Supported ones are: [text/xml].

    Please write a program of soap web service that will take content type of soap request as application/xml.

  2. Praful Anand says:

    Hi Pankaj,

    The WSDL file/URL (http://localhost:8888/ws/person?wsdl) of above soap web service is not being executed on other systems(PC) (systems apart from the system on which Endpoint.publish(“http://localhost:8888/ws/person”, new PersonServiceImpl()) is executed) Can you please write the program for the soap web service whose WSDL file/URL can be executed at any PC/system)?

    1. Pankaj says:

      When you specify localhost, it looks for the WSDL file in the local system. If you are running it on some server, then you will have to give the IP address. Also, the ports should be accessible from the outside world.

  3. Achutha says:

    Can you send me the project structure,web.xml and required jars

  4. Deepak says:

    While accessing the WSDL, getting the output as below:

    <?xml version=”1.0″ encoding=”UTF-8″?>

    -<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/”>

    -<soapenv:Body>

    -<soapenv:Fault>

    <faultcode/>

    <faultstring>0</faultstring>

    -<detail>

    <Exception>java.lang.ArrayIndexOutOfBoundsException: 0 at org.apache.axis2.description.AxisService.getWSDL(AxisService.java:1643) at org.apache.axis2.description.AxisService.printWSDL(AxisService.java:1413) at org.apache.axis2.transport.http.HTTPWorker.service(HTTPWorker.java:154) at org.apache.axis2.transport.http.server.AxisHttpService.doService(AxisHttpService.java:281) at org.apache.axis2.transport.http.server.AxisHttpService.handleRequest(AxisHttpService.java:187) at org.apache.axis2.transport.http.server.HttpServiceProcessor.run(HttpServiceProcessor.java:82) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) </Exception>

    </detail>

    </soapenv:Fault>

    </soapenv:Body>

    </soapenv:Envelope>

    Please suggest.

  5. Yihua Shen says:

    In the client side Person.java generated by wsimport, the toString() method is lost. Did I miss anything, or it’s a bug of wsimport? Also, in the TestPersonService.java, I have to use
    System.out.println(service.getAllPersons().getItem());
    instead of
    System.out.println(Arrays.asList(service.getAllPersons()));
    to print out the list. I use java 1.8

  6. Yash Somani says:

    Result
    Exception: No such operation ‘getAll’ Message: No such operation ‘getAll’

  7. Sudarshan Amirineni says:

    Can you share the file structure and all the commands used to deploy the project ?

  8. Naveed Khan says:

    Nice tutorial, Thanks Pankaj for providing basics of SOAP, God bless you.

  9. Raj Gopal says:

    Can you please specify which version of java , tomcat server , and Axis 2 server were used for this project

  10. Abhishek Prasad says:

    Can you send me the project structure?

    Thanks,
    Abhishek Prasad

  11. Tejas Khairnar says:

    Hi,

    I have followed the tutorial and used wsimport to generate all java classes from the wsdl location. I have imported these into my spring boot project. I am using jaxws-ri 2.3.0. Everything works completely fine when i run my springboot project using the embedded tomcat container.
    When I am deploying the war file onto my server running tomcat 8.5.24, the code gets stuck when i am trying to create an object of the class generated by wsimport service. Becuase of that I am not able to make the SOAP call from my server.
    i will highly appreciate any suggestions/advice in this direction.

    Thanks,
    Tejas.

    1. Pankaj says:

      Can you please let me know what is the error/exceptions you get? Also, check the WAR contents to make sure all the classes are present in that.

  12. marco says:

    woa, great tutorial. THANKS!

  13. Nathan says:

    Two things:
    1)
    When you write the implementation of the Person class, you put it in a Package called “…beans” yet when you reference it in your TestPersonService.java class, you import it from a package called “…service”.

    2)
    When trying to recreate TestPersonService.java in a different project, I am getting the error: “The import com.service.PersonServiceImplService cannot be resolved”.
    Looking back through the code above I do not see anywhere this class is defined.

    1. Pankaj says:

      You missed the part where classes are being generated using wsimport utility. You need to copy these to the different project to call the SOAP web service.

  14. masoud says:

    i have this problem :
    Exception in thread “main” javax.xml.ws.WebServiceException: Failed to access the WSDL at: http://localhost:8888/ws/person?wsdl. It failed with:
    Connection refused: connect.

    pleas help me

    1. Pankaj says:

      Check the tomcat port, then the web service context and the WSDL URL.

  15. harish says:

    thanks a lot, that makes lot of sense. I usually prefer journaldev site for any java technical. Keep up the good work

    1. rama says:

      What changes I have to make in web.xml?

  16. Venkat says:

    Thanks. But I want to integrate the web service with spring mvc 3.0 and deploy in websphere v8.0. Please help

  17. Vishnu says:

    Thanks a lot pankaj for such a nice example .

  18. Gnanasekhar says:

    Thank you a lot…

  19. nandkishore says:

    Thanks Pankaj for nice explainations.

  20. Ullu says:

    wsdl to the endpoint url as shown in below image. BUT IMAGE IS NOT VISIBLE JUST SHOWS BLANK SCREEN

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages