本文翻译自:Dealing with “Xerces hell” in Java/Maven?

In my office, the mere mention of the word Xerces is enough to incite murderous rage from developers. 在我的办公室里,仅仅提到Xerces这个词就足以煽动开发者的凶悍愤怒。 A cursory glance at the other Xerces questions on SO seem to indicate that almost all Maven users are "touched" by this problem at some point. 粗略地看一眼其他Xerces关于SO的问题似乎表明,几乎所有Maven用户都会在某个时候“触及”这个问题。 Unfortunately, understanding the problem requires a bit of knowledge about the history of Xerces... 不幸的是,理解这个问题需要对Xerces的历史有一点了解......

History 历史

  • Xerces is the most widely used XML parser in the Java ecosystem. Xerces是Java生态系统中使用最广泛的XML解析器。 Almost every library or framework written in Java uses Xerces in some capacity (transitively, if not directly). 几乎每个用Java编写的库或框架都以某种身份使用Xerces(传递,如果不是直接的话)。

  • The Xerces jars included in the official binaries are, to this day, not versioned. 包含在官方二进制文件中的Xerces罐子直到今天还没有版本化。 For example, the Xerces 2.11.0 implementation jar is named xercesImpl.jar and not xercesImpl-2.11.0.jar . 例如,Xerces 2.11.0实现jar被命名为xercesImpl.jar而不是xercesImpl-2.11.0.jar

  • The Xerces team does not use Maven , which means they do not upload an official release to Maven Central . Xerces团队不使用Maven ,这意味着他们不会将正式版本上传到Maven Central 。

  • Xerces used to be released as a single jar ( xerces.jar ), but was split into two jars, one containing the API ( xml-apis.jar ) and one containing the implementations of those APIs ( xercesImpl.jar ). Xerces曾经作为单个jar ( xerces.jar )发布,但被分成两个jar,一个包含API( xml-apis.jar ),另一个包含这些API的实现( xercesImpl.jar )。 Many older Maven POMs still declare a dependency on xerces.jar . 许多较旧的Maven POM仍声明对xerces.jar的依赖。 At some point in the past, Xerces was also released as xmlParserAPIs.jar , which some older POMs also depend on. 在过去的某个时刻,Xerces也被发布为xmlParserAPIs.jar ,一些较旧的POM也依赖于它。

  • The versions assigned to the xml-apis and xercesImpl jars by those who deploy their jars to Maven repositories are often different. 分配给xml-apis和xercesImpl的版本由那些将其jar部署到Maven存储库的人通常是不同的。 For example, xml-apis might be given version 1.3.03 and xercesImpl might be given version 2.8.0, even though both are from Xerces 2.8.0. 例如,xml-apis可能是1.3.03版本,而xercesImpl可能是2.8.0版本,即使两者都来自Xerces 2.8.0。 This is because people often tag the xml-apis jar with the version of the specifications that it implements. 这是因为人们经常使用它实现的规范版本来标记xml-apis jar。 There is a very nice, but incomplete breakdown of this here . 还有就是这是一个非常不错的,但不完全击穿这里 。

  • To complicate matters, Xerces is the XML parser used in the reference implementation of the Java API for XML Processing (JAXP), included in the JRE. 更复杂的是,Xerces是包含在JRE中的Java API for XML Processing(JAXP)的参考实现中使用的XML解析器。 The implementation classes are repackaged under the com.sun.* namespace, which makes it dangerous to access them directly, as they may not be available in some JREs. 实现类在com.sun.*命名空间下重新打包,这使得直接访问它们很危险,因为它们可能在某些JRE中不可用。 However, not all of the Xerces functionality is exposed via the java.* and javax.* APIs; 但是,并非所有Xerces功能都通过java.*javax.* API公开; for example, there is no API that exposes Xerces serialization. 例如,没有API公开Xerces序列化。

  • Adding to the confusing mess, almost all servlet containers (JBoss, Jetty, Glassfish, Tomcat, etc.), ship with Xerces in one or more of their /lib folders. 添加到令人困惑的混乱中,几乎所有servlet容器(JBoss,Jetty,Glassfish,Tomcat等)都在一个或多个/lib文件夹中附带Xerces。

