【问题标题】:Maven doesn't resolve local parent POMMaven 不解析本地父 POM
【发布时间】:2013-11-14 23:02:36
【问题描述】:

这是一个有趣的问题,我不知道是我做错了什么还是 Maven 的限制。

场景的最简单版本是有父 POM、单子 POM 和聚合 POM。聚合 POM 只是将模块链接在一起。

当我安装聚合 POM 时,它没有找出子 POM 对父 POM 的依赖关系。我不希望有相对路径,并且根据我对 Maven 工件的理解应该是可能的。

任何见解将不胜感激。谢谢。

这是 uber 父级(没关系,里面什么都没有)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>my.group</groupId>
    <artifactId>parent-uber</artifactId>
    <version>0.0.2-SNAPSHOT</version>
    <packaging>pom</packaging>

</project>

这是孩子:

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>my.group</groupId>
        <artifactId>parent-uber</artifactId>
        <version>0.0.2-SNAPSHOT</version>
    </parent>

    <groupId>my.group</groupId>
    <artifactId>parent-java</artifactId>
    <packaging>pom</packaging>

    <properties>
    </properties>

    <build>
        <!-- To define the plugin version in your parent POM -->
        <pluginManagement>
            <plugins>
                <!-- All projects that extend this should have valid JavaDoc built-->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>attach-javadocs</id>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>    
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>    
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>2.1</version>
            </dependency>    
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.4</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

为了完整起见,聚合器:

<project>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>my.group</groupId>
        <artifactId>_maven-integration-aggregator</artifactId>
        <version>0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath> <!-- parent aggregator -->
    </parent>

    <groupId>my.group.maven</groupId>
    <artifactId>_poms-aggregator</artifactId>
    <version>0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>parent-uber</module>
        <module>parent-java</module>
    </modules>

</project>

错误:

org.apache.maven.model.resolution.UnresolvableModelException: Could not find artifact my.group:parent-uber:pom:0.0.2-SNAPSHOT
    at org.apache.maven.project.ProjectModelResolver.resolveModel(ProjectModelResolver.java:159)
    at org.apache.maven.model.building.DefaultModelBuilder.readParentExternally(DefaultModelBuilder.java:817)
    at org.apache.maven.model.building.DefaultModelBuilder.readParent(DefaultModelBuilder.java:669)
    at org.apache.maven.model.building.DefaultModelBuilder.build(DefaultModelBuilder.java:307)
    at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:411)
    at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:380)
    at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:496)
    at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:380)
    at org.apache.maven.project.DefaultProjectBuilder.build(DefaultProjectBuilder.java:344)
    at org.apache.maven.DefaultMaven.collectProjects(DefaultMaven.java:637)
    at org.apache.maven.DefaultMaven.getProjectsForMavenReactor(DefaultMaven.java:586)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:229)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:152)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:555)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not find artifact my.group:parent-uber:pom:0.0.2-SNAPSHOT
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:459)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(DefaultArtifactResolver.java:262)
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(DefaultArtifactResolver.java:239)
    at org.eclipse.aether.internal.impl.DefaultRepositorySystem.resolveArtifact(DefaultRepositorySystem.java:295)
    at org.apache.maven.project.ProjectModelResolver.resolveModel(ProjectModelResolver.java:155)
    ... 23 more
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact my.parent:parent-uber:pom:0.0.2-SNAPSHOT
    at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:449)
    ... 27 more

【问题讨论】:

  • 愚蠢的问题:你安装了 parent-uber pom 吗?
  • 尝试删除子&lt;module&gt;parent-java&lt;/module&gt;。我猜 Maven 仍然会通过 parent-uber 关注它
  • 目标是让它们都在聚合器中列出,并让 maven 了解对 parent-uber 的依赖。所以不,我没有安装超级父母。我想同时或至少为我的超级根聚合器自动安装 parent-uber 和 parent-java(未显示)
  • 您的父母是否在相对于您孩子的默认位置可用?否则,请尝试在子 pom 中为父级添加 relativePath。
  • 这可能是一种可能性,但我希望 Maven 足够聪明,可以自动找出依赖关系,而无需硬编码相对路径。

标签: java maven pom.xml parent-pom


