博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
osgi应用使用桥接的方式打成war包部署在websphere上时遇到的与cxf相关的问题
阅读量:5297 次
发布时间:2019-06-14

本文共 4031 字,大约阅读时间需要 13 分钟。

原来我们的程序都是基于Equinox架构的,可是后面由于要实现打成war包在中间件中部署的需求,使用了eclipse官方提供的桥接方式实现。

桥接的部分后面有时间了我专门写一个文章来说,不明确的临时请參考eclipse官方文档。这里主要说一下已经桥接成功。可是在使用CXF时遇到问题的情况。

本来在其它中间件里跑得好好的程序,一放到websphere_v8里,就各种报错。都是与axis2有关的,可是我们的项目并没有使用axis2。而是使用cxf。

报错类似例如以下(我有3个环境。每一个报的错都不同,只是都非常明显的出现了不该出现的axis2):

java.lang.ClassCastException: org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler incompatible with org.apache.cxf.frontend.ClientProxy	at org.apache.cxf.frontend.ClientProxy.getClient(ClientProxy.java:93)

后来查了资料发现websphere有自带的jaxws引擎。能够看到在$WAS_HOME/endorsed_apis下有三个jar包:

javax.j2ee.annotation.jarjaxb-api.jarjaxws-api.jar//version:2.2
然后在$WAS_HOME/plugins下有org.apache.axis2.jar.

比方说,你实现了MyService继承了javax.xml.Service。

那么在Service的构造方法里我们能够看到:

protected Service(java.net.URL wsdlDocumentLocation, QName serviceName) {        delegate = Provider.provider().createServiceDelegate(wsdlDocumentLocation,                serviceName,                this.getClass());    }
就是这个Provider.provider()得到的Provider实现始终是axis的实现,而不是我们的cxf的实现。

一、通用方案

查询了cxf和IBM的官方文档。得到的解决方式例如以下:

參考

1.关闭websphere自带的jaxws引擎。这里有两种级别的设置:

server级:

在控制台界面进入应用程序服务器 > server1 > 进程定义 > Java 虚拟机。然后在通用JVM參数中增加

-Dcom.ibm.websphere.webservices.DisableIBMJAXWSEngine=true 

或者再进入定制属性。加入一个定制属性name=com.ibm.websphere.webservices.DisableIBMJAXWSEngine, value=true.

针对某个app:

在你的war包的META-INF/MANIFEST.MF中增加DisableIBMJAXWSEngine:true,像这样

Manifest-Version: 1.0DisableIBMJAXWSEngine: trueClass-Path:

2.设置你的应用的ClassLoader策略为Parent_Last

企业应用程序 > $YOUR_APP > 类装入和更新检測

把类装入器顺序设置为Parent_Last

设置Application的classloader策略

企业应用程序 > $YOUR_APP > 模块管理 > $YOUR_MODULE ,将类装入器顺序设置为Parent_Last

最后另一个地方的类载入策略(能够验证一下这个是否须要设置。有些文章上没有说这个地方):

应用程序服务器 > server1。把类装入方式设置为Parent_Last

以上就是IBM和CXF官方提供的解决方式。

然后在网上还发现了一些其它方案:

1. 移除org.apache.axis2.jarH或移除org.apache.axis2.jar中的'META-INF/services/javax.xml.ws.spi.Provider' 

这比較暴力,并且会造成对整个WAS的影响。

2. 改用

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setAddress(wsdlURL);factory.setServiceClass(MyWebService.class);MyWebService port = (MyWebService) factory.create();//and then call ClientProxy as usual but with the object created using JaxWsProxyFactoryBeanClient client = ClientProxy.getClient(port);
替代原来的

MyWebService ss = new   MyWebService (wsdlURL, SERVICE_NAME);instance = ss.getTestHttpPort();Client cxfClient = ClientProxy.getClient(instance);

第2条我试的时候,报了MyWebService不是一个interface的错误.没有详细去跟是什么原因。

在网上的全部能找到的方式都尝试无果之后,不得不自己分析了。

