jws

JAX-WS Dependencies Example

In this post, we present a JAX-WS web services example using Maven dependency configuration.

1. Introduction

Java API for XML Web Services (JAX-WS) uses XML files for configuring services and for exchanging data. JAX-WS is generally used for SOAP-based messaging. It relies on Java API for XML Binding (JAXB) to marshal and unmarshal Java objects to XML documents and the reverse.

You have choices when developing and deploying JAX-WS web services.  You can take a minimalist approach and simply use the JAX-WS runtime libraries that are part of the reference implementation provided by the JAVA EE platform.  For robust applications, you probably want to use a web services stack such as Metro or Apache CXF.

In this example, we will show the unique Maven
dependencies required for developing and deploying JAX-WS web services with the
JAX-WS runtime libraries from the reference implementation, the Metro web
services stack, and the Apache CXF web services stack, respectively.

1.1 Tools Used in this Example

  • Eclipse Oxygen
  • Maven 3.2.1
  • Tomcat 9.0
  • SoapUI 5.3.0

To set up a Tomcat server for use in Eclipse, see Tomcat in Eclipse: 6 popular how to questions.

2. JAX-WS Dependencies Example

In this example, we’ll develop a “Get Quote” web service that returns random quotes.  Let’s begin by creating a simple Maven project.

2.1 Create the Maven Project

  1. Select New -> Other… Maven Project. Click Next.
  2. Select  the “Create a simple project (skip archetype selection)” checkbox and click Next.
JAX-WS Dependencies - Creating a new Maven Project
Creating a new Maven Project

Enter a Group Id and Artifact Id, select “war” for Packaging and click Finish.

JAX-WS Dependencies - Group and Artifact ID
Group and Artifact ID

At this point, you will see the following problem: “web.xml is missing and<failOnMissingWebXml> is set to true”, since we elected to package the application as a war file.  To fix this, right-click on the project and select Java EE Tools -> Generate Deployment Descriptor Stub.

Open the pom.xml and add the following Maven plugins just above the closing </project> tag:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.examples</groupId>
	<artifactId>JAXWS-Dependencies</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>JAXWS-Dependencies</name>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.6.1</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>3.0.0</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
						<warName>JaxWsDepencencies</warName>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

The Maven compiler plugin will compile the source code and the Maven war plugin will package the application in a deployable WAR file.

Save the changes and select Maven->Update Project… from the project context menu.

2.2 Create the Web Service

First we’ll create a Java interface for our web service.

RandomQuoteService.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 RandomQuoteService {
	
	@WebMethod
	public String getQuote();
}

Next, create the implementation for the interface.

RandomQuoteServiceImpl.java

package com.javacodegeeks.examples.jaxws;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.jws.WebService;

@WebService(endpointInterface = "com.javacodegeeks.examples.jaxws.RandomQuoteService")
public class RandomQuoteServiceImpl implements RandomQuoteService {
	
	private static List<String> quoteList;
	
	@PostConstruct
	private void createList() {
		quoteList = new ArrayList<String>();
		quoteList.add("You cannot escape the responsibility of tomorrow by evading it today");
		quoteList.add("I think therefore I am");
		quoteList.add("It was the best of times, it was the worst of times...");
		quoteList.add("Don't cry because it's over, smile because it happened");
		quoteList.add("Be yourself; everyone else is already taken");
		quoteList.add("So many books, so little time");
	}

	@Override
	public String getQuote() {
		Random random = new Random();
		int index = random.nextInt(quoteList.size());
		return (String) quoteList.get(index);
	}
}

2.3 Update the Deployment Descriptor

Open the web.xml file and add the following elements:

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
	<display-name>JAXWS-Dependencies</display-name>

	<listener>
		<listener-class>
			com.sun.xml.ws.transport.http.servlet.WSServletContextListener
		</listener-class>
	</listener>

	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
</web-app>

When the servlet container starts the web application, WSServletContextListener will set up HTTP adapters for the endpoints specified in the sun-jaxws.xml file

2.4 Create the sun-jaxws.xml Configuration File

Create the sun-jaxws.xml file in the WEB-INF directory with the following content:

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="RandomQuoteServiceImpl"
		implementation="com.javacodegeeks.examples.ws.RandomQuoteServiceImpl"
		url-pattern="/getQuote" />
</endpoints>

This file is used to configure the endpoint, its implementation class, and URL pattern to use for its invocation..

If you try to run the web service on the Tomcat server at this point you will see the following exception: 

