首页 > 解决方案 > Maven多模块+继承:通过占位符维护父版本号时构建子模块的问题

问题描述

这是关于通过占位符维护父版本号的答案的后续行动:

我在 Maven 3.6.1上,并且具有以下多模块 Maven 项目结构:

pom.xml
a/
  pom.xml
b/
  pom.xml

pom.xml(父母):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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.tuna</groupId>
    <artifactId>root</artifactId>
    <version>${ver}</version>
    <packaging>pom</packaging>

    <modules>
        <module>a</module>
        <module>b</module>
    </modules>

    <properties>
        <ver>1.0-SNAPSHOT</ver>
    </properties>
</project>

a/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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>

    <parent>
        <groupId>com.tuna</groupId>
        <artifactId>root</artifactId>
        <version>${ver}</version>
        <relativePath>..</relativePath>
    </parent>

    <artifactId>a</artifactId>
    <version>${ver}</version>
</project>

b/pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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>

    <parent>
        <groupId>com.tuna</groupId>
        <artifactId>root</artifactId>
        <version>${ver}</version>
        <relativePath>..</relativePath>
    </parent>

    <artifactId>b</artifactId>
    <version>${ver}</version>

    <dependencies>
        <dependency>
            <groupId>com.tuna</groupId>
            <artifactId>a</artifactId>
            <version>${ver}</version>
        </dependency>
    </dependencies>
</project>

请注意,b取决于a.

现在,当我用

mvn clean install

它成功构建(带有一些'version' contains an expression but should be a constant警告 - 很公平)。

但是,如果我这样做

mvn clean install -rf :b
[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.tuna:a:jar:1.0-SNAPSHOT
[WARNING] 'version' contains an expression but should be a constant. @ com.tuna:a:${ver}, C:\Users\janaka\code\dustbin\mvn-multi-module\a\pom.xml, line 15, column 14
[WARNING] 'version' contains an expression but should be a constant. @ com.tuna:root:${ver}, C:\Users\janaka\code\dustbin\mvn-multi-module\pom.xml, line 9, column 14
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.tuna:b:jar:1.0-SNAPSHOT
[WARNING] 'version' contains an expression but should be a constant. @ com.tuna:b:${ver}, C:\Users\janaka\code\dustbin\mvn-multi-module\b\pom.xml, line 15, column 14
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.tuna:root:pom:1.0-SNAPSHOT
[WARNING] 'version' contains an expression but should be a constant. @ com.tuna:root:${ver}, C:\Users\janaka\code\dustbin\mvn-multi-module\pom.xml, line 9, column 14
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]



[INFO]
[INFO] -----------------------------< com.tuna:b >-----------------------------
[INFO] Building b 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.472 s
[INFO] Finished at: 2019-10-09T00:08:14+05:30
[INFO] ------------------------------------------------------------------------



[ERROR] Failed to execute goal on project b: Could not resolve dependencies for project com.tuna:b:jar:1.0-SNAPSHOT: Failed to collect dependencies at com.tuna:a:jar:1.0-SNAPSHOT: Failed to read artifact descriptor for com.tuna:a:jar:1.0-SNAPSHOT: Cannot access central (https://repo.maven.apache.org/maven2) in offline mode and the artifact com.tuna:root:pom:${ver} has not been downloaded from it before. -> [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

如果我mvn clean install从内部运行,也会发生同样的情况b/

显然 Maven可以同时${ver}解析和ba但是当它扫描a的 POM 时,它无法解析a ${ver}版本(尽管relativePath条目在那里);可能是因为 Maven 是a从本地存储库中读取的 POM(~/.m2/repository/- 相对路径没有意义),而不是从本地代码库?

有没有办法让它工作 - 避免错误并让部分构建工作 - 也许通过一些黑客; ${ver}就像通过系统属性传递默认值一样?

PS:

是的,是的,我知道在父版本号中使用占位符很臭很邪恶;但我的实际项目有大约 30 个模块,其中许多模块相互依赖。所以我只想要一种方法来维护一个版本号(一行),我可以轻松地更改它 - 每次升级时都不必更改和提交几百行。

基本上,我不是要求建议在整个地方复制版本号(并使用 Maven 版本插件之类的东西来一次升级它们)——我只需要一个 hack 来让当前的结构正常工作。

(所以我相信这不能被标记为重复 - 因为复制和占位符是我在 SO 中遇到的唯一两个选项,我的问题是关于后者的具体情况。)

标签: javamavenmaven-3

解决方案


只是提到我的最终解决方法,以防它帮助某人:

我最终覆盖了maven-resources-plugin执行以制作每个 POM 的副本,替换所有占位符(配置添加到根 POM 以便它适用于所有子模块):

<!-- replaces version number placeholders in POMs, with current values -->
<plugin>
  <artifactId>maven-resources-plugin</artifactId>
  <version>3.0.1</version>
  <execution>
    <id>copy-resources</id>
    <phase>validate</phase>
    <goals>
       <goal>copy-resources</goal>
    </goals>
    <configuration combine.children="append">
      <resources>
        <resource>
          <directory>.</directory>
          <include>pom.xml</include>
          <filtering>true</filtering>
        </resource>
      </resources>
      <outputDirectory>target</outputDirectory>
    </configuration>
  </execution>
</plugin>

我还重写maven-install-plugin以使用/安装此修改后的(固定)副本target/,而不是带有占位符的原始副本:

<plugin>
  <artifactId>maven-install-plugin</artifactId>
  <version>2.4</version>
  <configuration combine.children="append">
    <pomFile>target/pom.xml</pomFile>
  </configuration>
</plugin>

现在安装到本地/远程仓库的 POM 没有占位符;因此任何依赖的项目/模块都能够成功处理这些 POM!从某种意义上说,我相信这是正确的方法,因为在我的情况下,占位符只是为了方便开发人员而存在的;实际上,一旦将它们安装到 Maven 存储库中,就没有可靠的方法来解析它们的值。

一个缺点是所有占位符都得到解决。例如,如果 POM 包含${java.home}表达式,则安装的副本现在包含构建器机器的 Java 安装的实际绝对路径。我仍然没有找到适当的方法来排除此类(一部分)占位符被替换。


推荐阅读