Problems 问题

Conflict Resolution 解决冲突

For some -- or perhaps all -- of the reasons above, many organizations publish and consume custom builds of Xerces in their POMs. 对于上述某些原因(或许是全部原因),许多组织在其POM中发布和使用Xerces的自定义构建。 This is not really a problem if you have a small application and are only using Maven Central, but it quickly becomes an issue for enterprise software where Artifactory or Nexus is proxying multiple repositories (JBoss, Hibernate, etc.): 如果你有一个小应用程序并且只使用Maven Central,这不是一个真正的问题,但它很快成为企业软件的问题,其中Artifactory或Nexus代理多个存储库(JBoss,Hibernate等):

For example, organization A might publish xml-apis as: 例如,组织A可能会将xml-apis发布为:

<groupId>org.apache.xerces</groupId>
<artifactId>xml-apis</artifactId>
<version>2.9.1</version>

Meanwhile, organization B might publish the same jar as: 同时,组织B可能会发布相同的jar

<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.3.04</version>

Although B's jar is a lower version than A's jar , Maven does not know that they are the same artifact because they have different groupId s. 虽然B的jar是比A的jar更低的版本,但Maven并不知道它们是相同的工件,因为它们有不同的groupId Thus, it cannot perform conflict resolution and both jar s will be included as resolved dependencies: 因此,它无法执行冲突解决,并且两个jar都将作为已解析的依赖项包含在内:

Classloader Hell Classloader Hell

As mentioned above, the JRE ships with Xerces in the JAXP RI. 如上所述,JRE在JAXP RI中附带Xerces。 While it would be nice to mark all Xerces Maven dependencies as <exclusion> s or as <provided> , the third-party code you depend on may or may not work with the version provided in JAXP of the JDK you're using. 虽然将所有Xerces Maven依赖项标记为<exclusion><provided>会很好,但您所依赖的第三方代码可能会也可能不会与您正在使用的JDK的JAXP中提供的版本一起使用。 In addition, you have the Xerces jars shipped in your servlet container to contend with. 此外,您还可以在servlet容器中附带Xerces jar以进行竞争。 This leaves you with a number of choices: Do you delete the servlet version and hope that your container runs on the JAXP version? 这给您留下了许多选择:您是否删除了servlet版本并希望您的容器在JAXP版本上运行? Is it better to leave the servlet version, and hope that your application frameworks run on the servlet version? 离开servlet版本是否更好,并希望您的应用程序框架在servlet版本上运行? If one or two of the unresolved conflicts outlined above manage to slip into your product (easy to happen in a large organization), you quickly find yourself in classloader hell, wondering which version of Xerces the classloader is picking at runtime and whether or not it will pick the same jar in Windows and Linux (probably not). 如果上面列出的一个或两个未解决的冲突进入您的产品(很容易在大型组织中发生),您很快就会发现自己处于类加载器地狱,想知道类加载器在运行时选择的Xerces版本以及是否将在Windows和Linux中选择相同的jar(可能不是)。

Solutions? 解决方案?

We've tried marking all Xerces Maven dependencies as <provided> or as an <exclusion> , but this is difficult to enforce (especially with a large team) given that the artifacts have so many aliases ( xml-apis , xerces , xercesImpl , xmlParserAPIs , etc.). 我们已经尝试将所有Xerces Maven依赖项标记为<provided><exclusion> ,但这很难强制执行(特别是对于大型团队),因为工件有很多别名( xml-apisxercesxercesImplxmlParserAPIs等)。 Additionally, our third party libs/frameworks may not run on the JAXP version or the version provided by a servlet container. 此外,我们的第三方库/框架可能无法在JAXP版本或servlet容器提供的版本上运行。

