Apache CXF 在 WebLogic 9.2 上的问题定位分析及权宜之计

简介: http://yulimin.javaeye.com/blog/129015 同样的程序在 Tomcat 5.5.16/25 以及 Jetty 5.1.12 上都能够成功部署及运行,但是部署到 WebLogic 9.2 上时出错 org.springframework.web.context.ContextLoader initWebApplicationContext FATAL: Con

http://yulimin.javaeye.com/blog/129015

同样的程序在 Tomcat 5.5.16/25 以及 Jetty 5.1.12 上都能够成功部署及运行,但是部署到 WebLogic 9.2 上时出错
org.springframework.web.context.ContextLoader initWebApplicationContext
FATAL: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxxWebService': Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: portName
Caused by: java.lang.NoSuchMethodError: portName
at org.apache.cxf.jaxws.support.JaxWsImplementorInfo.getEndpointName(JaxWsImplementorInfo.java:154)
at org.apache.cxf.jaxws.support.JaxWsServiceConfiguration.getEndpointName(JaxWsServiceConfiguration.java:89)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.getEndpointName(ReflectionServiceFactoryBean.java:983)
at org.apache.cxf.frontend.AbstractEndpointFactory.createEndpoint(AbstractEndpointFactory.java:91)
at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:107)
at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:147)
at jrockit.reflect.VirtualNativeMethodInvoker.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Unknown Source)
at java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;I)Ljava.lang.Object;(Unknown Source)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1179)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1145)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:427)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:144)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:160)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:279)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:360)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:241)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:184)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:49)

从 Stack Trace 来分析,Spring 在 ContextLoaderListener 进行加载配置文件时出错了。
通过查看 JaxWsImplementorInfo.java:154 的源程序
代码
portName = wsAnnotations.get(x).portName();  

可以知道 wsAnnotations 的定义为
代码
private List<WebService> wsAnnotations = new ArrayList<WebService>(2);  

得到List里的对象类型为WebService,并得到全称为javax.jws.WebService
通过 JarClassFind 来搜索,可以得到 Apache CXF 中的 geronimo-ws-metadata_2.0_spec-1.1.1.jar 包含有这个类
而 WebLogic 9.2 中的则有两个 .jar 文件包含有此类:
No.1
Jar Package:%WLS_HOME%/server/lib/api.jar
No.2
Jar Package:%WLS_HOME%/server/lib/weblogic.jar
经过对比,WebLogic 9.2 里的两个 .jar 文件里带个类是一样的,况且,正常启动时 WebLogic 也只是将 weblogic.jar 加到 CLASSPATH 中。

问题猜测应当是由于这两类的版本不一样导致的,拆出来 jad 一下,WebLogic 中的 javax.jws.WebService.java 代码为:
代码
package javax.jws;  
 
import java.lang.annotation.Annotation;  
 
public interface WebService  
    extends Annotation  
{  
 
    public abstract String name();  
 
    public abstract String targetNamespace();  
 
    public abstract String serviceName();  
 
    public abstract String wsdlLocation();  
 
    public abstract String endpointInterface();  
}  

拆出 Apache CXF 里的 javax.jws.WebService jad 一下,代码为:
代码
package javax.jws;  
 
import java.lang.annotation.Annotation;  
 
public interface WebService  
    extends Annotation  
{  
 
    public abstract String name();  
 
    public abstract String targetNamespace();  
 
    public abstract String serviceName();  
 
    public abstract String wsdlLocation();  
 
    public abstract String endpointInterface();  
 
    public abstract String portName();  
}  

这下就完全明白了,是 Apache CXF 期望加载的 javax.jws.WebService 注解与 Weblogic 中 javax.jws.WebService 注解版本不一致导致的。

OK,现在首先想到的是在 weblogic.xml 设置 prefer-web-inf-classes 为 true 来提前加载了。如下:
代码
<?xml version="1.0" encoding="UTF-8"?>  
<weblogic-web-app>  
    <container-descriptor>  
        <prefer-web-inf-classes>true</prefer-web-inf-classes>  
    </container-descriptor>  
</weblogic-web-app>  

