【问题标题】:Maven: pin dependency version where dependency is managed by a BOMMaven:pin 依赖版本,其中依赖由 BOM 管理
【发布时间】:2018-04-01 02:21:40
【问题描述】:

我们使用Maven BOM 来管理一套库的依赖关系。 BOM 的dependencyManagement 部分通常使用版本范围来指定这些库的版本,例如,[2.0,2.1)Child pom.xml 使用 BOM 不指定这些托管依赖项的版本。 (编辑澄清:我们对第三方依赖项使用特定版本,范围用于正在开发的内部库,其中版本可以快速更改。我们定义版本范围以确保这些库之间的广泛兼容性,即都在同一个主要版本。)

(请注意,这不是一个多模块项目。使用 BOM 机制的库和服务项目只需将其声明为父项并从 Nexus 存储库中提取它。它们不是一起构建的。 )

我们还有一些构建系统脚本,它们使用versions:resolve-ranges 来固定出现在我们的库和服务 pom.xml(不是 BOM 的 pom.xml)中的依赖项版本。这些具有已解析范围的 pom.xml 被签入到源代码管理并标记,因此如果我们需要将部署回滚到早期版本,我们可以使用该标记的 pom.xml 来构建使用相同依赖项版本的构建原始构建,即使现在可以使用更新版本的依赖项(因此如果我们重新运行它,resolve-ranges 会提供更新版本)。

我刚刚注意到这两种机制不能很好地协同工作。在库或服务 pom.xml 上运行 versions:resolve-ranges 只会解析该 pom.xml 中的范围。依赖管理下的版本仍未指定,所以如果我们使用这个 pom.xml 进行新构建,我们将在构建时获得范围内的最新依赖版本。不是我们想要的!

有没有办法使用versions:resolve-ranges(或任何其他插件或技术)来解析托管版本并将它们粘贴到子 pom.xml 中?

这是一个人为的例子。

物料清单:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.maventest</groupId>
    <artifactId>myproject</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>myproject</name>
    <url>http://maven.apache.org</url>
    <dependencyManagement>
       <dependencies>
          <dependency>
             <groupId>commons-lang</groupId>
             <artifactId>commons-lang</artifactId>
             <version>[2.0, 2.3]</version>
          </dependency>
       </dependencies>
    </dependencyManagement>
</project>

使用 BOM 的子项目(一个托管依赖项,一个非托管依赖项):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <parent>
    <groupId>com.maventest</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../myproject/pom.xml</relativePath>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.maventest</groupId>
  <artifactId>mytest</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>mytest</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <scope>compile</scope>
   </dependency>
   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>[3.8, 3.9)</version>
     <scope>test</scope>
   </dependency>
  </dependencies>
</project>

来自mvn dependency:tree 的片段显示了依赖项的有效版本:

[INFO] com.maventest:mytest:jar:1.0-SNAPSHOT

[INFO] +- commons-lang:commons-lang:jar:2.3:compile

[INFO] \- junit:junit:jar:3.8.2-brew:test

mvn versions:resolve-ranges 之后来自 mytest pom.xml 的依赖部分:

<dependencies>
  <dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <scope>compile</scope>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>3.8.2-brew</version>
    <scope>test</scope>
  </dependency>
</dependencies>

因此,如预期的那样解决了非托管依赖项。但托管的不是。我怎样才能让它也得到解决?

【问题讨论】:

  • BOM 不应使用版本范围。最好定义所用库的特定版本...而不需要更改子版本中的版本...
  • BOM 确实为第三方的东西使用了特定的版本。我们为正在开发的内部库使用版本范围,其中版本可以非常迅速地更改。为这些使用特定版本是不切实际的。 (话虽这么说,也许我们不应该为 BOM 中的那些库提供依赖管理并明确指定子项中的范围。)
  • 您可以通过versions-maven-plugin更新依赖关系,它也可以由自动进程处理,因此无需手动执行此操作。除了该版本范围外,您的构建不可重现......
  • 是的,我们确实使用versions-maven-plugin在Jenkins中自动解析范围,以制作可用于重现构建的pom版本,这些是我们部署的构建。范围对于我们进行并行、迭代开发、进行本地快照构建等我们不关心构建是否可重现的地方仍然非常有用。在我们引入 BOM 之前,这对我们来说效果很好;唯一的问题是该系统不适用于 BOM 中的范围。

标签: maven versions-maven-plugin maven-bom maven-versions-plugin


【解决方案1】:

忘记了这个问题!最后,我永远无法找到一种方法来固定基于范围的托管版本。所以我确实停止在 BOM 中定义版本,只是在每个子 pom.xml 中用范围指定它们。子 poms 中有更多样板,但还不错。

我们仍然能够定义指定 BOM 中子级可以使用的范围的属性,从而在必要时更轻松地调整所有范围。

【讨论】:

    猜你喜欢
    • 2015-10-13
    • 2018-10-12
    • 2019-10-16
    • 2016-11-30
    • 2021-07-11
    • 2015-10-17
    • 1970-01-01
    • 2019-12-25
    • 2015-04-03
    相关资源
    最近更新 更多