How can we best address this problem with Maven? 我们怎样才能最好地解决Maven的这个问题? Do we have to exercise such fine-grained control over our dependencies, and then rely on tiered classloading? 我们是否必须对依赖关系进行如此细粒度的控制,然后依赖分层类加载? Is there some way to globally exclude all Xerces dependencies, and force all of our frameworks/libs to use the JAXP version? 有没有办法全局排除所有Xerces依赖项,并强制我们所有的框架/库使用JAXP版本?


UPDATE : Joshua Spiewak has uploaded a patched version of the Xerces build scripts to XERCESJ-1454 that allows for upload to Maven Central. 更新 :Joshua Spiewak已将Xerces构建脚本的修补版本上传到XERCESJ-1454 ,允许上传到Maven Central。 Vote/watch/contribute to this issue and let's fix this problem once and for all. 投票/观看/贡献这个问题,让我们一劳永逸地解决这个问题。


#1楼

参考:https://stackoom.com/question/mzrw/在Java-Maven中处理-Xerces-hell


#2楼

I guess there is one question you need to answer: 我想你需要回答一个问题:

Does there exist a xerces*.jar that everything in your application can live with? 是否存在xerces * .jar,应用程序中的所有内容都可以使用?

If not you are basically screwed and would have to use something like OSGI, which allows you to have different versions of a library loaded at the same time. 如果不是,你基本上搞砸了,并且必须使用像OSGI这样的东西,它允许你同时加载不同版本的库。 Be warned that it basically replaces jar version issues with classloader issues ... 请注意,它基本上用类加载器问题替换jar版本问题......

If there exists such a version you could make your repository return that version for all kinds of dependencies. 如果存在这样的版本,您可以使您的存储库为所有类型的依赖项返回该版本。 It's an ugly hack and would end up with the same xerces implementation in your classpath multiple times but better than having multiple different versions of xerces. 这是一个丑陋的黑客攻击,并且会在你的类路径中多次使用相同的xerces实现,但是比拥有多个不同版本的xerces更好。

You could exclude every dependency to xerces and add one to the version you want to use. 您可以将每个依赖项排除在xerces之外,并将一个依赖项添加到要使用的版本中。

I wonder if you can write some kind of version resolution strategy as a plugin for maven. 我想知道你是否可以编写某种版本解析策略作为maven的插件。 This would probably the nicest solution but if at all feasible needs some research and coding. 这可能是最好的解决方案,但如果可行则需要一些研究和编码。

For the version contained in your runtime environment, you'll have to make sure it either gets removed from the application classpath or the application jars get considered first for classloading before the lib folder of the server get considered. 对于运行时环境中包含的版本,您必须确保从应用程序类路径中删除它,或者在考虑服务器的lib文件夹之前首先考虑应用程序jar进行类加载。

So to wrap it up: It's a mess and that won't change. 所以把它包起来:这是一团糟,不会改变。


#3楼

坦率地说,我们遇到的几乎所有东西都适用于JAXP版本,所以我们总是排除 xml-apisxercesImpl


#4楼

You could use the maven enforcer plugin with the banned dependency rule. 您可以将maven enforcer插件与禁止的依赖关系规则一起使用。 This would allow you to ban all the aliases that you don't want and allow only the one you do want. 这将允许您禁止所有您不想要的别名,并且只允许您想要的那些别名。 These rules will fail the maven build of your project when violated. 违反时,这些规则将使项目的maven构建失败。 Furthermore, if this rule applies to all projects in an enterprise you could put the plugin configuration in a corporate parent pom. 此外,如果此规则适用于企业中的所有项目,则可以将插件配置放在公司父pom中。

see: 看到:

  • http://maven.apache.org/plugins/maven-enforcer-plugin/ http://maven.apache.org/plugins/maven-enforcer-plugin/
  • http://maven.apache.org/enforcer/enforcer-rules/bannedDependencies.html http://maven.apache.org/enforcer/enforcer-rules/bannedDependencies.html

#5楼

There are 2.11.0 JARs (and source JARs!) of Xerces in Maven Central since 20th February 2013! 自2013年2月20日起,Maven Central的Xerces有2.11.0 JAR (和源JAR!) See Xerces in Maven Central . 参见Maven Central的Xerces 。 I wonder why they haven't resolved https://issues.apache.org/jira/browse/XERCESJ-1454 ... 我想知道为什么他们没有解决https://issues.apache.org/jira/browse/XERCESJ-1454 ...