二、桥接的方式特殊的地方

JAX-WS採用了service provider interface (SPI)的机制,定义了上层的API。执行的时候再由Provider类载入不同的实现。

首先看一下JAX-WS的载入顺序:

 
 
JAX-WS 的载入顺序
javax.xml.ws.spi.Provider provider()
  • If a resource with the name of META-INF/services/javax.xml.ws.spi.Provider
    = com.sun.xml.ws.spi.ProviderImpl
  • $java.home/lib/jaxws.properties,it contains an entry whose key is javax.xml.ws.spi.Provider
  • If a system property with the name javax.xml.ws.spi.Provider
  • Default is loaded(com.sun.xml.internal.ws.spi.ProviderImpl)
javax.xml.bind.ContextFinder.find
  • jaxb.properties (key=javax.xml.bind.JAXBContext)
  • System property with name javax.xml.bind.JAXBContext
  • META-INF/services/javax.xml.bind.JAXBContext 
  • Default is loaded(com.sun.xml.internal.bind.v2.ContextFactory)
 
|_META-INF
|_services
|_ javax.xml.bind.JAXBContext (com.sun.xml.bind.v2.ContextFactory)

jaxws-api肯定是用的websphere的了,在我们已经依照官方文档关闭了IBMJAXWSEngine和改动ClassLoader策略之后,他还是老是载入到websphere自带的axis2。,所以推測Provider.provider()在寻找Provider的实现时。根本没有发现我们应用中的cxf包,这跟OSGI桥接的方式相关,使用这样的方式的同学应该了解是什么文件夹结构。

所以,解决方案是在war/WEB-INF/lib中也放入一个cxf.jar. 然后再也没有出现axis2来困扰我们了。

这里就会产生一个问题,lib包中有一个cxf,eclipse的plugin文件夹下也有一个cxf。

那么使用的时候会出现类冲突吗?

假设直接把eclipse的plugin文件夹下的cxf移除掉,启动的时候肯定各种bundle依赖报错。那么外面一个cxf,里面一个cxf究竟会不会产生冲突呢?

答案是不会。 

由于我把lib下的cxf包中的内容都删了。仅仅剩下META-INF/services/中的几个文件。竟然也能够正常执行。所以能够看出执行中载入到的类应该还都是eclipse的plugins中的cxf中的类.  推測载入cxf中的类是从equinox中的bundle的classLoader開始载入的,所以就会载入到eclipse中的plugins中的类。假设是用的Module或之上的ClassLoader来载入,那么在lib下仅仅有cxf空包,而没有详细的类的时候。肯定会载入不到这个类。那么既然在这样的情况下还能载入到,就说明是从bundle的Classloader開始载入的。

只是为了保险起见。这一个步的终于方案为:

cxf中的META-INF/services文件夹拷贝出来打成一个jar包,放在war/WEB-INF/lib文件夹下.

转载于:https://www.cnblogs.com/claireyuancy/p/7258593.html

你可能感兴趣的文章
配置流分类
查看>>
5.Windows应急响应:挖矿病毒
查看>>
检测光纤的同心性
查看>>
C#中的虚函数及继承关系
查看>>
[Leetcode 70] 82 Remove Duplicates from Sorted List II
查看>>
hdu1698 Just a Hook 【区间修改】(模板题)
查看>>
Android音频不能播放问题
查看>>
unfinished application
查看>>
设计模式 - Java中单例模式的6种写法及优缺点对比
查看>>
axios的配置项
查看>>
Excel中针对IP地址的排序方法
查看>>
MySQL常用函数
查看>>
如何创建C# Closure ?
查看>>
android 优秀图表库之MPAndroidChart
查看>>
MyBatis
查看>>
vscode mac下终端code .快速打开工程文件
查看>>
登陆界面的记住密码
查看>>
Hadoop的体系结构之HDFS的体系结构
查看>>
java基础(一):我对java的三个环境变量的简单理解和配置
查看>>
arcgis api 4.x for js 结合 Echarts4 实现散点图效果(附源码下载)
查看>>