Metro on WebSphere 7 – com.ibm.xml.xlxp2.jaxb.JAXBContextImpl incompatible exception
Problem
Developed a SOAP web service via Metro 2.0.1 (webservices-rt.jar
), integrate with Spring via jaxws-spring-1.8.jar
and deployed on WebSphere Application Server (WAS) version 7.0.0.13 . See web service below :
File : UserWS.java
package com.mkyong.user.ws;
//import...
@WebService()
public class UserWS {
private UserBo userBo;
@WebMethod(exclude = true)
public UserBo getUserBo() {
return userBo;
}
@WebMethod(exclude = true)
public void setUserBo(UserBo userBo) {
this.userBo = userBo;
}
@WebMethod(operationName = "listUser")
public List<User> listUser() throws SOAPException {
return userBo.listUser();
}
}
If everything is fine, the service is work as expected, but, when “userBo.listUser()
” hit error and throwing a SOAPException
back to the web service’s client :
Client get this :
Exception in thread "main"
javax.xml.ws.WebServiceException: No Content-type in the header!
WAS log file showing this :
Caused by: java.lang.ClassCastException: com.ibm.xml.xlxp2.jaxb.JAXBContextImpl
incompatible with com.sun.xml.bind.api.JAXBRIContext
at com.sun.xml.ws.fault.SOAPFaultBuilder.<clinit>(SOAPFaultBuilder.java:561)
at java.lang.J9VMInternals.initializeImpl(Native Method)
at java.lang.J9VMInternals.initialize(J9VMInternals.java:200)
... 34 more
P.S This web service is working on Tomcat, but failed on WebSphere only
Solution
The com.ibm.xml.xlxp2.jaxb.JAXBContextImpl
is located at WAS_APPSERVER_PROFILE\plugins\com.ibm.ws.prereq.xlxp.jar, and Metro library, webservices-rt.jar, also contain one of the instance com.sun.xml.bind.v2.runtime.JAXBContextImpl
. When exception raised, WAS is using two different instance to perform a same JAXB binding task, and raise an “java.lang.ClassCastException” incompatible exception.
To fix it, just make sure WAS is using same instance always.
- In WAS configuration screen, set module class loader to “parent-first“.
- In WAS folder, create a “classes” folder under WAS root folder and put
webservices-rt.jar
inside, for example,WAS_APPSERVER_PROFILE\classes\webservices-rt.jar
.
Restart WAS instance, now WAS will load your webservices-rt.jar
always. A dirty way, but it work :).
You can find a complete Guide for Metro, CXF and Axis on IBM Websphere (WAS) in the next link (Offical guides), some libs can generate conflicts with the WAS .jar libs.
http://public.dhe.ibm.com/software/dw/wes/1001_thaker/1001_thaker.pdf
http://www.ibm.com/developerworks/websphere/library/techarticles/1001_thaker/1001_thaker.html
i have found a nother way to get the same result without changing anything in the
WAS.
aparently if ou place a
jaxb.properties in the /src/main/resources path with the folowing string.
javax.xml.bind.context.factory=com.sun.xml.bind.v2.ContextFactory
websphere loads and uses only this contextFactory and the exception is never thrown 🙂
Can you specify where exactly did you put jaxb.properties file?
Does it have to be in the same package as the service implementation?
I tried adding it but it doesn’t work for me.
Thanks in advance,
Marko
jaxb.properties
with single line: javax.xml.bind.context.factory=com.sun.xml.bind.v2.ContextFactory
must be in package: com.sun.xml.ws.fault
somewhere with your classes
For other solutions you can check sources of: javax.xml.bind.ContextFinder.find
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/javax/xml/bind/ContextFinder.java#ContextFinder.find%28java.lang.String%2Cjava.lang.String%2Cjava.lang.ClassLoader%2Cjava.util.Map%29