osgi应用使用桥接的方式打成war包部署在websphere上时遇到的与cxf相关的问题
原来我们的程序都是基于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.jar
jaxb-api.jar
jaxws-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.0
DisableIBMJAXWSEngine: true
Class-Path:
2.设置你的应用的ClassLoader策略为Parent_Last
企业应用程序 > $YOUR_APP > 类装入和更新检測
把类装入器顺序设置为Parent_Last
企业应用程序 > $YOUR_APP > 模块管理 > $YOUR_MODULE ,将类装入器顺序设置为Parent_Last
最后另一个地方的类载入策略(能够验证一下这个是否须要设置。有些文章上没有说这个地方):
应用程序服务器 > server1。把类装入方式设置为Parent_Last
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYTQ3Nzk5Nw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
以上就是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 JaxWsProxyFactoryBean
Client 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
- $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)
- 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文件夹下.
osgi应用使用桥接的方式打成war包部署在websphere上时遇到的与cxf相关的问题的更多相关文章
- SpringBoot之打成war包部署到Tomcat
正常情况下SpringBoot项目是以jar包的形式,正常情况下SpringBoot项目是以jar包的形式,并且SpringBoot是内嵌Tomcat服务器,所以每次重新启动都是用的新的Tomcat服 ...
- springboot 学习之路 5(打成war包部署tomcat)
目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...
- 将web项目打成war包部署在tomcat步骤
将web项目打成war包部署在tomcat步骤 1.将自己的项目打成war包. 2.将打包好的war复制到${tomcat.home}/webapps项目下. 3.在${tomcat.hom}/con ...
- Web项目打成war包部署Tomcat时运行startup.bat直接闪退部署失败解决方案
即上篇通过将web项目打成war包部署到Tomcat服务器,解决mysql问题后,又出现了新问题,真是一波三折,所以将解决过程分享给大家,希望能帮助到小伙伴们~ 将打好的war包拷贝到Tomcat的w ...
- 使用idea创建springboot项目并打成war包发布到weblogic上
部署tomcat也是类似的,但是需要注意项目配置的路径,或者直接将项目放到webapp的ROOT目录下. 使用工具:intelliJ IDEA2016.3, jdk1.8 ,weblogic12 一 ...
- Web项目打成war包部署到tomcat时报MySQL Access denied for user 'root'@'localhost' (using password: YES)错误解决方案
Web项目使用使用root账号root密码进行部署,通过Eclipse加载到Tomcat服务器可以发布成功,打成war包放到tomcat的webapps目录无法发布成功,报错: jdbc.proper ...
- SpringBoot(十八)_springboot打成war包部署
最近在做项目的时候,由于使用的是springboot,需要打成war包.我就按照正常的思路去打包,结果部署后无法访问,一直报错404.后续问了问 公司同事,他给解决了.说大部分都是这个原因. 如果需要 ...
- Spring Boot 项目打成 war 包部署
Spring Boot 一个非常方便的功能就是支持内置的 Servlet 容器,一般我们部署 Spring Boot 应用时都是打成一个可执行的 Jar 包进行部署.其实 Spring Boot 也是 ...
- spring boot 项目打成war包部署到服务器
这是spring boot学习的第二篇了,在上一篇已经整合了spring boot项目了,如果还有小伙伴没有看得可以先去看第一篇 基础整合spring boot项目 到这里的小伙伴应该都是会整合基本的 ...
随机推荐
- java乱码问题总结
在基于Java的编程中,经常会碰到汉字的处里及显示的问题,比如一大堆乱码或问号. 这是因为JAVA中默认的编码方式是UNICODE,而中国人通常使用的文件和DB都是基于GB2312或者BIG5等编码, ...
- Java高级架构师(一)第34节:Nginx的Http模块部分的指令
默认长链接的数目在100个 默认长链接的超时时间,一般在75S.
- 消除Xcode 5中JosnKit类库的bit masking for introspection of objective-c 警告
Xcode 5中苹果对多个系统框架及相关类库进行了改进.之前建立的项目在Xcode 5中重新编译会产生一些新问题. JosnKit是常用的轻量级Josn解析类,在Xcode 5中: BOOL work ...
- 自定义Cell引发的悲剧。。。。
这两天毕设,昨晚微调自定义的cell,之前用mrc的时候直接打开xib布局好自定义cell就行乐,不用去勾选Use Autolayout,可是昨晚开始,自定义cell中,label不能动态调高的问题, ...
- scala 内部类
scala内部类不同于java内部类, java类中内部类从属于外部类,而scala的内部类从属于外部类对象 /** * 第一种方式 * 在内部类通过 外部类.this.成员名称 访问外部类成员 */ ...
- 初始化linux环境
初始化linux环境 1. 新建用户组 addgroup admin //假定为admin用户组 2. 新建用户 useradd -d /home/work -s /bin/bash -m work ...
- DataBase 之 拉链表结构设计
一.概念 拉链表是针对数据仓库设计中表存储数据的方式而定义的,顾名思义,所谓拉链,就是记录历史.记录一个事物从开始,一直到当前状态的所有变化的信息. 在历史表中对客户的一生的记录可能就这样几条记录,避 ...
- 内网渗透技巧:判断机器真实外网IP的5种方法总结
在内网渗透中有时需要在某台WEB服务器中留下后门,该机器可以通过内网IP建立IPC连接,但还需要获知外网IP或域名才能访问Wbshell,在无网关权限的情况下,我总结了有如下方法: 1.通过nsloo ...
- 解复用-mpeg2
http://blog.csdn.net/yipie/article/details/7612226 数字高清晰度电视(High Definition Television)简称HDTV,是继黑白电视 ...
- list/tuple/dict/set
一.list(列表) 内置类型,长度可变的有序集合,索引从0开始,索引为负数是标识从右开始取,最右边第一个是-1,以此类推.里面的元素可以是不同类型的. 1.定义:a = [] #空列表 2.获取长度 ...