使用CXF JaxWSClientFactoryBean创建Webservice客户端的WSDL解析异常

时间:2013-01-24 15:11:17

标签: java wsdl weblogic cxf xerces

我已经编写了一些代码来使用CXF创建和运行webservice客户端。我使用JaxWsClientFactoryBean(不确定它是最好的解决方案)从.wsdl文件创建客户端。 这里的目标是以编程方式避免Spring等。只使用Java和CXF的纯代码。

JaxWsClientFactoryBean cfb = new JaxWsClientFactoryBean();
cfb.setAddress(getServiceProperty(intClass, PROPERTY_KEY_URL_SUFFIX));
cfb.setServiceClass(intClass);
cfb.setOutInterceptors(getOutInterceptors(intClass));
cfb.setServiceName(SERVICE_NAME);
cfb.setWsdlURL("classpath:wsdl/" + intClass.getSimpleName() + ".wsdl");
cfb.setEndpointName(ENDPOINT_NAME);
Client client = cfb.create();
ClientProxy cp = new ClientProxy(client);
I intService = (I) 
   Proxy.newProxyInstance(intClass.getClassLoader(), new Class[] { intClass }, cp);

我真的不确定这是否正确完成,但是当我在本地运行此代码以及在Tomcat上部署它时,它可以正常工作。

不幸的是,我需要在Weblogic上运行此代码,这会导致奇怪的异常:

Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was
made to insert a node where it is not permitted.
        at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:235)
        at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:186)
        at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:92)
        ... 26 more
Caused by: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
        at com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(ParentNode.java:356)
        at com.sun.org.apache.xerces.internal.dom.ParentNode.insertBefore(ParentNode.java:284)
        at com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.insertBefore(CoreDocumentImpl.java:399)
        at com.sun.org.apache.xerces.internal.dom.NodeImpl.appendChild(NodeImpl.java:235)
        at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1019)
        at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:939)
        at org.apache.cxf.staxutils.StaxUtils.read(StaxUtils.java:866)
        at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:226)
        ... 28 more

这在应用程序部署期间发生。看起来.wsdl文件有问题,但是等等......它正在使用Tomcat!

我认为com.sun.org.apache.xerces。*在Weblogic中使用JRockit VM和标准JVM实现类可能会有所不同,但我不知道如何解决它。

我花了很多时间尝试不同的客户端创建方式。他们中的大多数在本地和Tomcat中工作,但在WebLogic上没有。

任何暗示接下来要尝试什么?我有点厌倦了这个话题:D

1 个答案:

答案 0 :(得分:2)

我同意您的怀疑,该问题与使用的Xerces版本有关。堆栈跟踪显示在您的情况下使用了Xerces的Sun实现,它是Apache Xerces的衍生产品。

请查看与WebLogic相关的Apache CFX Application Server Configuration Guide说明。

WebLogic ClassLoading

在WebLogic Server中,系统类路径中存在的任何.jar文件都由WebLogic Server系统类加载器加载。在服务器实例中运行的所有应用程序都加载到应用程序类加载器中,这些类加载器是系统类加载器的子代。在系统类加载器的此实现中,应用程序不能使用已存在于系统类加载器中的不同版本的第三方jar。每个子类加载器都会向父(系统类加载器)询问特定的类,并且不能加载父类看到的类。

例如,如果$ CLASSPATH和应用程序EAR中都存在一个名为com.foo.Baz的类,则加载$ CLASSPATH中的类,而不是EAR中的类。由于weblogic.jar位于$ CLASSPATH中,因此应用程序无法覆盖任何WebLogic Server类。

要使用Xerces的备用版本,您必须创建FilteringClassLoader。

使用FilteringClassLoader

FilteringClassLoader 提供了一种机制,您可以配置部署描述符以明确指定应始终从应用程序加载某些包,而不是由系统类加载器加载。这允许您使用备用版本的应用程序,如Xerces和Ant。

FilteringClassLoader位于应用程序类加载器和系统之间。它是系统类加载器的子项,也是应用程序类加载器的父项。 FilteringClassLoader拦截loadClass(String className)方法,并将className与weblogic-application.xml文件中指定的包列表进行比较。

总之,检查Apache CFX Application Server Configuration Guide中包含的步骤,并注意明确指定从应用程序加载org.apache.xerces.*包,而不是从系统类加载器加载。

例如,META-INF中的weblogic-application.xml文件应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90">
    <application-param>
        <param-name>webapp.encoding.default</param-name>
        <param-value>UTF-8</param-value>
    </application-param>
    <prefer-application-packages>
        <package-name>javax.jws.*</package-name>
        <package-name>org.apache.xerces.*</package-name>
    </prefer-application-packages>
</weblogic-application>

我希望这会有所帮助。