在Java / Maven中处理“Xerces hell”?

在我的办公室里,仅仅提到Xerces这个词就足以煽动开发者的凶悍愤怒.粗略地看一眼其他Xerces关于SO的问题似乎表明,几乎所有Maven用户都会在某个时候“触及”这个问题.不幸的是,理解这个问题需要对Xerces的历史有一点了解……

历史

> Xerces是Java生态系统中使用最广泛的XML解析器.几乎每个用Java编写的库或框架都以某种身份使用Xerces(传递,如果不是直接的话).
>到目前为止,official binaries中包含的Xerces罐子都没有版本化.例如,Xerces 2.11.0实现jar被命名为xercesImpl.jar而不是xercesImpl-2.11.0.jar.
> Xerces团队does not use Maven,这意味着他们没有
上传正式版本至Maven Central.
> Xerces曾经是released as a single jar(xerces.jar),但被分成两个罐子,一个包含API(xml-apis.jar),另一个包含这些API的实现(xercesImpl.jar).许多较旧的Maven POM仍声明对xerces.jar的依赖.在过去的某个时刻,Xerces也被发布为xmlParserAPIs.jar,一些较旧的POM也依赖于它.
>分配给xml-apis和xercesImpl的版本由那些将其jar部署到Maven存储库的人通常是不同的.例如,xml-apis可能是1.3.03版本,而xercesImpl可能是2.8.0版本,即使两者都来自Xerces 2.8.0.这是因为人们经常使用它实现的规范版本来标记xml-apis jar.这个here有一个非常好但不完整的细分.
>更复杂的是,Xerces是JDL中包含的Java API for XML Processing(JAXP)的参考实现中使用的XML解析器.实现类在com.sun.*命名空间下重新打包,这使得直接访问它们很危险,因为它们可能在某些JRE中不可用.但是,并非所有Xerces功能都通过java.*和javax.* API公开;例如,没有API公开Xerces序列化.
>添加到令人困惑的混乱中,几乎所有servlet容器(JBoss,Jetty,Glassfish,Tomcat等)都在一个或多个/ lib文件夹中附带Xerces.

问题

解决冲突

对于某些 – 或者可能是所有 – 上述原因,很多
组织在其中发布和使用Xerces的自定义构建
多金属氧酸盐.如果你有一个小应用程序并且只使用Maven Central,这不是一个真正的问题,但它很快成为企业软件的问题,其中Artifactory或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并不知道
它们是相同的神器,因为它们有不同
组id.因此,它不能同时执行冲突解决
jar将作为已解析的依赖项包含在内:

Classloader Hell

如上所述,JRE在JAXP RI中附带Xerces.虽然将所有Xerces Maven依赖项标记为< exclusion> s或< provided>会很好,但您所依赖的第三方代码可能会也可能不会使用您正在使用的JDK的JAXP中提供的版本.此外,您还可以在servlet容器中附带Xerces jar以进行竞争.这给您留下了许多选择:您是否删除了servlet版本并希望您的容器在JAXP版本上运行?离开servlet版本是否更好,并希望您的应用程序框架在servlet版本上运行?如果上面列出的一个或两个未解决的冲突进入您的产品(很容易在大型组织中发生),您很快就会发现自己处于类加载器地狱,想知道类加载器在运行时选择的Xerces版本以及是否将在Windows和Linux中选择相同的jar(可能不是).

解决方案?

我们已经尝试将所有Xerces Maven依赖项标记为< provided>或者作为< exclusion>,但这很难强制执行(特别是对于大型团队),因为工件有很多别名(xml-apis,xerces,xercesImpl,xmlParserAPIs等).此外,我们的第三方库/框架可能无法在JAXP版本或servlet容器提供的版本上运行.

我们怎样才能最好地解决Maven的这个问题?我们是否必须对依赖关系进行如此细粒度的控制,然后依赖分层类加载?有没有办法全局排除所有Xerces依赖项,并强制我们所有的框架/库使用JAXP版本?

更新:Joshua Spiewak已经将修补版的Xerces构建脚本上传到XERCESJ-1454,允许上传到Maven Central.投票/观看/贡献这个问题,让我们一劳永逸地解决这个问题.

最佳答案
自2013年2月20日起,Maven Central的Xerces有2.11.0 JAR(和源JAR!)!见Xerces in Maven Central.我想知道为什么他们没有解决https://issues.apache.org/jira/browse/XERCESJ-1454

我用过:

<dependency>
    <groupId>xerces</groupId>
    <artifactId>xercesImpl</artifactId>
    <version>2.11.0</version>
</dependency>

并且所有依赖关系都已经解决了 – 甚至是正确的xml-apis-1.4.01!

最重要的(以及过去不明显的) – Maven Central中的JAR与官方Xerces-J-bin.2.11.0.zip发行版中的JAR相同.

然而,我无法找到xml-schema-1.1-beta版本 – 由于其他依赖性,它不能是Maven分类器版本.

转载注明原文:在Java / Maven中处理“Xerces hell”? - 代码日志