In short:
I am trying to create a SOAP client, using auto generated code from WSDL files. The generation of the files was using CXF 3.5.3 Wsdl2Java.
The command for generating the data models from the WSDL was:
./wsdl2java -d ~/PROJECT/src/main/java -autoNameResolution PATH_TO_WSDL_FILE.wsdl
When trying to run the code I am seeing the following exception:
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:278)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:421)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721)
at org.apache.cxf.common.jaxb.JAXBContextCache$2.run(JAXBContextCache.java:345)
at org.apache.cxf.common.jaxb.JAXBContextCache$2.run(JAXBContextCache.java:343)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.common.jaxb.JAXBContextCache.createContext(JAXBContextCache.java:343)
at org.apache.cxf.common.jaxb.JAXBContextCache.getCachedContextAndSchemas(JAXBContextCache.java:245)
at org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContextAndSchemas(JAXBDataBinding.java:499)
at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:358)
... 8 more
In the call for: PortClass port = (PortClass) factoryBean.create();
Full code sample:
ClientProxyFactoryBean factoryBean = new ClientProxyFactoryBean();
factoryBean.setServiceClass(PortClass.class);
factoryBean.setAddress(ADDRESS);
PortClass port = (PortClass) factoryBean.create();
Any ideas how to properly set the dependencies?
Full Workflow:
At first I used the OOB generated files, with the following Gradle dependencies:
dependencies {
implementation 'org.apache.cxf:cxf-rt-transports-http:3.5.3'
implementation 'org.apache.cxf:cxf-rt-frontend-jaxws:3.5.3'
implementation 'org.apache.cxf:cxf-rt-ws-security:3.5.3'
implementation 'javax.xml.soap:javax.xml.soap-api:1.4.0'
implementation 'javax.annotation:javax.annotation-api:1.3.2'
implementation 'javax.xml.bind:jaxb-api:2.4.0-b180830.0359'
implementation 'com.sun.xml.ws:jaxws-rt:4.0.0'
implementation 'com.sun.xml.ws:jaxws-ri:4.0.0'
implementation 'com.sun.xml.bind:jaxb-ri:4.0.0'
implementation 'com.sun.xml.ws:rt:4.0.0'
implementation 'javax.xml.ws:jaxws-api:2.3.1'
implementation 'javax.jws:javax.jws-api:1.1'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'javax.xml.ws:jaxws-api:2.3.1'
implementation 'com.sun.xml.bind:jaxb-impl:4.0.0'
implementation 'com.sun.xml.bind:jaxb-core:4.0.0'
}
and encountered the exception: Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
Understanding that in Java 11 you have to migrate to Jakarta instead of Javax, I have replaced Gradle dependencies into:
dependencies {
implementation 'org.apache.cxf:cxf-rt-transports-http:3.5.3'
implementation 'jakarta.xml.soap:jakarta.xml.soap-api:3.0.0'
implementation 'org.apache.cxf:cxf-rt-frontend-jaxws:3.5.3'
implementation 'com.sun.xml.bind:jaxb-impl:4.0.0'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
implementation 'jakarta.jws:jakarta.jws-api:3.0.0'
implementation 'jakarta.xml.ws:jakarta.xml.ws-api:4.0.0'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
implementation 'com.sun.activation:javax.activation:1.2.0'
implementation 'jakarta.annotation:jakarta.annotation-api:2.1.1'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
implementation 'org.apache.cxf:cxf-rt-ws-security:3.5.3'
implementation 'org.glassfish.metro:webservices-rt:4.0.1'
implementation 'org.glassfish.metro:webservices-api:4.0.1'
implementation 'com.sun.xml.messaging.saaj:saaj-impl:3.0.0'
implementation 'com.sun.xml.ws:jaxws-rt:4.0.0'
implementation 'com.sun.xml.ws:jaxws-ri:4.0.0'
implementation 'com.sun.xml.bind:jaxb-ri:4.0.0'
implementation 'com.sun.xml.ws:rt:4.0.0'
implementation 'com.sun.xml.bind:jaxb-core:4.0.0'
}
Next, the generated code didn't compile because Jaxb was not recognized in the auto generated files (because it is not part of the dependencies):
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
So I have manually replaced these imports into:
import jakarta.jws.WebMethod;
import jakarta.jws.WebParam;
import jakarta.jws.WebService;
import jakarta.xml.bind.annotation.XmlSeeAlso;
import jakarta.xml.ws.RequestWrapper;
import jakarta.xml.ws.ResponseWrapper;
And indeed everything compiles, but there were still errors because Apache CXF itself is built on javax
. I had to return javax
dependencies into Gradle:
dependencies {
implementation 'jakarta.xml.soap:jakarta.xml.soap-api:3.0.0'
implementation 'org.apache.cxf:cxf-rt-frontend-jaxws:3.5.3'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
implementation 'jakarta.jws:jakarta.jws-api:3.0.0'
implementation 'jakarta.xml.ws:jakarta.xml.ws-api:4.0.0'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.0'
implementation 'org.apache.cxf:cxf-rt-ws-security:3.5.3'
implementation 'org.glassfish.metro:webservices-rt:4.0.1'
implementation 'org.glassfish.metro:webservices-api:4.0.1'
implementation 'com.sun.xml.messaging.saaj:saaj-impl:3.0.0'
implementation 'jakarta.xml.soap:jakarta.xml.soap-api:3.0.0'
implementation 'javax.jws:javax.jws-api:1.1'
implementation 'javax.activation:activation:1.1.1'
implementation 'org.glassfish.jaxb:jaxb-runtime:4.0.0'
implementation 'com.sun.xml.bind:jaxb-core:4.0.0'
implementation 'javax.annotation:javax.annotation-api:1.3.2'
implementation 'javax.xml.ws:jaxws-api:2.3.1'
implementation 'javax.xml.soap:javax.xml.soap-api:1.4.0'
implementation 'javax.annotation:javax.annotation-api:1.3.2'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
implementation 'com.sun.activation:javax.activation:1.2.0'
implementation 'org.apache.cxf:cxf-rt-transports-http:3.5.3'
implementation 'org.glassfish.jaxb:jaxb-runtime:4.0.0'
implementation 'com.sun.xml.bind:jaxb-impl:4.0.0'
implementation 'com.sun.xml.bind:jaxb-ri:4.0.0'
implementation 'com.sun.xml.bind:jaxb-core:4.0.0'
implementation 'com.sun.xml.ws:jaxws-rt:4.0.0'
implementation 'com.sun.xml.ws:jaxws-ri:4.0.0'
implementation 'com.sun.xml.bind:jaxb-ri:4.0.0'
implementation 'com.sun.xml.ws:rt:4.0.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
}
And now I am getting the above exception:
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:278)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:421)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721)
at org.apache.cxf.common.jaxb.JAXBContextCache$2.run(JAXBContextCache.java:345)
at org.apache.cxf.common.jaxb.JAXBContextCache$2.run(JAXBContextCache.java:343)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.common.jaxb.JAXBContextCache.createContext(JAXBContextCache.java:343)
at org.apache.cxf.common.jaxb.JAXBContextCache.getCachedContextAndSchemas(JAXBContextCache.java:245)
at org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContextAndSchemas(JAXBDataBinding.java:499)
at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:358)
... 8 more