【解决方案1】:

我不知道这是否是您问题的解决方案,但是:

指定父 pom 时,maven by default assumes it's located in the parent folder。这不是您的情况,因此您必须重新定义 parent-java 的父部分中的相对路径以指向 ../parent-uber,并且 pom 将在本地解析,或者作为 &lt;relativePath /&gt;,它将被解析远程。

【讨论】:

  • 这是一个问题,因为它迫使您在父依赖项的上下文中组织所有项目。这真的不是我要找的。我希望能够扩展父功能(依赖项、插件等)并通过我们的存储库解析 POM。我通常理解 Maven 严格定义的结构,但这有点过分了。如果我有一个使用 parent-uber 或 parent-java 的新干净项目,那么它应该简单地下载/解决该依赖项。如果我在错误发生后再次在子项目中“mvn install”,它将解决它。
  • 我了解我的评论将两个问题混为一谈。所以我会澄清。我只是想知道是否有一种方法可以在不硬编码相对路径的情况下解决 POM 结构。 Maven 在 repo 中有解决此问题的信息,但没有。
  • 您是否尝试过在父声明中使用&lt;relativePath /&gt;
  • 这个想法是我想提供一组父 POM,以便在默认情况下轻松扩展以提供必要的依赖项和插件声明。因此,它不重要,因为 为空或其他。如果是这样,您能否再解释一下,以便我可以尝试并理解结果?
【解决方案2】:

在我的情况下,定义的父 pom 版本与我在子 pom 中提到的版本不同,因此出现错误。一旦我更正了父 pom.xml 上的版本,它就开始正常工作 -

<version>2.1.0</version>

子 pom 条目看起来像

<relativePath>../parent-pom</relativePath>

