如何解决 Maven/Gradle 中的多级间接缺失依赖地狱?

Posted

技术标签:

【中文标题】如何解决 Maven/Gradle 中的多级间接缺失依赖地狱?【英文标题】:How do you resolve several-levels-indirect missing dependency hell in Maven/Gradle? 【发布时间】:2017-07-20 01:51:45 【问题描述】:

我们有一个项目依赖于 Aspose Words 的com.aspose:aspose-words:16.10.0:jdk16

aspose-words 的 POM 声明没有依赖关系,但事实证明这是一个谎言。它实际上使用jai-core,最新版本在javax.media:jai-core:1.1.3

不过,jai-core 的 POM 也存在问题 - 它声明没有依赖关系,但实际上依赖于 jai-codec,它位于 com.sun.media:jai-codec:1.1.3

让这些项目来解决问题似乎不切实际。 JAI 基本上是一个死项目,Maven Central 不知道是谁添加了 POM,因此没有人负责修复元数据。 Aspose 拒绝在没有测试重现的情况下修复问题,即使您可以向他们展示他们自己的代码做错了,即使他们修复了它,他们也会添加对 jai-core:1.1.3 的依赖,这无论如何只能解决一半的问题。

如果我查看整个依赖关系树,这只是问题的一个示例。其他人正在潜伏,被其他依赖链掩盖,巧合地拉动了缺失的依赖。在某些情况下,我们甚至向项目报告了 POM 问题,只是让他们说依赖“不是真实的”,尽管他们的类明确引用了另一个库中的类。

我能想到几个同样尴尬的选择:

创建jai-core:1.1.3.1aspose-words:16.10.0.1 并修复它们的POM 以包含缺少的依赖项,但是将来更新它们的人都必须做同样的事情。另外,我不知道哪个恰好依赖于jai-core 的任何其他库也必须更新。 从我们自己的项目中添加一个依赖项,即使它确实不是一个。 为现在存在的版本编辑 POM 以直接解决问题,唯一需要注意的是人们可能缓存了错误的版本。

所以我想我有两个相关的问题:

没有适当的方法可以解决这个问题吗?似乎任何非玩具项目最终都会遇到这个问题,因此没有明显正确的方法来处理它令人担忧。 有没有办法阻止不正确的依赖元数据首先进入工件服务器?这有点失控了,因为团队中的其他开发人员正在添加依赖项而没有正确检查事情,然后当一年后出现问题时,我不得不清理他们的错误。

【问题讨论】:

如果使用了特定的依赖项,您可以使用 Enforcer 插件使构建失败……但每个库都由其团队维护。如果他们拒绝修复,那么 fork 并自己修复是要走的路。这确实意味着您必须定期将新添加的原始内容合并到您自己的分叉中。但如果它无论如何都死了……就不会有任何东西了。但是我认为 Aspose 不是开源的?所以无论如何都可能存在许可问题。另一种解决方案:创建一个包装器 POM,依赖于 Aspose 及其所需的每个库,然后依赖于这个包装器 POM。 请阅读additional dependencies of Aspose.Words。您能否分享您的用例的完整细节?然后,我将为您提供有关您的查询的更多信息。我与 Aspose 合作,担任开发人员宣传员。 @TahirManzoor 在这种特殊情况下,我们使用 Aspose 将 DOC 转换为 PDF。一个 DOC 碰巧包含一个 BMP,出于某种原因,Aspose 使用 JAI 来读取 BMP。这似乎是一个遗留问题,因为我无法获得现代版本的 Word 来创建此类文档,所以我正在等待有关哪个 Word 版本创建它的更多信息,以便我可以使用该版本挖掘 VM并尝试制作一个测试文件。 【参考方案1】:

Tunaki 已经给出了很多好的方法。让我添加以下内容:

