`

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

    博客分类:
  • Java
阅读更多
同样的程序在 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
分享到:
评论
7 楼 cctvx1 2008-08-07  
其实这个问题的根本原因是,WLS9.2中的WLS9.2自带的JWS Package(weblogic.jar)与JSR181 JSR181 2.0 Final Release有部分annotation不一致
包括
@WebService 的portName 解决方法是使用@WLHttpTransport
(portName="ServiceProt"…)

@WebMethod 的exclude
@WebParam 的partName
@WebResult 的partName,header

原因很简单,当WLS9.2 出来的时候JSR181 Final Relase还没有出来。

可以参考JSR181草案-->FINAL的中间所有文档。

在JCP的PDF里面清晰的有

Web Services Metadata for the JavaTM Platform Specification ("Specification")
Version: 2.0
Status: FCS

同时在JavaDoc里面也有 这个说明,Since.

portName
public abstract java.lang.String portNameThe port name of the Web Service.
Used as the name of the wsdl:port when mapped to WSDL 1.1.

This member-value is not allowed on endpoint interfaces.


Since:
2.0
Specification Default:
@WebService.name+擯ort?
Default:
""

上面说的几个都是Since 2.0增加的。不过大部分人因为一开始就使用了2.0 FCS版 所有就不太清楚这个。
6 楼 stamen 2008-08-06  
分析透彻,非常好,谢谢了.
5 楼 quickselect 2008-08-06  
好样的,帮我解决了大问题!!
4 楼 ma.bin 2008-07-30  
我用的是cxf2.1.1版本
抛上面的错误
将版本回退到2.0.7就没有异常了。
3 楼 ma.bin 2008-07-30  
按照楼上和搂主的方法。
在cxf2.1.1版本中
仍然抛nested exception is javax.xml.ws.WebServiceException: java.lang.ArrayIndexOutOfBoundsException

Caused by: java.lang.ArrayIndexOutOfBoundsException
        at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.createMessageParts(ReflectionServiceFactoryBean.j
ava:1272)

异常。
在tomcat中也是对的。
比较郁闷。
2 楼 jeff_yuchang 2007-10-11  
通过打成ear也可以解决这个问题...

http://cwiki.apache.org/confluence/display/CXF20DOC/AppServerGuide
1 楼 jnn 2007-10-04  
不知道你遇到的LinkError具体的错误信息是什么样的。<br/>
<pre>java.lang.LinkageError: Class ** violates loader constraints<br/><br/>如果是上面的内容,那你有关LinkError的解释就不正确了,这是由于设置<span class='postbody'>prefer-web-inf-classes 为 true<br/>导致加载CXF相关jar的class loader与Weblogic Parent class loader之间脱离父子关系,<br/>JVM检测到QName的class loader与CXF jar class loader不一致而抛出的异常。<br/><br/>这个异常与class文件编译的时间没有任何关系。<br/><br/> </span></pre>

相关推荐

    CXF项目部署weblogic9.2终极解决方案

    在IT行业中,Apache CXF是一个广泛使用的开源框架,主要用于构建和开发服务导向架构(SOA)和服务级应用程序。本文将详细解析如何将CXF项目部署到WebLogic Server 9.2,提供一个终极解决方案。 首先,`...

    JacORB官方2.3以下所有版本(附带全部源码)

    虽然主要讨论的是 JacORB,但压缩包中包含了关于 Apache CXF 在 WebLogic 9.2 上问题定位的文档。Apache CXF 是一个开源服务框架,它支持多种 Web 服务标准,如 SOAP、RESTful 和 XML/JSON。WebLogic 是 Oracle 提供...

    apache cxf_jar包

    Apache CXF是一个开源的Java框架,它主要用于构建和开发服务导向架构(SOA)中的Web服务。这个"apache cxf_jar包"包含了实现基于Java的Web服务所需的一系列核心库。下面我们将深入探讨这些jar文件及其在Web服务实现...

    基于Apache CXF构建SOA应用

    Apache CXF 框架是一个比较有前途的开源 Web Services 框架,也是构建 SOA 架构应用的利器。本书采用案例源码和解说形式全面介绍 Apache CXF 框架的功能。 本书共 15 章,大致分为三个部分。第一部分介绍关于 SOA 和...

    apache-cxf-3.5.0.zip

    Apache CXF 是一款广泛使用的开源框架,主要用于构建和部署高质量的Web服务。它以其灵活性、易用性和强大的功能集而闻名。"apache-cxf-3.5.0.zip" 文件包含了CXF框架的3.5.0版本,该版本可能包含了一些新特性、改进...

    apache-cxf 2.2.8版本下载

    CXF这个名字来源于两个曾经流行的开源项目:XFire和Celtix,它们在2006年合并成为了现在的Apache CXF。 Apache CXF 2.2.8是该框架的一个特定版本,发布于2010年。这个版本包含了对Web服务的支持,允许开发者使用...

    Apache CXF

    Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF Apache CXF

    两本关于apache cxf的书籍,英文

    Apache CXF是一个开源的Java框架,专门用于构建和部署Web服务。它提供了全面的工具和技术,使得开发人员能够轻松地创建、实现和部署基于SOAP(简单对象访问协议)和RESTful(表述性状态转移)风格的服务。这两本书籍...

    apache-cxf2.7.18官方版最稳定版本

    它的名称CXF来源于两个前身项目:XFire和Celtix的组合,这两个项目在2006年合并成为Apache CXF。Apache CXF 2.7.18是该框架的一个稳定版本,提供了对Java EE、JAX-WS和JAX-RS标准的强大支持。 CXF的主要特性包括: ...

    Apache CXF Web Service Development(源码)

    "ApacheCXFBook"可能是书名或者是包含多个章节的文档,可能详细介绍了Apache CXF的使用方法、最佳实践,以及可能的案例分析。 在学习和使用Apache CXF时,开发者可以期待掌握以下关键知识点: 1. **SOAP与RESTful...

    apache-cxf3.1.15和3.2.3合集及jdk说明

    由于没有具体提到需要哪个版本的JDK,通常Apache CXF支持Java 7及以上版本。因此,你可以选择安装JDK 7或更高版本,但最好遵循项目文档中的推荐配置,以确保最佳的兼容性和性能。 使用Apache CXF的步骤大致如下: ...

    apache-cxf-3.1.8.zip

    10. **错误处理和调试**:CXF提供了详细的日志记录和异常处理机制,帮助开发者定位和解决问题。其强大的故障跟踪功能对于调试和优化Web服务尤其有用。 在"apache-cxf-3.1.8"这个压缩包中,包含了Apache CXF 3.1.8...

    基于Apache CXF构建SOA应用 随书源代码

    本书主要介绍Apache CXF在构建SOA架构各个方面的应用说明和编程案例。覆盖以下内容:基于JAX-WS规范和CXF自身的前端模式实现,CXF支持的数据绑定(DataBindings),CXF支持的WSDL绑定,CXF支持的传输协议绑定。CXF的...

    cxf框架包 apache-cxf-3.4.3.tar.gz

    在本案例中,我们讨论的是"apache-cxf-3.4.3.tar.gz",这是Apache CXF 3.4.3版本的压缩包,通常包含了CXF框架的所有组件和必要的库文件。 **1. CXF框架介绍** Apache CXF是一个全面的服务开发框架,它的全称是...

    CXF support WAS Weblogic

    #### 如何在WAS和Weblogic上部署CXF **1. WAS配置概述** 对于WebSphere Application Server (WAS),根据不同的版本(如小于6.1.0.29),可能需要采取不同的配置策略: - **未安装Web Services Feature Pack**:将...

    Developing Web Services with Apache CXF and Axis2(3rd Edition).zip

    Apache CXF = Celtix + XFire,Apache CXF 的前身叫 Apache CeltiXfire,现在已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且...

    apache cxf 用户手册

    apache cxf 2.1.3 的用户手册

    apache-cxf-2.7.11

    CXF这个名字是"CXF"前两个版本的名字——"Celtic XFire"和"XFire"的组合,它代表了这个框架在集成不同技术栈上的连续性和进化。在Apache CXF 2.7.11版本中,我们看到了一个相对稳定的版本,它为开发者提供了对Java ...

Global site tag (gtag.js) - Google Analytics