【讨论】:

    【解决方案3】:

    您可以通过添加特殊配置文件来仅构建父级来解决此问题。

    在您的子 pom 中,将 &lt;relativePath /&gt; 添加到 &lt;parent&gt; 标记。然后修改聚合器。

    聚合器 pom:

    <project>
        <modelVersion>4.0.0</modelVersion>
        <groupId>my.group.maven</groupId>
        <artifactId>_poms-aggregator</artifactId>
        <version>0.1-SNAPSHOT</version>
        <packaging>pom</packaging>
    
        <profiles>
            <profile>
                <id>default</id>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
                <modules>
                    <module>parent-uber</module>
                    <module>parent-java</module>
                </modules>
            </profile>
            <profile>
                <id>prepare</id>
                <modules>
                    <module>parent-uber</module>
                </modules>
            </profile>
        </profiles>
    
    </project>
    

    并使用它来运行构建两次,就像这样:

    mvn install -Pprepare
    mvn install
    

    第一个命令将 parent 的 pom 安装到本地 repo,因此第二个命令不会失败。

    但只有当您的父项目与孩子需要的版本相同时,此解决方案才有效。但是,假设您已经发布了 parent 的 1.0 版本,现在您正在使用 1.1-SNAPSHOT 版本的 parent,但 child 使用已发布的 1.0 版本。如果您现在要删除本地 repo,或者其他人将克隆您的项目,则使用 -Pprepare 构建将不起作用,因为这将安装 parent-uber:1.1-SNAPSHOT 并且子级仍将具有未解决的依赖关系。

    因此,要使其正常工作,您需要有一个外部存储库(nexus、artifactory 等),您已将 parent-uber:1.0 发布到该存储库中,并且您必须在子 pom.xml 中的 &lt;repositories&gt; 标记中提供此存储库。

    当有很多子项目时,将通用设置放入父 pom 中通常是个好主意,以避免重复代码。由于存储库对所有项目都是通用的,因此您可能希望将其放在父级中。但是,如果您没有在本地安装父级并尝试安装子级,那么 maven 不知道应该使用哪个存储库来下载父级。为避免此问题,您可以将该存储库的配置文件添加到 .m2/settings.xml 并建议您的所有团队成员也这样做。

    【讨论】:

      【解决方案4】:

      根据这个guideline,maven 多模块反应器似乎不会自动分析父依赖项。由于列表中没有列出父依赖项。

      在对项目进行排序时遵循以下关系:

      1. 项目依赖于构建中的另一个模块
      2. 插件声明,其中插件是构建中的另一个模块
      3. 插件依赖于构建中的另一个模块
      4. 在构建中的另一个模块上构建扩展声明 元素中声明的顺序(如果没有其他规则适用)

      我验证了 maven 确实通过分析子模块之间的标签定义的依赖关系图确定了构建顺序。

      【讨论】:

        【解决方案5】:

        嗯,我是用另一种方式做到的。

        就我而言,我想要一个“父级”,它也是一个“聚合器”。

        所以,我创建了我的项目“父+聚合器”。

        这是从我的项目“父+聚合器”的 pom.xml 中截取的:

        <parent>
            <groupId>com.test</groupId>
            <artifactId>project-sti</artifactId>
            <version>2.4</version>
        </parent>
        
        <groupId>com.test</groupId>
        <artifactId>parent-testproject</artifactId>
        <version>1.0.0</version>
        <packaging>pom</packaging>
        
        <profiles>
            <profile>
                <!-- Profile executed during upload to Archiva. Defined in the "parent". -->
                <id>deployArchiva</id>
                <activation>
                    <activeByDefault>false</activeByDefault>
                </activation>
                <!-- Necessary to avoid that during "deploy" ocurrs the compilation of the others modules. 
                    It's necessary because the tag "activeByDefault=true" works only inside of scope of 
                    "pom.xml" of project itself. Therefore, it doesn't consider the profile defined in 
                    the "parent". -->
            </profile>
            <profile>
                <!-- Profile executed during the local build (Clean Install). -->
                <id>clean-install-local</id>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
                <!-- The order of projects are indifferent, because Maven identify the correct order to 
                    compile the projects. -->
                <modules>
                    <module>../testprojectjpa</module>
                    <module>../testprojectejb</module>
                    <module>../testprojectweb</module>
                    <module>../testprojectapp</module>
                </modules>
            </profile>
        </profiles>
        
        <properties>
            <xstream.version>1.4.9</xstream.version>
            <dom4j.version>1.6.1</dom4j.version>
            <commons-lang.version>2.6</commons-lang.version>
            <commons-io.version>2.2</commons-io.version>
            <commons-beanutils.version>1.9.2</commons-beanutils.version>
            <commons-logging.version>1.1.2</commons-logging.version>
        </properties>
        
        <dependencies>
            <dependency>
                <groupId>com.thoughtworks.xstream</groupId>
                <artifactId>xstream</artifactId>
                <version>${xstream.version}</version>
                <scope>provided</scope>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>${dom4j.version}</version>
                <scope>provided</scope>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
                <version>${commons-lang.version}</version>
                <scope>provided</scope>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons-io.version}</version>
                <scope>provided</scope>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>commons-beanutils</groupId>
                <artifactId>commons-beanutils</artifactId>
                <version>${commons-beanutils.version}</version>
                <scope>provided</scope>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>${commons-logging.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>*</groupId>
                        <artifactId>*</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
        

        在此之后,我将“testprojectejb”更改为引用“parent-testproject”。

            <parent>
                <groupId>com.test</groupId>
                <artifactId>parent-testproject</artifactId>
                <version>1.0.0</version>
                <!-- Find the project "parent + aggregator" that was compiled before of 
                the project testprojectejb -->
                <relativePath>../testproject/pom.xml</relativePath>
            </parent>
        
            <artifactId>testprojectejb</artifactId>
            <packaging>ejb</packaging>
            <name>Projeto testproject ejb</name>
            <version>1.0.0</version>
        

        因此,当我在没有配置文件或使用“clean-install-local”配置文件的情况下构建“testproject”(parent-testproject)时,所有项目都会构建,包括父项目。

        当我使用配置文件“deployArchiva”构建“testproject”(parent-testproject)时,只有项目本身被构建并部署到 Archiva。

        希望对你有用。

        【讨论】:

          猜你喜欢
          • 2011-11-28
          • 2020-04-18
          • 2016-07-26
          • 1970-01-01
          • 2021-11-16
          • 2023-03-05
          • 2016-10-25
          • 2022-11-24
          • 2023-04-01
          相关资源
          最近更新 更多