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
- Select New -> Other… Maven Project. Click Next.
- Select the “Create a simple project (skip archetype selection)” checkbox and click Next.
Enter a Group Id and Artifact Id, select “war” for Packaging and click Finish.
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.
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.
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.
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.
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.
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.)
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.
You can download the full source code of this example here: JAX-WS Dependencies Example
Thank you for article
but this dependency don’t include the needed jars
com.sun.xml.ws
jaxws-rt
2.2.8
Hello,
This article shows different options for including the required dependencies to build/deploy a SOAP web service. Please look at section “2.5 -Use the JAX-WS RT Maven Dependencies” where it describes how to add jaxws-rt jar as a Maven dependency, which will pull in com.sun.xml.ws as a transitive dependency.
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.