JAX-WS Web Service Deployment on Tomcat Server

Filed Under: Java EE

We learned how to use JAX-WS to create SOAP web services and publish it using javax.xml.ws.Endpoint but most of the times we want to deploy our services on a servlet container. So today we will learn how to create a web service and deploy it on Apache Tomcat server and then test it out with the client application.

For this, our first step is to create a Dynamic Web Project to write our business logic. Our final project will look like below image.

JAXWS Tomcat Project

For JAX-WS web service deployment on a servlet container, we need to add some jar files into it. There are two ways to do this.

  1. Download jar files from https://jax-ws.java.net/ and include it in the dynamic web project.
  2. Convert Dynamic web project into Maven and add below dependencies.
    
    <dependency>
    	<groupId>com.sun.xml.ws</groupId>
    	<artifactId>jaxws-rt</artifactId>
    	<version>2.2.10</version>
    </dependency>
    

    This will automatically download all the required jar files as maven dependencies shown in the below image. I like this approach because I can upgrade the versions easily and it will also make sure none of the jars are getting missed.

    JAXWS Dependencies JARs

Now let’s go through the business logic. First, we will create a model bean class.


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 create our service interface and implementation classes.


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();
}

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;
	}

}

Our web service code is ready, next steps are required to create it as a web archive that we can deploy in the servlet container.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>JAXWS-Tomcat</display-name>

	<listener>
		<listener-class>
			com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
	</listener>
	
	<servlet>
		<servlet-name>JAXWSServlet</servlet-name>
		<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>JAXWSServlet</servlet-name>
		<url-pattern>/personWS</url-pattern>
	</servlet-mapping>
	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
	
</web-app>

There is nothing project-specific, these are generic changes to add listener class and front servlet class for web service.

Next step is to create sun-jaxws.xml file inside WEB-INF directory where we will provide endpoint details. URL-pattern should be same as defined in the web.xml file.

sun-jaxws.xml


<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
  <endpoint
     name="PersonServiceImpl"
     implementation="com.journaldev.jaxws.service.PersonServiceImpl"
     url-pattern="/personWS"/>
</endpoints> 

That’s it, we are done. Just export project as a WAR file and deploy it into tomcat container. Access the web service URL as shown in below image.

JAXWS Tomat URL

Access the WSDL URL and take note of targetNamespace and name attributes, we will use them in the client side program.

JAXWS wsdl url

Below is a simple test program to use our web service and run some tests.


package com.journaldev.jaxws.test;

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;
import com.journaldev.jaxws.service.PersonService;

public class SOAPPublisherClient {

	public static void main(String[] args) throws MalformedURLException {
		URL wsdlURL = new URL("http://localhost:8080/JAXWS-Tomcat/personWS?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()));
		
	}

}

As explained in previous tutorial, we can use wsimport utility to generate client stubs and use it. When we run above program, we get output as shown in below image.

JAXWS Client Program

That’s all for now, I hope you liked the tutorial and it will help you in deploying web services in Tomcat container.

You can download the final project code from our GitHub Repository.

Comments

  1. Ashwin KA says:

    http://localhost:8080/LearnWS/personWS
    I’m able to open the above URL and can see the list of API’s

    But http://localhost:8080/LearnWS/personWS?wsdl
    If I try to open this, I’m getting page cannot be displayed and I’m getting an error in the console as below
    SEVERE: caught throwable
    java.io.IOException: Trying to write END_DOCUMENT when the document has no root (ie. trying to output empty document).
    at com.sun.xml.ws.server.SDDocumentImpl.writeTo(SDDocumentImpl.java:299)
    at com.sun.xml.ws.transport.http.HttpAdapter.publishWSDL(HttpAdapter.java:931)
    at com.sun.xml.ws.transport.http.HttpAdapter.handleGet(HttpAdapter.java:440)
    at com.sun.xml.ws.transport.http.servlet.ServletAdapter.invokeAsync(ServletAdapter.java:193)
    at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doGet(WSServletDelegate.java:161)
    at com.sun.xml.ws.transport.http.servlet.WSServlet.doGet(WSServlet.java:89)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)
    Caused by: javax.xml.stream.XMLStreamException: Trying to write END_DOCUMENT when document has no root (ie. trying to output empty document).
    at com.ctc.wstx.sw.BaseStreamWriter.throwOutputError(BaseStreamWriter.java:1518)
    at com.ctc.wstx.sw.BaseStreamWriter.reportNwfStructure(BaseStreamWriter.java:1547)
    at com.ctc.wstx.sw.BaseStreamWriter._finishDocument(BaseStreamWriter.java:1373)
    at com.ctc.wstx.sw.BaseStreamWriter.close(BaseStreamWriter.java:243)
    at com.sun.xml.ws.util.xml.XMLStreamWriterFilter.close(XMLStreamWriterFilter.java:67)
    at com.sun.xml.ws.server.SDDocumentImpl.writeTo(SDDocumentImpl.java:297)
    … 29 more

    1. Suparna Mukherjee says:

      hi,How did you publish the webservice in tomcat? can you please guide

  2. Niveditha says:

    After a lot of other tutorials trials, this one had been perfect in terms of getting the service up and running in tomcat, as it shows precisely the dependencies we need.

  3. abhishek says:

    Please let me know how to deploy the same for JBOSS or Weblogic

  4. Richar says:

    hopefully you had a repository to see project details like the POM.
    Thanks for your examples.

  5. Victor says:

    Hi Pankaj, your tutorials are very helpful, please can you send me the pom.xml . thanks in advance

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