java.lang.ClassNotFoundException: com.sun.xml.ws.transport.http.servlet.WSServletContextListener

That is because we need to add the proper Maven dependencies in order to invoke the web service.  Let’s add the JAX-WS runtime dependency.

2.5 Use the JAX-WS RT Maven Dependencies

Open pom.xml and add the following dependency:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.examples</groupId>
	<artifactId>JAXWS-Dependencies</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>JAXWS-Dependencies</name>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.6.1</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>3.0.0</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
						<warName>JAXWS-rt</warName>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
	<dependencies>
        <!-- jax-ws maven dependency -->
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.2.8</version>
        </dependency>
	</dependencies>
</project>	

Save the changes and select Maven->Update Project… from the project context menu.

While in the Maven POM editor, select the “Dependency Hierarchy” tab.  

JAX-WS Dependencies - Dependency Hierarchy
Dependency Hierarchy

You can view the transitive dependencies for jaxws-rt:2.2.8 (in the left side pane under Dependency Hierarchy) by double-clicking on its icon.

jaxws-rt/pom.xml

    <parent>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>bundles</artifactId>
        <version>2.2.8</version>
    </parent>

    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.2.8</version>
    <packaging>pom</packaging>
    <name>JAX-WS RI Runtime Bundle</name>

    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.xml.ws</groupId>
            <artifactId>jaxws-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.xml.soap</groupId>
            <artifactId>javax.xml.soap-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.jws</groupId>
            <artifactId>jsr181-api</artifactId>
        </dependency>
        <!-- Provided dependencies -->
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>policy</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.gmbal</groupId>
            <artifactId>gmbal-api-only</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jvnet.staxex</groupId>
            <artifactId>stax-ex</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.stream.buffer</groupId>
            <artifactId>streambuffer</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jvnet.mimepull</groupId>
            <artifactId>mimepull</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.fastinfoset</groupId>
            <artifactId>FastInfoset</artifactId>
        </dependency>
        <dependency>
            <groupId>org.glassfish.ha</groupId>
            <artifactId>ha-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.messaging.saaj</groupId>
            <artifactId>saaj-impl</artifactId>
        </dependency>

        <dependency>
            <artifactId>woodstox-core-asl</artifactId>
            <groupId>org.codehaus.woodstox</groupId>
        </dependency>
        <dependency>
            <groupId>org.codehaus.woodstox</groupId>
            <artifactId>stax2-api</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.org.apache.xml.internal</groupId>
            <artifactId>resolver</artifactId>
        </dependency>
        
        <!-- Test dependencies -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

Of these dependencies, the bare minimum you need for JAX-WS web services development and deployment are:

  • gmbal-api-only.jar
  • jaxb-impl.jar
  • jaxws-api.jar
  • jaxws-rt.jar
  • policy.jar
  • stax-ex.jar
  • streambuffer.jar

Right-click the project and select Run As -> Run on Server. Select the Tomcat server and click “Finish”. When the application starts, you will see a 404 error in the browser, since we do not have a welcome page specified in web.xml. Enter /getQuote at the end of the URL and hit Enter. You will see a link to the WSDL file on the “Available SOAP services” page.  Copy the link for WSDL file.

JAX-WS Dependencies - The Get Quote Web Service
The Get Quote Web Service

Now start SoapUI and create a new SOAP project by clicking the SOAP button on the top bar.  Enter a name for your project and paste the WSDL URL link you copied in the Initial WSDL text box, for example, http://localhost:8080/JaxWsDepencencies/getQuote?wsdl. Make sure “Create Requests” is selected and click OK.

JAX-WS Dependencies - New SOAP Project
New SOAP Project

Expand RandomQuoteServiceImplPortBinding and getQuote in the Navigator and double-click Request 1. Click the green submit arrow on the upper-left corner of the Request window. You should see a successful response.

JAX-WS Dependencies - Successful Response
Successful Response

2.6 Use the Metro Maven Dependencies

Open pom.xml and replace the existing dependency with the following dependencies and save the changes:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.examples</groupId>
	<artifactId>JAXWS-Dependencies</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>JAXWS-Dependencies</name>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.6.1</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>3.0.0</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
						<warName>JAXWS-Metro</warName>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
	<dependencies>
		<!-- jax-ws metro maven dependencies -->
		<dependency>
			<groupId>org.glassfish.metro</groupId>
			<artifactId>webservices-rt</artifactId>
			<version>2.4.2</version>
		</dependency>
		<dependency>
			<groupId>org.glassfish.metro</groupId>
			<artifactId>webservices-api</artifactId>
			<version>2.4.2</version>
			<scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core -->
		<dependency>
			<groupId>com.sun.xml.bind</groupId>
			<artifactId>jaxb-core</artifactId>
			<version>2.3.0</version>
		</dependency>
	</dependencies>	