I've used: 我用过:

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

and all dependencies have resolved fine - even proper xml-apis-1.4.01 ! 并且所有依赖关系都已经解决了 - 甚至是正确的xml-apis-1.4.01

And what's most important (and what wasn't obvious in the past) - the JAR in Maven Central is the same JAR as in the official Xerces-J-bin.2.11.0.zip distribution . 最重要的(以及过去不明显的) - Maven Central中的JAR与官方Xerces-J-bin.2.11.0.zip发行版中的JAR相同 。

I couldn't however find xml-schema-1.1-beta version - it can't be a Maven classifier -ed version because of additional dependencies. 然而,我无法找到xml-schema-1.1-beta版本 - 由于其他依赖性,它不能是Maven classifier -ed版本。


#6楼

What would help, except for excluding, is modular dependencies. 除了排除外,有用的是模块化依赖。

With one flat classloading (standalone app), or semi-hierarchical (JBoss AS/EAP 5.x) this was a problem. 使用一个平面类加载(独立应用程序)或半分层(JBoss AS / EAP 5.x)这是一个问题。

But with modular frameworks like OSGi and JBoss Modules , this is not so much pain anymore. 但是对于像OSGi和JBoss Modules这样的模块化框架,这不再那么痛苦了。 The libraries may use whichever library they want, independently. 图书馆可以独立使用他们想要的任何图书馆。

Of course, it's still most recommendable to stick with just a single implementation and version, but if there's no other way (using extra features from more libs), then modularizing might save you. 当然,最好只推荐一个实现和版本,但如果没有其他办法(使用更多库中的额外功能),那么模块化可能会省去你。

A good example of JBoss Modules in action is, naturally, JBoss AS 7 / EAP 6 / WildFly 8 , for which it was primarily developed. JBoss模块运行的一个很好的例子当然是JBoss AS 7 / EAP 6 / WildFly 8 ,它主要是为它开发的。

Example module definition: 示例模块定义:

<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.jboss.msc"><main-class name="org.jboss.msc.Version"/><properties><property name="my.property" value="foo"/></properties><resources><resource-root path="jboss-msc-1.0.1.GA.jar"/></resources><dependencies><module name="javax.api"/><module name="org.jboss.logging"/><module name="org.jboss.modules"/><!-- Optional deps --><module name="javax.inject.api" optional="true"/><module name="org.jboss.threads" optional="true"/></dependencies>
</module>

In comparison with OSGi, JBoss Modules is simpler and faster. 与OSGi相比,JBoss模块更简单,更快捷。 While missing certain features, it's sufficient for most projects which are (mostly) under control of one vendor, and allow stunning fast boot (due to paralelized dependencies resolving). 虽然缺少某些功能,但对于大多数(一般)在一个供应商的控制下的项目来说,它足够了,并允许惊人的快速启动(由于并行的依赖关系解决)。

Note that there's a modularization effort underway for Java 8 , but AFAIK that's primarily to modularize the JRE itself, not sure whether it will be applicable to apps. 请注意, Java 8正在进行模块化工作 ,但AFAIK主要用于模块化JRE本身,不确定它是否适用于应用程序。

