Maven 3 不会从本地存储库更新快照依赖项

Posted

技术标签:

【中文标题】Maven 3 不会从本地存储库更新快照依赖项【英文标题】:Maven 3 does not update snapshot dependency from local repository 【发布时间】:2014-03-27 18:20:01 【问题描述】:

我正在尝试在我的 Maven 项目中使用外部库。由于我希望项目在任何机器上开箱即用,我不想使用mvn install 解决方案。因此,我在 pom.xml 中定义了本地存储库:

    <dependency>
        <groupId>com.test</groupId>
        <artifactId>fooLib</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    ....
    <repository>
        <id>in-project</id>
        <snapshots>
            <updatePolicy>always</updatePolicy>
            <enabled>true</enabled>
        </snapshots>
        <name>In Project Repo</name>
        <url>file://$project.basedir/libRepo</url>
    </repository>

问题是当我替换 libRepo 中的 jar 时(不更新版本号,因为它只是另一个快照),即使是 @987654327,也没有使用这个更新的 jar(使用来自 .m2 目录的旧版本) @ 如何让maven更新这个jar?

编辑: 根据What exactly is a Maven Snapshot and why do we need it? maven 应尝试查找从不版本的 SNAPSHOT 依赖项,“即使在本地存储库中找到此库的版本”。我的设置有什么问题?

肮脏的解决方案: 根据Maven 2 assembly with dependencies: jar under scope "system" not included 的回答,我的原始解决方案的以下扩展似乎有效:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <executions>
                <execution>
                    <id>hack-binary</id>
                    <phase>validate</phase>
                    <configuration>
                        <file>$repo.path.to.jar</file>
                        <repositoryLayout>default</repositoryLayout>
                        <groupId>com.test</groupId>
                        <artifactId>fooLib</artifactId>
                        <version>1.0-SNAPSHOT</version>
                        <packaging>jar</packaging>
                        <generatePom>true</generatePom>
                    </configuration>
                    <goals>
                        <goal>install-file</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

正如对该解决方案的评论所述,它不能单独工作,因此它与in-project 存储库结合使用(当本地.m2 存储库中的依赖项不可用时有效)并且第二部分刷新@987654331 @ 在每次构建期间。

但是我仍然不清楚为什么普通的“SNAPSHOT”机制不起作用(即当前的脏解决方案在没有 SNAPSHOT 的情况下也可以工作,因为本地 .m2 回购每次都会显式更新)。有没有更干净的方法?

解决方案(基于 Aaron 的回答和讨论):问题是我尝试使用 install-file 将文件安装到 libRepo。实际的解决方案是,如果库更新,使用

mvn deploy:deploy-file -Dfile=fooLib.jar  -DgroupId=com.test \
    -DartifactId=fooLib -Dversion=1.0-SNAPSHOT -Dpackaging=jar \
    -Durl=file://..\libRepo -DrepositoryId=in-project

将其部署到 repo。正确部署后,maven 可以正确处理 SNAPSHOT。

【问题讨论】:

您是在构建依赖项还是在构建主项目时使用mvn -U clean install 我仅将 maven 用于“主”项目。 fooLib 不是 maven 项目,是独立构建的。我只想在我的 Maven(“主”)项目中使用 fooLib 的更新快照。 所以你必须手动安装fooLib,因为它永远不会在你的.m2文件夹中更新,除非它的版本发生变化。 【参考方案1】:

如果您为此使用存储库,那么 Maven 会将 JAR 复制一次到其本地存储库中(通常在 $HOME/.m2/repository/ 中)。除非版本号更改,否则 Maven 不会认为此文件已更改并且不会复制它。请注意,版本号是 Maven 唯一查看的内容;它不关心校验和、文件大小或日期。

顺便说一下,快照在内部被分配一个版本号只是为了这个目的:这样 Maven 可以在内部注意到快照已被更新。

我建议改用system dependency。这样,实际的 JAR 将被添加到类路径中(无需任何复制或其他内容)。你也不需要为这种方法复制一个 repo 结构,它会清楚地传达你的意图。

[编辑] 我了解 Maven 以不同方式处理范围 system 的依赖项。我不确定这是否有意义(如果它使用依赖来编译,它肯定可以使用它来运行?)