总以为能够象往常一样,这样可以了,但是将 prefer-web-inf-classes 设置为 true 后,却发生了另一个异常了:
代码
FATAL: Context initialization failed  
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xxxWebService': Invocation of init method failed; nested exception is java.lang.LinkageError: Class javax/xml/namespace/QName violates loader constraints  
Caused by: java.lang.LinkageError: Class javax/xml/namespace/QName violates loader constraints  
        at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl.<clinit>(RuntimeBuiltinLeafInfoImpl.java:186)  
        at com.sun.xml.bind.v2.model.impl.RuntimeTypeInfoSetImpl.<init>(RuntimeTypeInfoSetImpl.java:25)  
        at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:84)  
        at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.createTypeInfoSet(RuntimeModelBuilder.java:41)  
        at com.sun.xml.bind.v2.model.impl.ModelBuilder.<init>(ModelBuilder.java:104)  
        at com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder.<init>(RuntimeModelBuilder.java:49)  
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:372)  
        at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:236)  
        at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:76)  
        at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:55)  
        at jrockit.reflect.InitialMethodInvoker.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;(Unknown Source)  
        at java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;I)Ljava.lang.Object;(Unknown Source)  
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:210)  
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:366)  
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)  
        at org.apache.cxf.jaxb.JAXBDataBinding.createJAXBContext(JAXBDataBinding.java:377)  
        at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:182)  
        at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:244)  
        at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:272)  
        at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:146)  
        at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:89)  
        at org.apache.cxf.frontend.AbstractEndpointFactory.createEndpoint(AbstractEndpointFactory.java:83)  
        at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:107)  
        at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:147)  

面对这个 java.lang.LinkageError: Class javax/xml/namespace/QName 错误,自然又联想到了版本不一致的问题。
继续 JarClassFind ,在 Apache CXF 里找到 stax-api-1.0.1.jar 包含有这个类。
No.1
Jar Package:%WLS_HOME%/server/lib/api.jar
No.2
Jar Package:%WLS_HOME%/server/lib/weblogic.jar
No.3
Jar Package:%WLS_HOME%/server/lib/webserviceclient+ssl.jar
No.4
Jar Package:%WLS_HOME%/server/lib/webserviceclient.jar
No.5
Jar Package:%WLS_HOME%/server/lib/xbean.jar
同样与 WebLogic 启动时有关的仍是 weblogic.jar ,怪异的是 WebLogic 中居然有三个版本的 javax/xml/namespace/QName 这个类,真是比较糟糕的事情。
api.jar、weblogic.jar 与 webserviceclient+ssl.jar、webserviceclient.jar 和 xbean.jar 中各是一个版本。

但是通过 jad 发现 weblogic 里的 javax/xml/namespace/QName 与 Apache CXF 里的是一样的,比较奇怪了。。。
再进行认真地比较发现,文件的时间不同,再直接进行对比 .class 文件,还是有两处有不同之处。Apache CXF 的时间晚于 WebLogic 里的类的时间,于是只能怀疑后者引起类在加载时发生了 java.lang.LinkageError 错误。
经查JDK文档:LinkageError 的子类指示一个类在一定程度上依赖于另一个类;但是,在编译前一个类之后,后一个类发生了不相容的改变。

于是真相大明了?因为 Apache CXF 里的类的时间晚于 WebLogic 里的类的时间,而且类的二进制内容也发生了改变,于是原来 WebLogic 里的其它类由于我们通过了 prefer-web-inf-classes 设置为 true 后,而引用到了现在的 Apache CXF 里的类了,就发生了 java.lang.LinkageError 错误。

由于设置 prefer-web-inf-classes 设置为 true 后,提前加载了应用程序中 lib 目录下的 .jar 文件,而发生了这个问题,于是就尝试去掉 prefer-web-inf-classes 的设置,直接在 WebLogic 的启动脚本中增加第一次异常时相关的 jar 到 CLASSPATH 中,即 geronimo-ws-metadata_2.0_spec-1.1.1.jar 文件,只提前加载这个 jar 文件。
代码
set CLASSPATH_CXF=X:/xyz/geronimo-ws-metadata_2.0_spec-1.1.1.jar  
set CLASSPATH=%CLASSPATH_CXF%;%CLASSPATH%;%MEDREC_WEBLOGIC_CLASSPATH%  

于是,再次进行启动,这下则可以正常启动了。

为了支持 Aegis ,除了必需的之外,还需要再增加如下 jar 包:
- jaxen.jar
- jdom.jar
- stax-utils.jar 

