原来我们的程序都是基于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的官方文档。得到的解决方式例如以下:

參考

lang=en">http://www-01.ibm.com/support/knowledgecenter/SS7JFU_7.0.0/com.ibm.websphere.express.doc/info/exp/ae/twbs_thirdparty.html?lang=en

http://cxf.apache.org/docs/application-server-specific-configuration-guide.html#ApplicationServerSpecificConfigurationGuide-ForWebSphere6.1.0.29+,V7andV8

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
    = 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文件夹下.

osgi应用使用桥接的方式打成war包部署在websphere上时遇到的与cxf相关的问题的更多相关文章

  1. SpringBoot之打成war包部署到Tomcat

    正常情况下SpringBoot项目是以jar包的形式,正常情况下SpringBoot项目是以jar包的形式,并且SpringBoot是内嵌Tomcat服务器,所以每次重新启动都是用的新的Tomcat服 ...

  2. springboot 学习之路 5(打成war包部署tomcat)

    目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...

  3. 将web项目打成war包部署在tomcat步骤

    将web项目打成war包部署在tomcat步骤 1.将自己的项目打成war包. 2.将打包好的war复制到${tomcat.home}/webapps项目下. 3.在${tomcat.hom}/con ...

  4. Web项目打成war包部署Tomcat时运行startup.bat直接闪退部署失败解决方案

    即上篇通过将web项目打成war包部署到Tomcat服务器,解决mysql问题后,又出现了新问题,真是一波三折,所以将解决过程分享给大家,希望能帮助到小伙伴们~ 将打好的war包拷贝到Tomcat的w ...

  5. 使用idea创建springboot项目并打成war包发布到weblogic上

    部署tomcat也是类似的,但是需要注意项目配置的路径,或者直接将项目放到webapp的ROOT目录下. 使用工具:intelliJ IDEA2016.3, jdk1.8 ,weblogic12 一 ...

  6. Web项目打成war包部署到tomcat时报MySQL Access denied for user 'root'@'localhost' (using password: YES)错误解决方案

    Web项目使用使用root账号root密码进行部署,通过Eclipse加载到Tomcat服务器可以发布成功,打成war包放到tomcat的webapps目录无法发布成功,报错: jdbc.proper ...

  7. SpringBoot(十八)_springboot打成war包部署

    最近在做项目的时候,由于使用的是springboot,需要打成war包.我就按照正常的思路去打包,结果部署后无法访问,一直报错404.后续问了问 公司同事,他给解决了.说大部分都是这个原因. 如果需要 ...

  8. Spring Boot 项目打成 war 包部署

    Spring Boot 一个非常方便的功能就是支持内置的 Servlet 容器,一般我们部署 Spring Boot 应用时都是打成一个可执行的 Jar 包进行部署.其实 Spring Boot 也是 ...

  9. spring boot 项目打成war包部署到服务器

    这是spring boot学习的第二篇了,在上一篇已经整合了spring boot项目了,如果还有小伙伴没有看得可以先去看第一篇 基础整合spring boot项目 到这里的小伙伴应该都是会整合基本的 ...

随机推荐

  1. POJ 3437 Tree Grafting

    题意:给出一个深度优先遍历树的up down顺序,求这棵树以及这棵树变为”左子右兄”树的高度 思路:直接dfs,x代表树1的高度,y代表树2的高度 #include<cstdio> #in ...

  2. Notepad++前端开发常用插件介绍

    Notepad++前端开发常用插件介绍 Notepad++除了自身的功能强大之外,更是有许多非常的优秀的插件,下面就总结一下前端开发过程一些比较常用的插件. Emmet Emmet的前身是Zen Co ...

  3. 在Linux系统环境下修改MySQL的root密码

    root用户登录系统 /usr/local/mysql/bin/mysqladmin -u root -p password 新密码 enter password 旧密码 第二种方法: root用户登 ...

  4. Android SO(动态链接库)UPX加固指南

    前言 随着移动互联网的爆发性增长,人们对移动应用的需求变得越来越复杂,企业在带给用户众多便利和享受的同时,却容易忽视应用自身的安全性问题,一旦遭受攻击,就会给企业和用户的经济或声誉带来影响.本文主要是 ...

  5. datetimepicker只显示日期,不显示时分秒

    HTML代码<div class="input-group date form_datetime form-date" data-link-field="dtp_i ...

  6. tcpdump的使用

    tcpdump命令的控制分4个部分 控制tcpdump行为 -c 控制抓取报文的个数 -p 非混杂模式 -s 限制报文长度,0 为不限制 -w 保存抓取的报文到指定路径 -r 从pcap报文读取报文 ...

  7. 【java】随机生成6位的数字 /生成例如010 045这样的三位数

    int radomInt = new Random().nextInt(999999) @org.junit.Test public void testName() throws Exception ...

  8. 【项目 部署】部署项目web context root,项目跟路径跟项目实际名称不符

    项目如下: 但是部署到 tomcat下后,tomcat中项目根目录变成: 并且项目启动起来之后, 解决方法: 发现此处 不能更改,然后 在workspace下找到本项目,定位到.setting文件夹下 ...

  9. sqlmap的二次开发

    1.sqlmapapi的帮助信息. -s 启动sqlmap作为服务器 -h 指定sqlmap作为服务器的IP地址,默认127.0.0.1 -p 指定sqlmap服务器的端口,默认端口为8775 2.启 ...

  10. 白话空间统计之:Moran&#39;s I(莫兰指数)

    前两天聊了空间统计学里面的两个经典概念,今天来说说第一篇文章留下的大坑:Moran's I. 首先,Moran's I这个东西.官方叫做:莫兰指数,是澳大利亚统计学家帕特里克·阿尔弗雷德·皮尔斯·莫兰 ...