涉及JAR中涉及MANIFEST.MF类路径的Maven构建失败

时间:2017-01-30 20:35:47

标签: java maven maven-3

首先,我是StackOverflow的长期用户(和受益人),但这是我的第一个问题。我已经对这个主题进行了大量的搜索,但是我发现的大部分文章都谈到了生成JAR文件,而不是使用Maven Central仓库中的第三方JAR,我真的没有权力修复它。我见过的几个解决方案并不是真的可以接受。

问题是,Maven Central存储库中的大多数jaxb JAR都包含指向依赖项的类路径条目(在MANIFEST.MF文件中),并且这些依赖项是使用相对路径指定的 - 通常假设依赖条。 jar与foo.jar存在于同一目录中。

例如,如果您在单个lib目录中拥有所有JAR依赖项,那么这很好。但是:

  • Maven希望维护自己的本地存储库,因此每个打包的JAR都存在于自己的目录中(每个版本都在一个单独的子目录中)。
  • Maven JAR通常使用文件名中嵌入的版本信息命名,而MANIFEST.MF中的类路径条目仅使用基本文件名(无版本)指定依赖项。

最终结果是这样的错误消息:

  

[错误]坏路径元素   “C:\用户\ rpoole \ .m2目录\库\ COM \太阳\ XML \绑定\ JAXB的IMPL \ 2.2.11 \ JAXB-core.jar添加”:   没有这样的文件或目录

一种解决方案是编写脚本或小应用程序来浏览所有JAR,并从嵌入的MANIFEST.MF文件中删除类路径信息。但这不是很干净,在进行实际构建之前需要额外的步骤。

另一个可能的解决方案是,一些较新发布的JAR版本已经解决了这个类路径问题,因此使用最新和最好的。不幸的是,我正在开发的这个应用程序是遗留的,并且正在为第三方开发,因此我无法更新某个版本之外的依赖项。到目前为止,我所研究的所有jaxb JAR似乎都存在问题。

有没有办法告诉Maven忽略JAR中的嵌入式类路径,只依赖于Maven自己的依赖解析?我已经尝试过重新排序依赖项之类的东西,但这不起作用(或将构建问题从一个子项目转移到另一个子项目)。

另外一个烦恼:我们有一个“幸运的”Maven回购似乎让构建完成没有任何问题,但到目前为止,我一直无法弄清楚为什么这个特定的JAR集合构建好。我怀疑有人可能已经进入并手动调整了一些JAR或POM,但是信息量很少,差异工具并没有太多帮助。

无论如何,项目从头开始构建。

如果我可以在pom.xml中为子项目指定一个类似于排除块的东西,那就更好了,但是用于处理JAR的嵌入式类路径而不是Maven自己的传递依赖项(由groupId / artifactId指定)。

编辑:显然,有些人认为这是不可能的,Maven会忽略Manifest.MF中的Class-Path条目。但是,这是一个已知问题,如this StackOverflow article中所述。还有another good article,它解释了一些更好的历史。

问题是我不能通过JAR并在构建过程中编辑每个上的MANIFEST.MF文件。即使通过脚本自动化,这也不是一种实用的方法。我需要一个实际上适用于已经在生产中的代码的解决方案。这些问题在相关JAR的更高版本中被推测修复,但我可能无法使用这些版本的更新版本。

此外,建议的修复之一是将-Xlint:-path添加到编译器args,这会抑制错误消息。然而,对于我来说,构建只是在另一个方面失败,所以乍一看这似乎也不是一个好的解决方案。我将再次尝试这个,因为根据this,POM文件中的编译器参数的语法有点不稳定。

2 个答案:

答案 0 :(得分:1)

我讨厌回答我自己的问题,但我终于设法解决了这个问题。对于那些坚持认为Maven构建可能不会受到jar的MANIFEST.MF中的Class-Path条目影响的人,请阅读Michael Bayne的this article。它很好地总结了问题和解决方案。提示:javac当然关心jar中的嵌入式类路径。

诀窍是将-Xlint:-path添加到编译器参数中,尽管我最初对此解决方案持怀疑态度。这样做会抑制错误的路径元素警告/错误,因此Maven不会过早停止构建。我遇到的问题是找出在pom.xml中嵌入这些参数的正确语法。这就是this article派上用场的地方。因此,编译器插件的配置必须如此正确理解:

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>${java-version}</source>
            <target>${java-version}</target>
            <compilerArguments>
                <Xlint/>
                <Xlint:-path/>
            </compilerArguments>
            <showWarnings>true</showWarnings>
            <showDeprecation>true</showDeprecation>
        </configuration>
    </plugin>
</plugins>

请注意,这种语法不是很好的XML(正如Bayne指出的那样),并且大多数IDE会将第二个Xlint行标记为错误,但它可以与Maven一起使用。使用某些Maven教程中给出的语法可能会导致参数根本没有传递给编译器,或者只传递传递的最后一个参数。

一旦解决了这个问题,您可能会发现其他构建问题(我当然也会这样做),但至少这些问题不会再被隐藏起来了。

答案 1 :(得分:0)

问题在于您引用的是七年前的帖子..并且不使用maven-compiler-plugin的更新版本:

javac compiler的参数可以更好地完成:

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.6.1</version>
        <configuration>
          <compilerArgs>
            <arg>-Xlint</arg>
            <arg>-Xlint:-path</arg>
          </compilerArgs>
        </configuration>
      </plugin>
    </plugins>
    [...]
  </build>
  [...]
</project>