mvn dependency:tree在简单项目上失败

13

我有一个相当复杂的项目(大约100个模块),我想运行mvn dependency:tree命令。但是它失败了,并抱怨无法解析的依赖关系。项目在其他方面都可以编译成功。因此,我创建了我能想到的最基本的项目,但仍然出现相同的错误。显然,要么我必须犯了一些非常基本的错误,要么就是maven-dependency-plugin还没有被任何人使用过。这是我的测试项目中的三个POM文件:

pom.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>root</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>foo</module>
        <module>bar</module>
    </modules>
</project>

foo/pom.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>foo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
</project>

bar/pom.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>bar</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>foo</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

然后我在顶级目录中发出以下命令mvn dependency:tree,并得到以下输出:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] foo
[INFO] bar
[INFO] root
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building foo 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ foo ---
[INFO] com.example:foo:jar:1.0.0-SNAPSHOT
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building bar 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] foo ................................................ SUCCESS [  0.756 s]
[INFO] bar ................................................ FAILURE [  0.011 s]
[INFO] root ............................................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.065 s
[INFO] Finished at: 2015-03-03T16:19:18+01:00
[INFO] Final Memory: 13M/309M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project bar: Could not resolve dependencies for project com.example:bar:jar:1.0.0-SNAPSHOT: Could not find artifact com.example:foo:jar:1.0.0-SNAPSHOT -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
[ERROR] 
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :bar

我错过了什么吗?这不应该只是有效的吗?


4
你是否先运行过 mvn install 命令?如果没有,foo 模块还未被安装到你的仓库中,因此在 bar 模块中无法解析。 - gizmo
1
@gizmo 我需要这样做吗?这样会把构件放入我的全局.m2目录中,这似乎是一个非常糟糕的想法。我同时在处理该项目的多个分支,我不希望它们相互干扰。所有模块都在项目目录中,并列在顶级 POM 的 <modules> 标记中。 - Feuermurmel
1
@jeanMarcAssin 但是这样我每次运行 mvn clean 都需要额外运行 rm -r ~/.m2,这对我来说似乎浪费了带宽和时间。 - Feuermurmel
1
@gizmo 但是当我运行 mvn compile(而不运行 mvn install)时,Maven确实会解决依赖关系,那么这是如何工作的呢? - Feuermurmel
1
据我所知,mvn clean不会从我的本地存储库中删除这些构件。而且它也无法解决两个构建同时运行的问题。 - Feuermurmel
显示剩余8条评论
5个回答

22

我感到沮丧,不知道为什么它没有起作用。
一个简单的依赖分析就是没用的。
而且官方也没有任何指导如何做。
另一个非常有用的命令也没有起作用。

mvn dependency:resolve

但是,也许你可以尝试这些命令

mvn test-compile dependency:resolve
mvn test-compile dependency:tree

无论如何,它对我有效


2017年3月13日更新

我们可以通过跳过编译使其更快

 mvn test-compile dependency:resolve -Dmaven.main.skip=true -Dmaven.test.skip=true
 mvn test-compile dependency:tree    -Dmaven.main.skip=true -Dmaven.test.skip=true

很遗憾它没有为我们的项目工作,因为我们的项目正在使用Kotlin,也许这是Kotlin的一个错误,未跳过编译,也许我应该向JetBrains报告此错误。


我现在无法测试这个,因为我已经离开了Java和Maven的世界,并用完全不同的一套东西来代替它。在有人可以确认它可行之前,我将接受这个答案。 - Feuermurmel
@Feuermurmel,它能够工作是因为test-compile生命周期可以成功解决所有依赖项(包括主要和测试)在本地项目中,之后,在插件任务执行时,它也可以成功解决依赖项,因此不会触发存储库中的查找,并且不会出现错误。它需要更多时间来执行,因为它必须编译所有源代码,但对我来说这是可以接受的。 - William Leung
这对我也有效,谢谢! 较早的生命周期compile对我也有效: mvn compile dependency:tree 我认为这应该比运行到test-compile生命周期更快。 - ribi86
如果您的多模块项目具有“test-jar”依赖项,则@ribi86 compile dependency:tree将失败。 - William Leung
这个对我的项目很有效。执行 "mvn dependency:tree" 只是像 OP 一样惨败了,但执行 "mvn test-compile dependency:tree" 就可以工作了。@Feuermurmel - 如果你看到了这个,你应该标记为已接受! - tonicsoft

10

好的,让我们来做一个正式的答案,因为评论有点太短了,不能正确地解释。

Maven是一个具有多种组合面向的工具,有时很难确定哪些部分在执行给定命令时起作用。

