Maven无法解析本地父POM

7
这是一个有趣的问题,我无法确定是我做错了什么还是Maven的限制。
最简单的情况是有一个父POM、一个子POM和一个聚合POM。聚合POM仅链接模块。
当我安装聚合POM时,它无法找到子POM对父POM的依赖关系。我希望不要使用相对路径,从我对Maven构件的了解来看应该是可能的。
任何见解将不胜感激。谢谢。
这是终极父级POM(注意其中什么也没有)。
<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

3
愚蠢的问题:你安装了parent-uber pom吗?(注:pom是Maven项目管理工具中的一种配置文件) - nablex
尝试移除子模块<module>parent-java</module>。我猜Maven仍将通过parent-uber跟随它。 - Boj
1
你的父项目是否位于子项目的默认位置?否则,请尝试在子POM中为父项目添加一个relativePath。 - DanielBarbarian
1
这可能是一种可能性,但我希望Maven足够聪明,能够自动找出依赖关系,而不需要硬编码相对路径。 - Thomas Beauvais
我仍然认为你可以从聚合器中删除parent-java,然后所有内容都将被构建。你试过了吗? - Boj
显示剩余2条评论
5个回答

4
你可以通过为仅构建父模块添加特殊配置文件来解决此问题。
在子模块的pom中,将<relativePath />添加到<parent>标记中。然后修改聚合器。 聚合器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

第一个命令将父pom安装到本地仓库,这样第二个命令就不会失败了。

但是,这种解决方案只适用于您的父项目与子项目所需的版本相同的情况。假设您发布了1.0版本的parent,并且现在正在使用1.1-SNAPSHOT版本的parent工作,但是子项目仍使用发布版本1.0。如果现在删除您的本地仓库,或者其他人克隆了您的项目,并使用-Pprepare构建,则无法正常工作,因为这将安装parent-uber: 1.1-SNAPSHOT,而子项目仍将存在未解决的依赖项。

因此,要使其正常工作,您需要拥有外部仓库(nexus、artifactory等),并在子POM中的<repositories>标签中提供已发布的parent-uber:1.0

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


1
根据这个指南,似乎Maven多模块反应堆不会自动分析父依赖关系。因为列表中没有列出任何父依赖项。
以下关系在排序项目时受到尊重:
  1. 构建中对另一个模块的项目依赖
  2. 插件声明,其中插件是构建中的另一个模块
  3. 构建中对另一个模块的插件依赖
  4. 在构建中另一个模块上声明的构建扩展 以元素中声明的顺序(如果没有其他规则适用)
我验证了Maven确实通过分析子模块之间由标签定义的依赖关系图来确定构建顺序。

0
在我的情况下,父POM版本定义与我在子POM中提到的版本不同,因此出现了错误。当我更正了父POM.xml上的版本后,它立即开始正常工作。
<version>2.1.0</version>

子POM条目看起来像这样

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

0

好的,我用另一种方式实现了这个。

在我的情况下,我想要一个既是“父级”的又是“聚合器”的东西。

因此,我创建了我的项目“父级+聚合器”。

这是来自我的项目“父级+聚合器”的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"(父-testproject)时,所有的项目都会被构建,包括父项目。

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

希望这有用。


0

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

当指定父POM时,Maven 默认假设它位于父文件夹中。但这不是您的情况,因此您必须重新定义父级部分中的相对路径,将其指向../parent-uber,然后POM将在本地解析,或者使用<relativePath />,然后它将在远程解析。


这是一个问题,因为它强迫你在父级依赖的上下文中组织所有项目。这真的不是我想要的。我希望能够通过我们的存储库扩展父功能(依赖项、插件等)并解决POM。我通常理解Maven的严格定义结构,但这有点过分了。如果我有一个新的干净项目使用parent-uber或parent-java,那么它应该简单地下载/解析该依赖项。如果出现错误后,再次在子项目中执行“mvn install”则可以解决它。 - Thomas Beauvais
我明白我的评论混淆了两个问题。所以我要澄清一下。我只是想知道是否有一种方法可以在不硬编码相对路径的情况下解决POM结构。Maven有信息来解决这个问题,但它没有这样做。 - Thomas Beauvais
你在父级声明中尝试使用过 <relativePath /> 吗? - diegomtassis
我的想法是提供一组易于扩展的父POM,以默认方式提供必要的依赖项和插件声明。因此,<relativePath/>为空或其他情况都无关紧要。如果有必要,请您详细解释一下,以便我可以尝试并理解结果。 - Thomas Beauvais

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