</project>

While in the Maven POM editor, select the “Dependency Hierarchy” tab. 

JAX-WS Dependencies - Metro Dependency Hierarchy
Metro Dependency Hierarchy

The right pane of the editor shows the resolved dependencies of the project.  So why are they different from the JAX-WS runtime resolved dependencies?  In actuality, many of the same packages are in the Metro jar files, as can be seen in the project navigator.  Also, the Metro stack includes additional features that are not in the reference implementation.  (Note that we also added the jaxb-core dependency as these libraries are not part of the Metro dependencies.)

JAX-WS Dependencies - Project Explorer
Project Explorer

You can restart the server and test using SoapUI.

2.7 Use the Apache CXF Maven Dependencies

Open pom.xml and replace the existing dependencies with the following dependencies and save the changes:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.examples</groupId>
	<artifactId>JAXWS-Dependencies</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>JAXWS-Dependencies</name>
	<build>
		<pluginManagement>
			<plugins>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-compiler-plugin</artifactId>
					<version>3.6.1</version>
					<configuration>
						<source>1.8</source>
						<target>1.8</target>
					</configuration>
				</plugin>
				<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>3.0.0</version>
					<configuration>
						<warSourceDirectory>src/main/webapp</warSourceDirectory>
						<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
						<warName>JaxWsDepencencies</warName>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
	<dependencies>
		<!-- jax-ws CXF maven dependencies -->
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>3.2.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>3.2.7</version>
		</dependency>
		<!--  Spring framework dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>5.0.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.0.7.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>5.0.7.RELEASE</version>
		</dependency>
	</dependencies>
</project>

While it is possible to use CXF without Spring (by extending CXFNonSpringServlet) we are showing the more typical configuration that includes the Spring dependencies.

While in the Maven POM editor, select the “Dependency Hierarchy” tab.   Again, many of the required packages are in the CXF jar files.

Open the web.xml file.  Remove the <listener> element and add the following elements :

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
	<display-name>JAXWS-Dependencies</display-name>
	<servlet>
		<servlet-name>cxfservlet</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>cxfservlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>

	<session-config>
		<session-timeout>30</session-timeout>
	</session-config>
</web-app>

We map CXFServlet to handle all requests coming through “/*”.

Next, create a cxf-servlet.xml file in the WEB-INF directory with the following content.

cxf-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:cxf="http://cxf.apache.org/core"
	xmlns:soap="http://cxf.apache.org/bindings/soap"
	xsi:schemaLocation="http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<jaxws:server id="quoteService" serviceClass="com.javacodegeeks.examples.jaxws.RandomQuoteService" address="/getQuote">
		<jaxws:serviceBean>
			<bean class="com.javacodegeeks.examples.jaxws.RandomQuoteServiceImpl" />
		</jaxws:serviceBean>
	</jaxws:server>

</beans>

Apache CXF with Spring configuration uses the cxf-servlet.xml file to configure the endpoint, implementation, and URL of the web service.

You can restart the server and test using SoapUI.

3. Summary

In this example, we demonstrated how to add the required Maven dependencies to a JAX-WS web service project.

4. Download the Source Code

This was a JAX-WS Dependencies Example.

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

Gilbert Lopez

Gilbert Lopez is an application developer and systems integration developer with experience building business solutions for large and medium-sized companies. He has worked on many Java EE projects. His roles have included lead developer, systems analyst, business analyst and consultant. Gilbert graduated from California State University in Los Angeles with a Bachelor of Science degree in Business.
Subscribe
Notify of
guest

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

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
azzemouf
azzemouf
3 years ago

Thank you for article
but this dependency don’t include the needed jars

com.sun.xml.ws
jaxws-rt
2.2.8

goranf
goranf
2 years ago
Reply to  Gilbert Lopez

For me it also doesn’t work. If I use jaxws-rt version 2.3.2 at least @WebService and @WebMethod annotation work, but it still doesn’t recognize @SOAPBinding annotation.

Swathi
Swathi
2 years ago
  • Hi. I had implemented web service in java using jaxws-api.jar and jaxws-rt.jar files. But after I upgraded the jar files to jaxws-api-2.3.0.jar, I am getting char 0x0 out of allowed range error while trying to open wsdl. Please help me out here.
Back to top button