我们不得不处理许多遗留 jar,它们是 MavenCentral 上现有 jar 的一些旧版本或奇怪版本。我们给了他们一个特殊的版本号(比如 1.2.3-companyname),并为他们创建了一个符合我们目的的 POM。这或多或少是您的第一个“尴尬选择”。在你的情况下,这就是我想要的;另外,我会在 dependencyManagement 中定义版本,这样 Maven 依赖中介就不会将其设置为其他版本。

如果您的 jar 有新版本出现,您可以检查它是否仍然存在相同的问题(如果他们进行了正确的 Maven 构建,他们应该在 POM 中包含所有依赖项)。如果是这样,您需要再次修复它。

我不会为已经存在的版本更改 pom,因为它会使人们感到困惑并且可能导致不一致的问题,因为如果旧版本已经在本地存储库中,Maven 将不会获取新的 POM。如果您要管理的项目很少,那么您可以选择将依赖项添加到您自己的项目中,这样您仍然可以看到正在发生的事情(对 POM 中的依赖项进行适当的注释可以使其更清晰)。

【讨论】:

【参考方案2】:

JAI 对于 Aspose.Words for Java 是可选的。 Aspose.Words for Java 仅在可用时才使用 JAI 图像编码器和解码器。如果没有 JAI,它也可以正常工作。

编解码器补充了标准 java ImageIO 编码器/解码器。最显着的新增功能是对 Tiff 的支持。

JAI(Java 高级成像)不是常用的库。首先 - 它是本机库。 IE。它对不同的平台有单独的分布。它还具有“可移植的”纯 Java 分布式,但如果您想要 JAI 的全部功能 - 您应该坚持使用本机选项。

另一件事:通常您应该在主机系统上运行 JAI 本地分发的安装。 IE。它像桌面应用程序一样安装,而不像通常的 java 库。同样,JAI 编解码器的行为与通常的库不同:如果它安装在系统上 - 它将插入 ImageIO,与类路径无关。

所以,我不知道使用 Maven 安装 JAI 的好方法 - 就像使用 Maven 安装 Skype 或任何其他桌面应用程序一样。但恕我直言,我不是 Maven 方面的专家:)

【讨论】:

在这种特殊情况下,它使用 JAI 来读取 BMP,因为文档恰好包含一个 BMP。如果您没有 JAI,则尝试将此类文档保存为 PDF 时会失败。所以“它会正常工作”有点误导......只有当你没有碰巧遇到一个包含 BMP 的文档时它才会正常工作。而且您无法提前知道您收到的文件是否会引发问题。 它是否插入“红十字”图像而不是不支持/损坏的图像?如果是 - 没关系。无论如何,您最好在 Aspose.Words 支持论坛 aspose.com/community/forums/aspose.words-product-family/75/… 上提问。可能您的系统可以在没有 JAI 的情况下加载您的 BMP 类型 - 在这种情况下,这是一个错误。 它根本不会生成 PDF,因为您遇到了失败。我们确实已经在论坛上发布了有关它的信息,但他们要求提供样本。也没有人会给我们样本,而且 Aspose 本身不能用于创建包含 BMP 的文档,因为它们会自动将其转换为 PNG。 “询问样本” - 是一种标准做法 - 他们应该重现您的错误以修复它。 PDF 不支持 BMP,因此应将 BMP 转换为其他格式 - PNG 可以。 不,我的意思是它不能将 BMP 插入 DOC。显然,DOC 可以本地存储 BMP 文件,因为 BMP 文件的存在会导致问题。问题是我无法使用他们的库创建示例数据,并且向我们报告问题的人也拒绝交出他们的文档。 ://

以上是关于如何解决 Maven/Gradle 中的多级间接缺失依赖地狱?的主要内容,如果未能解决你的问题,请参考以下文章

Intellij 处理混合项目(maven+gradle)

如何获得命题逻辑中的“间接蕴涵”

Android Gradle 本地化部署 maven

Android Gradle 本地化部署 maven

如何通过命令行运行Maven / Gradle Web项目?

如何将 Eclipse 项目文件夹结构更改为 Maven/Gradle 结构