在我看来,您有以下选择:

    使用deploy:deploy-file 将依赖项安装到您的libRepo 中,而不是自己复制它。这应该以这样一种方式更新元数据,当您在真实项目上再次运行 mvn install 时,Maven 会再次复制它。

    请注意,file:install 不起作用。文件插件用于访问本地存储库,但您需要使用知道如何更新共享/服务器存储库的部署插件。

    将依赖项安装到您的本地仓库中;我建议为此使用可以包含在项目中的脚本。这样一来,您就可以避免所有问题,并且很容易在新机器上进行设置。

    更改依赖的版本号,但这很繁琐,当依赖的真实版本号更改时,您可能会遇到麻烦。

    为您的公司设置本地 repo 服务器并将依赖项部署到它。这将需要几个小时,但是 a) 您将获得所有依赖项的本地缓存,从而使您的初始构建更快;b) 它将使其他开发人员的设置速度更快。

【讨论】:

起初它看起来很有帮助,我可以看到 mvn dependency:tree 中的依赖关系,但是在执行它时它没有添加到类路径中,例如通过mvn exec:java 也不会使用maven-jar-plugin 添加到清单中(但是maven-dependency-plugin:copy-dependencies 有效) 提出一个新问题,向我们展示您使用的代码是如何添加依赖项的。 已经有这样的问题(不是我的):***.com/questions/2065928/… 但是它不处理快照...除了这个详细的解决方案与我原来的解决方案相同。 我的“插件”是例如' org.apache.maven.pluginsmaven-jar-plugintrue falselib/$jar.mainclass$project.version ' 我很困惑。这个问题似乎不相关(它涉及构建程序集而不是exec:java。另外,当您想知道如何添加依赖项时,为什么要发布 JAR 插件的配置?【参考方案2】:

Maven 永远不会读取存在于任何库文件夹中的 jar。您必须首先了解 maven 是如何工作的。 maven 查找 jar 的唯一位置是 localRepository (.m2),如果不存在,它会搜索您的 POM.xml 中提到的其他存储库

【讨论】:

我不是可以添加范围为系统的依赖项并添加文件路径并要求POM读取它吗? 但是由于 jar 已经存在于您的本地存储库中,它总是会在访问任何其他存储库之前找到它! 所以没有办法获取任何依赖的新快照? 是的,您必须将 jar 作为依赖项添加到您的项目中,并在构建项目之前构建 jar。您可以通过 parent/module 部分了解更多详细信息 虽然您的答案在技术上是正确的,但它并不真正适用于这里,因为 OP 已将 JAR 放在一个存储库中,而该存储库恰好位于他的项目结构中。 Maven 可以从那里读取它,但这里的关键问题是它只执行 一次【参考方案3】:

之前的回答者(和一位评论者)指出,maven 只在本地项目存储库中查找一次,在后续构建中,它会从 .m2 存储库中获取缓存的 jar。

我只是 found 解决需要增加版本号的方法(例如,在开发库的小改动上):

首先将 jar 重新安装到本地项目存储库中:

mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -DgroupId=com.johndoe.dev -DartifactId=Helpers -Dversion=0.1 -Dfile=C:/path/to/helpers.jar

(其中 -Dfile 可以指向生成 helpers.jar 的外部项目)

然后只清除 .m2-repository 中的这个特定工件:

mvn dependency:purge-local-repository -DmanualInclude=com.johndoe.dev:Helpers:0.1

(以com.johndoe.dev为GroupId,Helpers为ArtifactId,与上一步安装的版本相同)

执行后一步,maven 使用本地项目存储库 jar 文件重建 .m2 内的工件。

另一种可能是肮脏的变体: 只需将 helpers.jar 复制到 C:\Users\johndoe\.m2\repository\com\johndoe\dev\Helpers\0.1\Helpers-0.1.jar (不了解 linux,因为我没有在那里使用过 mave)。

【讨论】:

以上是关于Maven 3 不会从本地存储库更新快照依赖项的主要内容,如果未能解决你的问题,请参考以下文章

Gradle在本地Maven存储库中找不到现有的依赖项

Maven:如何将本地 lib 目录用于依赖项而不是 Maven 存储库

Leiningen 中的本地依赖项而不创建 Maven 存储库?

Eclipse m2eclipse 从本地存储库获取依赖项

将项目从 bitbucket 导入到本地 maven 存储库

将项目从bitbucket导入到本地maven存储库