Maven里Xerces依赖冲突导致Spring加载xml出错

如果你在使用Spring加载xml文件时出现下面的错误:

javax.xml.parsers.ParserConfigurationException: Unable to validate using XSD: Your JAXP provider [org.apache.xerces.jaxp.DocumentBuilderFactoryImpl@50c4fe76] does not support XML Schema. Are you running on Java 1.4 with Apache Crimson? Upgrade to Apache Xerces (or Java 1.5) for full XSD support.


你可以首先考虑是否存在xerces jar包冲突,可以查找有哪些jar包里面包括DocumentBuilderFactoryImpl这个类。


我的项目中出现该错误的原因就是因为同时存在两个jar包中含有该类:xerces-1.2.3.jar和xercesImpl-2.6.2.jar,后者是我们需要的jar,但是由于某种原因xerces-1.2.3.jar在classpaht中的位置靠前,所以产生以上的错误。


因为项目中用到了maven,xercesImpl-2.6.2.jar是在pom.xml直接依赖的,而xerces-1.2.3.jar是由于引入了camel-jxpath而间接被引入的,所以一种解决方案是在camel-jxpath的依赖中加入exclusion以去掉对xerces-1.2.3.jar的引用:

<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jxpath</artifactId>
<version>1.4.0</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xerces</artifactId>
</exclusion>
</exclusions>  
</dependency>


但是如果xerces-1.2.3.jar被其它的类所用到,那你就只能在你的shell script里面将xercesImpl-2.6.2.jar在classpath中的位置调到xerces-1.2.3.jar前面。


在使用Maven的项目中,经常会出现这类问题。而且这类问题很有可能是在开发阶段发现不了,等部署到Linux/Unix就出现了。根源就在于runtime时的classpath不能保证和开发阶段一样。

其实问题还没有结束?

明明是Spring load xml文件,为什么就用到xerces-1.2.3.jar里面的类,那如果没有这个jar,spring load xml文件是不是就要失败?这就要去看Spring是如何load xml文件的。

详细的过程这里就不讲了,有一位帅哥的文章中写得很详细:spring 读取 xml 配置源代码解析http://kiminotes.iteye.com/blog/547103),这里只讲其中关键的一步:如何获得DocumentBuilderFactory的实例,其实javadoc里面说得很详细,只是平时没有注意罢了。

1、Use the “javax.xml.parsers.DocumentBuilderFactory” system property.

2、Use the properties file "lib/jaxp.properties" in the JRE directory.

3、Use the Services API (as detailed in the JAR specification), if available, to determine the classname. The Services API will look for a classname in the file “META-INF/services/javax.xml.parsers.DocumentBuilderFactory"  in jars available to the runtime.

4、Platform default "DocumentBuilderFactory" instance,也就是类com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl。

如果前面三步都找不到实现类,jdk(好像必须是jdk1.5或以上版本)里自带的类DocumentBuilderFactoryImpl将会被使用,所以不用担心没有xerces-1.2.3.jar spring load xml会失败。


回到前面讲到的例子,xerces里面的类就是在step 3被调用的。打开xercesImpl-2.6.2.jar你可以看到里面存着文件 “META-INF/services/javax.xml.parsers.DocumentBuilderFactory" ,文件的内容是org.apache.xerces.jaxp.DocumentBuilderFactoryImpl,所以系统会去加载org.apache.xerces.jaxp.DocumentBuilderFactoryImpl这个类,而这个类在xerces-1.2.3.jar里面存着,所以xerces-1.2.3.jar里的类就被使用了。


最后你可以通过java -Djaxp.debug=1 YourProgram来打印出jaxp的debug信息。






阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