No XPathFctory implementation found for the object model: http://java.sun.com/jaxp/xpath/dom

异常信息

    最近在使用 CXF-DOSGI 动态调用 WebService 时,如果传入的参数不是简单的原生类型和 String 等基本类型,而是一个对象时,会抛出“java.lang.ExceptionInInitializerError” 的异常,异常信息如下:

java.lang.ExceptionInInitializerError
	at com.sun.tools.internal.xjc.reader.internalizer.DOMForest.transform(DOMForest.java:437)
	at com.sun.tools.internal.xjc.api.impl.s2j.SchemaCompilerImpl.bind(SchemaCompilerImpl.java:210)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.cxf.common.util.ReflectionInvokationHandler.invoke(ReflectionInvokationHandler.java:54)
	at com.sun.proxy.$Proxy15.bind(Unknown Source)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:320)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:240)
	at org.apache.cxf.endpoint.dynamic.DynamicClientFactory.createClient(DynamicClientFactory.java:219)
	at gboat2.cxf.utils.CXFUtil.createJaxWsDynamicClient(CXFUtil.java:121)
	at gboat2.cxf.utils.CXFUtil.invokeWebService(CXFUtil.java:211)
	at gboat2.cxf.utils.CXFUtil.invokeWebService(CXFUtil.java:194)
	at cn.tisson.intf.protocol.Main.main(Main.java:65)
Caused by: java.lang.RuntimeException: XPathFactory#newInstance() failed to create an XPathFactory for the default object model: http://java.sun.com/jaxp/xpath/dom with the XPathFactoryConfigurationException: javax.xml.xpath.XPathFactoryConfigurationException: No XPathFctory implementation found for the object model: http://java.sun.com/jaxp/xpath/dom
	at javax.xml.xpath.XPathFactory.newInstance(Unknown Source)
	at com.sun.tools.internal.xjc.reader.internalizer.Internalizer.(Internalizer.java:70)
	... 15 more

    使用 Google 和 Baidu 搜索解决方案时,大多是说在项目中引入 xalan 相关的 jar 包,但我在 xalan-2.7.1.jar 和其相关的几个 jar 包都加入到项目中,重新启动后调用 webService 时仍然抛出一样的异常,折腾了半天无果而终,网上的各种解决方案该试的都试过了,但因为我们的项目是使用的 OSGI 环境,与普通的 javaWeb 环境还不太一样,最终没办法,就只能试着设置一个对应的异常断点,根据断点去跟踪源代码。

原因分析

    通过跟踪源代码得知 XPathFactory#newInstance() 方法创建 XPathFactory 实例主要是通过调用 javax.xml.xpath.XPathFactoryFinder 类中的相关方法实现,它查找 XPathFactory 对象的顺序如下:

1. 如果存在系统属性 DEFAULT_PROPERTY_NAME + ":uri"(其中 uri 就是我们异常信息中的“http://java.sun.com/jaxp/xpath/dom”),则其值作为类名称读取。该方法将试图通过使用类加载器创建此类的新实例,如果创建成功,则返回它。 
2. 读取 ${java.home}/lib/jaxp.properties,并查找与作为系统属性的键关联的值。如果存在,则按上面的方式处理该值。 
3. 类加载器要求服务提供者的提供者配置文件与资源目录 META-INF/services 中的 javax.xml.xpath.XPathFactory 匹配。有关文件格式和解析规则,请参阅 JAR File Specification。每个可能的服务提供者均要实现该方法: 
       isObjectModelSupported(String objectModel)
     返回支持指定对象模型的类加载器顺序中的第一个服务提供者。 
4. 以特定于平台的方式来定位平台默认的 XPathFactory。必须存在 W3C DOM 的平台默认 的 XPathFactory,即 DEFAULT_OBJECT_MODEL_URI。 
如果这些都失败,则抛出 XPathFactoryConfigurationException

解决方案

    既然已经知道其实现原理了,问题就好解决了,我为了省事就直接在调用 WebService 工具类的静态块中添加了如下代码:

// 设置 XPathFactory,解决调用 webService 传递复杂对象时抛出 java.lang.ExceptionInInitializerError 错误的问题
System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":" + XPathFactory.DEFAULT_OBJECT_MODEL_URI, "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl");

特别需要提醒的是,如果你想使用 jaxp.properties 的方式指定 XPathFactory,要记得将冒号(:)使用反斜杠(\)进行转义,如:

http\://java.sun.com/jaxp/xpath/dom=org.acme.DomXPathFactory

参考资料:
http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/1.6/api/javax/xml/xpath/XPathFactory.html#newInstance(java.lang.String)
http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/javax/xml/xpath/XPathFactory.html#newInstance(java.lang.String)

你可能感兴趣的:(javaWeb,webservice)