相关文章
|
存储 Apache
Apache Hudi Savepoint实现分析
Apache Hudi Savepoint实现分析
293 0
|
3月前
|
存储 自然语言处理 分布式计算
Apache Doris 3.1 正式发布:半结构化分析全面升级,湖仓一体能力再跃新高
Apache Doris 3.1 正式发布!全面升级半结构化分析,支持 VARIANT 稀疏列与模板化 Schema,提升湖仓一体能力,增强 Iceberg/Paimon 集成,优化存储引擎与查询性能,助力高效数据分析。
549 4
Apache Doris 3.1 正式发布:半结构化分析全面升级,湖仓一体能力再跃新高
|
消息中间件 数据挖掘 Kafka
Apache Kafka流处理实战:构建实时数据分析应用
【10月更文挑战第24天】在当今这个数据爆炸的时代,能够快速准确地处理实时数据变得尤为重要。无论是金融交易监控、网络行为分析还是物联网设备的数据收集,实时数据处理技术都是不可或缺的一部分。Apache Kafka作为一款高性能的消息队列系统,不仅支持传统的消息传递模式,还提供了强大的流处理能力,能够帮助开发者构建高效、可扩展的实时数据分析应用。
749 5
|
9月前
|
存储 SQL Apache
为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案?
本文将从技术选型的视角,从开放性、系统架构、实时写入、实时存储、实时查询等多方面,深入分析 Apache Doris 与 Elasticsearch 的能力差异及性能表现
846 17
为什么 Apache Doris 是比 Elasticsearch 更好的实时分析替代方案?
|
6月前
|
人工智能 运维 监控
Aipy实战:分析apache2日志中的网站攻击痕迹
Apache2日志系统灵活且信息全面,但安全分析、实时分析和合规性审计存在较高技术门槛。为降低难度,可借助AI工具如aipy高效分析日志,快速发现攻击痕迹并提供反制措施。通过结合AI与学习技术知识,新手运维人员能更轻松掌握复杂日志分析任务,提升工作效率与技能水平。
|
消息中间件 监控 数据挖掘
基于RabbitMQ与Apache Flink构建实时分析系统
【8月更文第28天】本文将介绍如何利用RabbitMQ作为数据源,结合Apache Flink进行实时数据分析。我们将构建一个简单的实时分析系统,该系统能够接收来自不同来源的数据,对数据进行实时处理,并将结果输出到另一个队列或存储系统中。
1094 2
|
存储 SQL Apache
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
Apache Doris 是一个基于 MPP 架构的高性能实时分析数据库,以其极高的速度和易用性著称。它支持高并发点查询和复杂分析场景,适用于报表分析、即席查询、数据仓库和数据湖查询加速等。最新发布的 2.0.2 版本在性能、稳定性和多租户支持方面有显著提升。社区活跃,已广泛应用于电商、广告、用户行为分析等领域。
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
|
存储 JSON 物联网
查询性能提升 10 倍、存储空间节省 65%,Apache Doris 半结构化数据分析方案及典型场景
本文我们将聚焦企业最普遍使用的 JSON 数据,分别介绍业界传统方案以及 Apache Doris 半结构化数据存储分析的三种方案,并通过图表直观展示这些方案的优势与不足。同时,结合具体应用场景,分享不同需求场景下的使用方式,帮助用户快速选择最合适的 JSON 数据存储及分析方案。
619 15
查询性能提升 10 倍、存储空间节省 65%,Apache Doris 半结构化数据分析方案及典型场景
|
监控 Cloud Native BI
8+ 典型分析场景,25+ 标杆案例,Apache Doris 和 SelectDB 精选案例集(2024版)电子版上线
飞轮科技正式推出 Apache Doris 和 SelectDB 精选案例集 ——《走向现代化的数据仓库(2024 版)》,汇聚了来自各行各业的成功案例与实践经验。该书以行业为划分标准,辅以使用场景标签,旨在为读者提供一个高度整合、全面涵盖、分类清晰且易于查阅的学习资源库。
451 8
|
存储 数据挖掘 数据处理
Apache Paimon 是一款高性能的数据湖框架,支持流式和批处理,适用于实时数据分析
【10月更文挑战第8天】随着数据湖技术的发展,越来越多企业开始利用这一技术优化数据处理。Apache Paimon 是一款高性能的数据湖框架,支持流式和批处理,适用于实时数据分析。本文分享了巴别时代在构建基于 Paimon 的 Streaming Lakehouse 的探索和实践经验,包括示例代码和实际应用中的优势与挑战。
632 1

推荐镜像

更多