在我的办公室里,仅提及Xerces一词就足以引起开发人员的致命愤怒。粗略地浏览SO上的其他Xerces问题似乎表明,几乎所有Maven用户在某个时候都被该问题“感动”。不幸的是,了解问题需要对Xerces的历史有一点了解…
历史Xerces是Java生态系统中使用最广泛的XML解析器。几乎所有用Java编写的库或框架都以某种能力使用Xerces(如果不是直接使用,则是透明地使用)。
到目前为止,官方二进制文件中包含的Xerces jar 尚未进行版本控制。例如,Xerces 2.11.0实现jar被命名为xercesImpl.jarnot xercesImpl-2.11.0.jar。
Xerces团队不使用Maven,这意味着他们不将正式发行版上载到Maven Central。
Xerces以前以单个jar(xerces.jar)的形式发布,但被拆分为两个jar,一个包含API(xml-apis.jar),一个包含这些API的实现(xercesImpl.jar)。许多较旧的Maven POM仍声明依赖于xerces.jar。在过去的某个时候,Xerces也发布为xmlParserAPIs.jar,一些较早的POM也依赖于此。
将jar部署到Maven存储库的人分配给xml-apis和xercesImpl jar的版本通常是不同的。例如,即使xml-apis都来自Xerces 2.8.0,也可能会给它们提供1.3.03版,而给xercesImpl提供2.8.0版。这是因为人们经常用实现的规范版本标记xml-apis jar。还有就是这是一个非常不错的,但不完全击穿这里。
更复杂的是,Xerces是XML解析器,用于JRE中包含的XML处理Java API(JAXP)的参考实现中。实现类在com.sun.*名称空间下重新打包,这使得直接访问它们很危险,因为它们在某些JRE中可能不可用。但是,并非所有的Xerces功能都通过java.*和javax.*API 公开;例如,没有API公开Xerces序列化。
令人困惑的是,几乎所有servlet容器(JBoss,Jetty,Glassfish,Tomcat等)都随Xerces一起放在其一个或多个/lib文件夹中。
问题解决冲突由于上述某些(或全部)原因,许多组织在其POM中发布和使用Xerces的自定义版本。如果您的应用程序很小,并且仅使用Maven Central,那么这并不是真正的问题,但是对于Artifactory或Nexus代理多个存储库(JBoss,Hibernate等)的企业软件,这很快就成为一个问题:
由Artifactory代理的xml-apis
例如,组织A可能发布xml-apis为:
<groupId>org.apache.xerces</groupId> <artifactId>xml-apis</artifactId> <version>2.9.1</version>
同时,组织B可能发布与以下内容相同jar的内容:
<groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> <version>1.3.04</version>
尽管B的jar版本比A的版本低jar,但是Maven不知道它们是相同的工件,因为它们具有不同 groupId的。因此,它不能执行冲突解决,并且两个都 jar将作为已解决的依赖项包括在内:
使用多个xml-api解析的依赖关系
类加载器地狱如上所述,JRE在JAXP RI中与Xerces一起提供。将所有Xerces Maven依赖项标记为s或as 会很好,您所依赖的第三方代码可能与您使用的JDK的JAXP中提供的版本兼容或不兼容。另外,您还可以在servlet容器中运送Xerces jars。这给您提供了许多选择:是否删除servlet版本,并希望您的容器在JAXP版本上运行?离开servlet版本更好,希望您的应用程序框架在servlet版本上运行是否更好?如果上面概述的一两个未解决的冲突成功地融入了您的产品(在大型组织中很容易发生),您很快就会陷入类加载器地狱中,想知道该类加载器在运行时选择的是哪个版本的Xerces,是否将在Windows和Linux中选择相同的jar(可能不是)。
解决方案?我们试过标志认证的所有Xerces的Maven依赖作为或作为,但这是给难以执行(尤其是大型团队)的文物有这么多的别名(xml-apis,xerces,xercesImpl,xmlParserAPIs,等)。此外,我们的第三方库/框架可能无法在JAXP版本或servlet容器提供的版本上运行。
我们如何最好地使用Maven解决这个问题?我们是否必须对依赖项进行这种细粒度的控制,然后依靠分层的类加载?是否有某种方法可以全局排除所有Xerces依赖关系,并强制我们所有的框架/库使用JAXP版本?
更新:Joshua Spiewak已将Xerces构建脚本的修补版本上载到XERCESJ-1454,从而可以上载到Maven Central。投票/观看/贡献这个问题,让我们一劳永逸地解决这个问题。