在您的示例中,您有两个“经典”的项目foobar,以及一个特殊的项目root
root在您的示例中是特殊的,因为它扮演了两个角色。

  • 第一个称为parent pom。通常用于修复依赖项和插件版本,以及一些需要级联到子项目的常见配置。它还具有一个有时有用的属性,即除非在子项目本身中显式指定版本,否则子项目将继承该版本。
  • 第二个角色称为reactor pom。这部分主要在<modules>标记中定义。它定义了一组其他项目,可以作为一组发送命令(例如:mvn clean install)。当执行此类命令时,Maven将查看在<modules>中描述的项目,并根据它们声明的依赖关系确定调用它们的顺序,以便最大化构建成功的机会。

现在,关于您尝试的各种命令的行为(假设它们都在root项目上调用:

  • mvn dependency:tree将对<modules>标记中列出的所有项目以及自身执行依赖项分析。该分析针对存储库执行,即您的本地.m2 repo和必要时其他外部存储库。如果您没有先在存储库中安装项目,则它将对bar失败,因为它在那里找不到com.example:foo:1.0.0-SNAPSHOT
  • mvn [clean] install,按照相同的顺序,将完全打包并部署您的项目到本地存储库中。由于在将foo放入存储库后才执行bar,因此一切都会很好,每个人都会感到满意。

但是mvn compile怎么办?

嗯,这有点棘手。由于示例中没有实际要编译的代码,编译时跳过了依赖项解析,因此在foo工件尚不可用时没有出现错误。

现在,关于您对分支和仓库中工件的评论...
当您切换到分支时,除非所有其他项目(模块)都使用稳定的版本号(即不带SNAPSHOT后缀),否则您应该在反应堆POM上运行mvn [clean] install以确保开始使用一致的模块和依赖项集。
您可能认为与解释性语言相比,这是浪费时间,但这是MAVEN方式处理项目。它确保在开始工作之前所有模块都被调整。


1
首先,感谢您的回答,但我对两个问题不确定:com.example:root:1.0.0-SNAPSHOT 不是另外两个项目的父级,我没有在 foobar 模块中声明它。当模块包含 Java 源代码时,即使 bar 中的代码引用了 foo 中的代码,mvn compile 也可以工作。 - Feuermurmel
1
关于您的评论,为什么我可能认为这是浪费时间。我并不是在将其与其他构建系统(如_GNU Make_)进行比较,后者当然解决了一个非常不同的问题,但是在不改变任何全局状态的情况下完成了这个任务,因此在我看来具有许多优点。它甚至可以说,我无法理解_maven_为什么需要那个全局状态,即将工件安装到本地存储库中,以便可以从同一项目的其他模块中使用。 - Feuermurmel
它并没有解释为什么被接受的答案中提出的黑客方法有效。mvn test-compile dependency:tree -Dmaven.main.skip=true -Dmaven.test.skip=true - JJ Roman
是的,只需要在运行 mvn dependency:tree 前先运行 mvn install 就可以了,;-) - user1767316

1
我遇到了以下错误:java.lang.NoClassDefFoundError: org/sonatype/aether/*,但是我使用了一个旧的插件来解决它,正如官方页面在错误日志中提到的那样:
mvn org.apache.maven.plugins:maven-dependency-plugin:2.8:tree

1

对我来说,问题出现在尝试执行 requireUpperBoundDeps 规则时。我无法将 maven-enforcer-plugin 降级(从 3.1.0 到 3.0.0-M3)。我不得不对一些依赖项添加排除。

<dependency>
  <groupId>net.sf.ehcache</groupId>
  <artifactId>ehcache-core</artifactId>
  <version>${dep.ehcache}</version>
  <exclusions>
    <exclusion>
      <groupId>net.sf.ehcache</groupId>
      <artifactId>sizeof-agent</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.richfaces</groupId>
  <artifactId>richfaces</artifactId>
  <version>${dep.richfaces}</version>
  <exclusions>
    <exclusion>
      <groupId>jacorb</groupId>
      <artifactId>jacorb</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.richfaces.cdk</groupId>
      <artifactId>annotations</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.richfaces</groupId>
  <artifactId>richfaces-a4j</artifactId>
  <version>${dep.richfaces}</version>
  <exclusions>
    <exclusion>
      <groupId>jacorb</groupId>
      <artifactId>jacorb</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.richfaces.cdk</groupId>
      <artifactId>annotations</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.richfaces</groupId>
  <artifactId>richfaces-core</artifactId>
  <version>${dep.richfaces}</version>
  <exclusions>
    <exclusion>
      <groupId>jacorb</groupId>
      <artifactId>jacorb</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.richfaces.cdk</groupId>
      <artifactId>annotations</artifactId>
    </exclusion>
  </exclusions>
</dependency>

0
对我来说,这些都没有起作用。我的 maven-enforcer-plugin 依赖版本设置为 3.0.0,但将其更改为 3.0.0-M3 对我有帮助。

我使用的是3.1.0版本,当我降级时出现了API不兼容的问题。 - caduceus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接