在Java / Maven中处理“Xerces hell”?相关推荐

  1. java maven 读写pdf_Java 在PDF中加盖骑缝章

    骑缝章是用于往来业务合同,以确保合同真实.有效的印章加盖方法,是一种防范风险的重要方式.在Java程序中,可以通过使用工具来辅助加盖这种骑缝章. 工具:Free Spire.PDF for Java ...

  2. 【狂人小白】如何将Java项目发布到Maven中

    将Java项目发布到Maven中 如何通过Sonatype进行发布Maven操作,并且能够在http://search.maven.org 中搜索到 关键步骤: 1. 申请OSS账号 2. 通过gpg ...

  3. java程序中执行maven_java – 将一个enviornment变量传递给Maven中的已执行进程

    我一直在墙上撞了大约一个小时:我正试图将一个简单的属性( java.library.path)传递给exec-maven-plugin.目标是将其与Netbeans右键单击文件集成>运行文件过程 ...

  4. maven 对于java的要求_如何在Maven中表达对Java EE功能的依赖以过渡到Java 9?

    该模块系统讲的无名模块作为在从类路径加载应用的情况下构建模块图的方式.此外,从文档本身来看: 当编译器在未命名模块中编译代码,或者调用Java启动程序并将应用程序的主类从类路径加载到应用程序类加载器的 ...

  5. Jenkins+maven+SVN构建java项目中遇到的问题及解决

    Jenkins+maven+SVN构建java项目中遇到的问题及解决 参考文章: (1)Jenkins+maven+SVN构建java项目中遇到的问题及解决 (2)https://www.cnblog ...

  6. 运行java maven项目提醒 -SNAPSHOT.jar中没有主清单属性(maven项目指定主类)

    运行java maven项目提醒 -SNAPSHOT.jar中没有主清单属性 问题描述 在运行使用maven打包的项目之后,运行项目发现主类没有找到.提示XXX–1.0-SNAPSHOT.jar中没有 ...

  7. jsp项目在idea需要导入什么依赖_idea中的java web项目(添加jar包介绍)和java maven web项目目录结构...

    java web项目 web项目下web根目录名称是可以更改的 idea中新建java web项目,默认src为Sources Root,当然也可以手动改,在Sources Root下右键只能新建Pa ...

  8. java http url 401 unauthorized_java - 为什么我在Maven中收到“401 Unauthorized”错误?

    为什么我在Maven中收到"401 Unauthorized"错误? 这是我在调用mvn deploy -e(底部的完整日志)时遇到的错误: mvn deploy -e mvn d ...

  9. 你还在 Java 代码中写 set/get 方法?赶快试试这款插件吧!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:Mr.ml https://blog.csdn.net/Ma ...

最新文章

  1. 如何在 InfoPath 2003 表单中动态加载数据
  2. java中的快速生成代码
  3. 没用调用flush导致的数据保存丢失
  4. 【.NET深呼吸】基础:自定义类型转换
  5. 「LibreOJ Round #11」Misaka Network 与求和(杜教筛 + Min_25)
  6. 如何看计算机几核,windows7系统怎么看CPU是几核的?win7查看CPU是几核的方法
  7. MySQL--timestamp类型字段的CURRENT_TIMESTAMP与ON UPDATE CURRENT_TIMESTAMP属性
  8. js删除字符串的最后一个字符几种方法
  9. C# 从文本列中检索数据
  10. MATLAB图像分割实验代码及运行结果
  11. Java短视频直播APP源码
  12. php图书馆占座系统代码,PHP图书馆管理系统(源码+数据库脚本+截图)
  13. 自己动手来做一寸或两寸照片(使用工具)
  14. 英文数据集txt_【美股量化07篇】Python获取标普500成分股数据
  15. Xcode运行报错The operation couldn’t be completed.
  16. 华为云ecs服务器镜像上传到容器镜像服务SWR
  17. 以红酒数据集分类为例做决策树的可视化
  18. 从GIS地图到前端页面展示-简述(QGIS+GeoServer+Tomcat+OpenLayers)
  19. Web前端面试指导(五):掌握面试技巧,让面试变得轻松
  20. window.open()跳转新页面访问不了,但是单独访问这些地址则正常

热门文章

  1. python中处理命令行参数命令getopt
  2. go语言最好的帮助在哪里?
  3. 看我72变:解决Entity Framework中枚举类型与tinyint的映射问题
  4. Windows8中离线安装.Net 3.5的方法
  5. 基于PHP构建OAuth 2.0 认证平台
  6. Java4Android视频笔记
  7. 47 Majority Element II
  8. [UI]抽屉菜单DrawerLayout分析(三)
  9. [ckeditor系列]CKeditor自定义上传图片功能
  10. Net设计模式实例之观察者模式(Observer Pattern)