Maven 依赖收敛错误(使用了错误的版本)

Maven dependency convergence error (wrong version used)

我遇到了这个奇怪的问题,我不知道是什么问题。

我有一个多模块 java Maven 项目,其结构如下:

+ A (parent)
+-+-B
| +--C
| +--D

我在父 pom (A) 中添加了一个依赖项:

  <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>1.8.5</version>
            <exclusions>
                <exclusion>
                    <groupId>com.mchange</groupId>
                    <artifactId>c3p0</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.mchange</groupId>
                    <artifactId>mchange-commons-java</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

注意:除A

之外的其他模块需要1.8.5版本

在模块 C 和 D 中,必须使用版本 2.3.0,因此我使用此依赖项从父 pom A 覆盖版本 1.8.5:

 <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
        <exclusions>
            <exclusion>
                <groupId>com.mchange</groupId>
                <artifactId>c3p0</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.mchange</groupId>
                <artifactId>mchange-commons-java</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

我在模块 C 和 D 的 poms 中添加了这个依赖。C 也是 D 的依赖。所以当我尝试构建项目时,出现以下错误:

[WARNING] Rule 1: org.apache.maven.plugins.enforcer.DependencyConvergence   failed with message:
Failed while enforcing releasability the error(s) are [
Dependency convergence error for org.quartz-scheduler:quartz:1.8.5 paths to dependency are:
+-de.xxx.xxx.xxx:module-D:6.40.1-jat-SNAPSHOT
  +-de.xxx.xxx.xxx:module-C:6.40.1-jat-SNAPSHOT
    +-org.quartz-scheduler:quartz:1.8.5
and
+-de.xxx.xxx.xxx:module-D:6.40.1-jat-SNAPSHOT
  +-org.quartz-scheduler:quartz:2.3.0

所以不知何故maven认为模块C的quartz版本是1.8.5,但我在模块C的pom中明确地将版本设置为2.3.0

同样当我 运行 mvn dependency:tree -Dverbose 在模块 C 的目录中时,它似乎是正确的: [INFO] +- org.quartz-scheduler:quartz:jar:2.3.0:compile

有人知道吗?

检查模块 C 的依赖层次结构并排除版本 1.8.5(使用像 eclipse 这样的现代 IDE,这应该很容易)。 或者您可以从父 pom 中删除此依赖项,在依赖项管理中使用它,并在子模块中指明您要使用的版本。 parent pom中的依赖会被所有children继承。

模块 A(父模块)的包装类型必须为 pom

一般来说在父 poms 中声明依赖关系是个坏主意因为它强制所有子模块都具有这些特定的依赖关系,无论它们是否需要。相当于在每个子模块中声明这些依赖。

当模块 C 和 D 开始发挥作用时,您将拥有 具有冲突版本的重复依赖声明

相反,模块 A 应该使用 <dependencyManagement> 部分来声明依赖版本,而不强制每个子模块实际依赖它们。

换句话说:

<dependencyManagement>
    <dependencies>
        ...
        <dependency>
           <groupId>org.quartz-scheduler</groupId>
           <artifactId>quartz</artifactId>
           <version>1.8.5</version>
           <exclusions>
               <exclusion>
                  <groupId>com.mchange</groupId>
                  <artifactId>c3p0</artifactId>
               </exclusion>
               <exclusion>
                   <groupId>com.mchange</groupId>
                   <artifactId>mchange-commons-java</artifactId>
               </exclusion>
           </exclusions>
        </dependency>
        ...
    </dependencies>
</dependencyManagement>

模块 C 和 D 中的石英依赖声明将简单地覆盖父 A 中指定的版本。

依赖于 managed quartz 库的其他模块仍然需要显式声明它:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
</dependency>

versionexclusions 将从托管依赖声明中获取。