javawebspherejax-wslinkageerror

ServiceConfigurationError caused by LinkageError in WebSphere


I have an application that is deployed on WebSphere 9.0.5.2 where I want to use CXF for webservice calls and I'm getting this This ServiceConfigurationError

WrapperedException { java.util.ServiceConfigurationError: javax.xml.ws.spi.Provider: Provider org.apache.cxf.jaxws.spi.ProviderImpl could not be instantiated 

Further down the stacktrace, I see that this is caused by a LinkageError

Caused by: java.lang.LinkageError: loading constraint violation when overriding method
  "javax/xml/ws/spi/ServiceDelegate.createDispatch(Ljavax/xml/namespace/QName;Ljavax/xml/bind/JAXBContext;Ljavax/xml/ws/Service$Mode;)Ljavax/xml/ws/Dispatch;" during creation of class
  "org/apache/cxf/jaxws/ServiceImpl": loader
  "com/ibm/ws/classloader/CompoundClassLoader@832133d2" of class
  "org/apache/cxf/jaxws/ServiceImpl" and loader
  "com/ibm/oti/vm/BootstrapClassLoader@2eec706a" of class
  "javax/xml/ws/spi/ServiceDelegate" have different types for the method signature 

I understand that this could be caused by multiple libraries that have different definitions for QName or JAXBContext, but I think I've ruled those out.

I also understand that WebSphere has it's own JAX-WS with it's own method signature for ServiceDelegate.createDispatch and I've tried setting DisableIBMJAXWSEngine to true in WebSphere as instructed here

Using a third-party JAX-WS web services engine

I still haven't been able to get rid of the error and am pretty much at a loss as to what to try next. Any suggestions is appreciated!!!


Solution

  • The issue here is a cross-linkage between the application and server's copies of the JAXB API, JAX-WS API, and JAX-WS implementation. The application (configured with parent-last class loading delegation, so it searches locally before delegating to parents) contains a JAX-WS implementation and JAXB API/impl, but it does not contain the JAX-WS API. Since JAX-WS references JAXB, we get the following linkage pattern:

    1) Some application class references the JAX-WS API. Because it's not packaged in the application, it's loaded from the server libraries.

    2) When the API class is linked, it uses its local class loader to find the JAXB API. That, in turn, links it to the server's version as well.

    3) JAX-WS uses the thread context class loader to load its implementation. It finds it in the parent-last application.

    4) When the implementation class is linked, it uses its local class loader to find the JAXB API, which finds it locally in the application.

    5) The implementation now is linked to two versions of the same class:

    JAXWSImpl -> JAXWSAPI -> JAXB (server) JAXWSImpl -> JAXB (app)

    The JVM can't tolerate that, and a LinkageError is thrown.

    The solution can be approached one of two ways:

    1) Add the JAX-WS API to the application - this prevents the initial delegation in #1 above

    2) Remove the JAXB API (and implementation, if provided) from the application - this causes the linkage in #4 to delegate down to the server for JAXB, so it's always loaded from the same place.

    Either way, the trick is to ensure that all the necessary classes are available to the application through the same class loader.