Like removing APIs from the Java platform (JEP 320) after decades of backwards compatibility wasn't bad enough, we also have to decide whether to migrate to JakartaEE or stay with JavaEE.
JavaEE was submitted to the Eclipse Foundation under the new name JakartaEE and the JAX-WS and JAXB APIs were migrated from the javax.xml.*
namespace to jakarta.xml.*
. The XML namespaces used in JAX-WS and JAXB binding files have similar breaking changes.
There are a couple of reasons you might want to target the JavaEE edition of the JAX-WS API in the short term. One reason is that many of JAXB extension plugins are not ready to target the JakartaEE APIs yet. Another reason is that if you are still using a JavaEE servlet container such as Tomcat 9 and frameworks that build on JavaEE such as Spring 5 then it's safer to wait and do a full switch to JakartaEE when everything is ready, rather than trying to use a hybrid stack of JavaEE and JakartaEE.
If you do stay with the JavaEE JAX-WS APIs for now, then make sure to use the Eclipse Metro major version 2 and not some later major version.
Example projects that generate JAX-WS clients contract first from a WSDL file with Java 11 are available on Github for both JavaEE and JakartaEE, but the instructions that follow pertain to the JakartaEE example.
Target JAX-WS API | Eclipse Metro major version | Github project | ||
---|---|---|---|---|
JavaEE | 2 | https://github.com/SorenPoulsen/javaee-jaxws-client-with-java11 | ||
JakartaEE | 3+ | https://github.com/SorenPoulsen/jaxws-client-with-java-11 |
The test service is of the Document Literal Wrapped type bound to a SOAP-over-HTTP implementation.
It has a SendMessage operation that sends a string and returns another string.
The test.wsdl file is as follows:
<?xml version="1.0"?>
<definitions name="TestService"
targetNamespace="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://tempuri.org/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://tempuri.org/">
<xsd:element name="SendMessage">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Message" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="SendMessageResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="MessageResponse" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
<message name="TestRequestMessage">
<part name="TestRequestPart" element="tns:SendMessage" />
</message>
<message name="TestResponseMessage">
<part name="TestResponsePart" element="tns:SendMessageResponse" />
</message>
<portType name="TestPortType">
<operation name="SendMessage">
<input name="TestInput" message="tns:TestRequestMessage" />
<output name="TestOutput" message="tns:TestResponseMessage" />
</operation>
</portType>
<binding name="TestBinding" type="tns:TestPortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
<operation name="SendMessage">
<input name="TestInput">
<soap12:body use="literal" />
</input>
<output name="TestOutput">
<soap12:body use="literal" />
</output>
</operation>
</binding>
<service name="TestService">
<port name="TestPort" binding="tns:TestBinding">
<soap12:address location="http://tempuri.org/testservice" />
</port>
</service>
</definitions>
You will need a recent Maven 3 and JDK 11 on path.
The client artifacts are generated from a WSDL file using the JAX-WS Maven plugin's wsimport goal.
There is no need to install any of the schema commandline tools as the plugin uses wsimport directly from its own jaxws-tools.jar dependency.
Now that JAX-WS is are no longer part of JavaSE and the JDK, we can add the dependencies from Maven Central instead.
<dependencies>
<dependency>
<groupId>jakarta.xml.ws</groupId>
<artifactId>jakarta.xml.ws-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
The JAX-WS Maven plugin is added to the POM file and configured to execute the wsimport goal.
The test.wsdl file is read from the project's src/main/resources folder during artifacts generation and is read from the root of the classpath /test.wsdl at runtime.
The "extension" property tells the plugin to support soap v1.2 bindings.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.9.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<goals>
<goal>wsimport</goal>
</goals>
</execution>
</executions>
<configuration>
<wsdlLocation>/test.wsdl</wsdlLocation>
<wsdlDirectory>${project.basedir}/src/main/resources/</wsdlDirectory>
<extension>true</extension>
</configuration>
<dependencies>
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-tools</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
And finally we can run maven to generate the JAX-WS client artifacts.
$ mvn install
Using the generated artifacts to invoke the service goes something like this.
TestService testService = new TestService();
TestPortType testPort = testService.getTestPort();
BindingProvider binding = (BindingProvider) testPort;
binding.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8088/mockTestBinding");
String response = testPort.sendMessage("hello");
This post doesn't cover how to use the wsgen goal to generate a service provider, but you could load the test.wsdl file in a SoapUI project and let it run a mock service for a quick test of the client.