WebSphere中LinkageError导致的ServiceConfigurationError

ServiceConfigurationError caused by LinkageError in WebSphere

我有一个部署在 WebSphere 9.0.5.2 上的应用程序,我想在其中使用 CXF 进行 Web 服务调用,但我收到了这个 ServiceConfigurationError

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

进一步查看堆栈跟踪,我发现这是由 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 

我知道这可能是由多个库对 QNameJAXBContext 具有不同定义引起的,但我认为我已经排除了这些可能性。

我也知道 WebSphere 有它自己的 JAX-WS 和它自己的 ServiceDelegate.createDispatch 方法签名,我已经尝试按照此处的说明在 WebSphere 中将 DisableIBMJAXWSEngine 设置为 true

Using a third-party JAX-WS web services engine

我仍然无法摆脱这个错误,对于接下来要尝试什么几乎一头雾水。任何建议表示赞赏!!!

这里的问题是 JAXB API、JAX-WS API 和 JAX-WS 实现的应用程序和服务器副本之间的交叉链接。该应用程序(配置了父级最后 class 加载委派,因此它在委派给父级之前在本地搜索)包含 JAX-WS 实现和 JAXB API/impl,但它不包含 JAX-WS API。由于 JAX-WS 引用 JAXB,我们得到以下链接模式:

1) 某些应用程序 class 引用了 JAX-WS API。因为它没有打包在应用程序中,所以它是从服务器库中加载的。

2) 当链接 API class 时,它使用其本地 class 加载程序来查找 JAXB API。反过来,它也将它链接到服务器的版本。

3) JAX-WS 使用线程上下文 class 加载器来加载其实现。它在父级最后一个应用程序中找到它。

4) 当链接实现 class 时,它使用其本地 class 加载器查找 JAXB API,后者在应用程序本地找到它。

5) 现在的实现链接到相同的两个版本 class:

JAXWSImpl -> JAXWSAPI -> JAXB(服务器) JAXWSImpl -> JAXB(应用程序)

JVM 无法容忍,并抛出 LinkageError。

解决方案可以通过以下两种方式之一来解决:

1) 将 JAX-WS API 添加到应用程序 - 这会阻止上面 #1 中的初始委托

2) 从应用程序中删除 JAXB API(和实现,如果提供的话)——这会导致 #4 中的链接向下委托给 JAXB 服务器,所以它总是从同一个地方加载.

无论哪种方式,诀窍是确保所有必需的 classes 通过相同的 class 加载程序可供应用程序使用。