在我的办公室里,仅仅提到Xerces这个词,就足以激起开发人员的杀气。粗略浏览SO上其他Xerces的问题似乎表明,几乎所有的Maven用户都在某个时候被这个问题“触动”过。不幸的是,理解这个问题需要了解Xerces的历史……
Xerces是Java生态系统中使用最广泛的XML解析器,几乎所有用Java编写的库或框架都以某种方式使用Xerces(传递,如果不是直接的话)。
官方二进制文件中包含的Xerces jar至今尚未版本化。例如,Xerces 2.11.0实现jar名为xercesImpl.jar
而不是xercesImpl-2.11.0.jar
。
Xerces队不使用Maven,这意味着他们没有将正式版本上传到MavenCentral。
Xerces曾经是作为一个罐子释放(xerces.jar
),但被分成两个罐子,一个包含API(xml-apis.jar
),另一个包含这些API的实现(xercesImpl.jar
)。许多较旧的Maven POM仍然声明依赖于xerces.jar
。在过去的某个时候,Xerces也作为xmlParserAPIs.jar
发布,一些较旧的POM也依赖于它。
将jars部署到Maven存储库的人分配给xml-apis和xercesImpl jar的版本通常是不同的。例如,xml-apis的版本可能是1.3.03,xercesImpl的版本可能是2.8.0,尽管两者都来自Xerces 2.8.0。这是因为人们经常用它实现的规范版本标记xml-apis jar。这个这里有一个非常好但不完整的细分。
更复杂的是,Xerces是包含在JRE中的XML处理JavaAPI(JAXP)的参考实现中使用的XML解析器。实现类被重新打包在com.sun.*
命名空间下,这使得直接访问它们变得危险,因为它们可能在某些JRE中不可用。然而,并非所有Xerces功能都通过java.*
和javax.*
API公开;例如,没有公开Xerces序列化的API。
除了混乱之外,几乎所有的servlet容器(JBoss、Jetty、Glassfish、Tomcat等)都在一个或多个/lib
文件夹中附带Xerces。
由于上述原因中的某些-或所有-,许多组织发布和使用Xerce的自定义构建POM。如果您有一个小型应用程序并且只使用Maven Central,这并不是一个真正的问题,但对于Arti工厂或Nexus代理多个存储库(JBoss、Hibernate等)的企业软件来说,这很快就会成为一个问题:
例如,组织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
将作为已解决的依赖项包含:
如上所述,JRE在JAXP RI中随Xerces一起提供。虽然将所有Xerces Maven依赖项标记为<exclusion>
或<provided>
会很好,但您依赖的第三方代码可能适用于也可能不适用于您正在使用的JDK的JAXP中提供的版本。此外,您需要应对servlet容器中提供的Xerces jar。这为您留下了许多选择:您是否删除servlet版本并希望您的容器在JAXP版本上运行?是否最好保留servlet版本,并希望您的应用程序框架在servlet版本上运行?如果上面列出的一两个未解决的冲突设法进入你的产品(在大型组织中很容易发生),你很快就会发现自己陷入了类加载器的地狱,想知道类加载器在运行时选择的是哪个版本的Xerces,以及它是否会在Windows和Linux中选择相同的jar(可能不会)。
我们尝试将所有Xerces Maven依赖项标记为<provided>
或<exclusion>
,但这很难强制执行(尤其是在大型团队中),因为工件有很多别名(xml-apis
、xerces
、xercesImpl
、xmlParserAPIs
等)。此外,我们的第三方lib/框架可能无法在JAXP版本或servlet容器提供的版本上运行。
我们如何用Maven最好地解决这个问题?我们必须对我们的依赖进行如此细粒度的控制,然后依赖分层类加载吗?有没有办法全局排除所有Xerces依赖,并强制我们所有的框架/库使用JAXP版本?
更新:Joshua Spiewak已将Xerces构建脚本的修补版本上传到XERCESJ-1454,允许上传到Maven Central。投票/观看/贡献此问题,让我们一劳永逸地解决此问题。