具有显式finalName的Maven无法正常工作 [英] Maven with an explicit finalName won't work properly

查看:166
本文介绍了具有显式finalName的Maven无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1.背景

我的maven项目中有很多带有jarswars的模块和子模块,并且一切正常.我也可以毫无问题地将其部署在服务器上.

我决定遵循此maven命名转换,我正在使用project.nameproject.build.finalName进行一些测试以使用适当的名称.

我定义的用于为根工件创建project.name的模式是company-${project.artifactId},用于模块和子模块的模式是${project.parent.name}-${project.artifactId}:

  • company-any-artifact-any-module1
  • company-any-artifact-any-module2-any-submodule1
  • company-any-artifact-any-module2-any-submodule2

project.build.finalName的模式为${project.name}-${project.version}:

  • company-any-artifact-any-module1-1.0.jar
  • company-any-artifact-any-module2-any-submodule1-2.0.jar
  • company-any-artifact-any-module2-any-submodule2-3.0.war

但是maven不会生成这些文件,而是给我一个StackOverflowError.

2.重现错误的示例

您可以从github克隆此示例: https://github.com/pauloleitemoreira/company -任何人工制品

在github中,有一个 master 分支,将重现此错误.并且有一个 only-modules 分支,它可以正常工作我想使用${project.parent.name}生成jar finalName的示例.

让我们考虑一个具有一个root pom构件,一个pom模块和一个子模块的maven项目.

-any-artifact
     |
     |-any-module      
           |
           |-any-submodule

2.1任何伪像

<?xml version="1.0" encoding="UTF-8"?>
<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.company</groupId>
    <artifactId>any-artifact</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <name>company-${project.artifactId}</name>

    <modules>
        <module>any-module</module>
    </modules>

    <!-- if remove finalName, maven will not throw StackOverflow error -->
    <build>
        <finalName>${project.name}-${project.version}</finalName>
    </build>
</project>

2.2任意模块

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <parent>
        <artifactId>any-artifact</artifactId>
        <groupId>com.company</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.company.any-artifact</groupId>
    <artifactId>any-module</artifactId>
    <packaging>pom</packaging>

    <name>${project.parent.name}-${project.artifactId}</name>

    <modules>
        <module>any-submodule</module>
    </modules>
</project>

2.3任意子模块

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <parent>
        <artifactId>any-module</artifactId>
        <groupId>com.company.any-artifact</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.company.any-artifact.any-module</groupId>
    <artifactId>any-submodule</artifactId>

    <name>${project.parent.name}-${project.artifactId}</name>
</project>

3.问题

尝试mvn clean install时,maven给了我StackOverflowError:

Exception in thread "main" java.lang.StackOverflowError
    at org.codehaus.plexus.util.StringUtils.isEmpty(StringUtils.java:177)
    at org.codehaus.plexus.util.introspection.ReflectionValueExtractor.evaluate(ReflectionValueExtractor.java:194)
    at org.codehaus.plexus.util.introspection.ReflectionValueExtractor.evaluate(ReflectionValueExtractor.java:163)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:266)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:174)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:429)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:174)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:429)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:174)
    at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)

重要的是要知道错误仅在我们使用子模块时才会发生.如果我们使用根POM工件和jar模块创建项目,则不会发生该错误.

4.问题

为什么仅当我们使用子模块时才会发生此错误?

有解决我问题的建议吗?我是否应该忘记它,并按照我想要的模式为每个项目手动设置project.nameproject.build.fileName?

重要更新:

一些答案​​只是说要使用 &{parent.name} ,但不起作用.拜托,这是一个悬而未决的问题,在回答这个问题之前,请考虑使用Maven version 3.3.9测试您的解决方案.

Maven版本3.3.9

编辑 -在发生错误的阶段向问题中添加详细信息,直到prepare-package阶段一切正常,但是StackOverflow发生在package项目的Maven生命周期阶段.

解决方案

对您问题的严格回答是,${project.parent.name}作为模型插值过程的一部分进行解析.反过来,您有一个StackOverflowError,位于代码的完全不同的位置,即在……构建项目的最终JAR时.

第1部分:建立的模型有误

这就是发生的情况.在项目上启动Maven命令时,它要执行的第一步是创建项目的有效模型.这意味着读取您的POM文件,使用已激活的概要文件进行推理,应用继承,对属性执行插值...所有这些都为您的项目构建了最终的Maven模型.这项工作是由 Maven模型构建器组件完成的. >

构建模型的过程非常复杂,许多步骤可能分为两个阶段,但是我们在 Modello 从源.mdo文件生成的,并且该来源仅定义<parent>元素的"noreferrer"> groupIdartifactIdversionrelativePath (以及自定义的id).在文档中>

所有这些的结果是,在执行模型插值后,标记${project.parent.name}将不会被替换.而且,从中构造的MavenProject的名称将包含未替换的${project.parent.name}.您可以在日志中看到此示例项目中的

 [INFO] Reactor Build Order:
[INFO] 
[INFO] company-any-artifact
[INFO] ${project.parent.name}-any-module
[INFO] ${project.parent.name}-any-submodule
 

意味着Maven认为项目any-module的实际名称为${project.parent.name}-any-module.

第2部分:怪异开始

我们现在是正确创建甚至编译反应堆中所有项目的时候.实际上,理论上所有内容都可以正常工作,但项目本身的名称完全不正确.但是,您遇到了一个奇怪的情况,在使用maven-jar-plugin创建JAR时,它失败了.在您的示例中,构建失败并显示以下日志:

 [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ any-submodule ---
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] company-any-artifact ............................... SUCCESS [  0.171 s]
[INFO] ${project.parent.name}-any-module .................. SUCCESS [  0.002 s]
[INFO] ${project.parent.name}-any-submodule ............... FAILURE [  0.987 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
 

表示在构建模型后出现了一些问题.原因是插件default-value="${project.build.finalName}" * @required */ private String finalName;

注意project.build.finalName作为子模块生成的JAR名称的默认值.注入和变量的内插由另一个名为不变.

  • Maven现在尝试在any-submodule上插值${project.parent.name},它再次正常工作并返回${project.parent.name}-any-module.
  • Maven现在尝试在any-submodule ...上内插${project.parent.name},该方法可以工作并返回${project.parent.name}-any-module,因此它尝试评估${project.parent.name} ...
  • 您会看到这里发生了无尽的递归,这导致您拥有StackOverflowError.这是PluginParameterExpressionEvaluator中的错误吗?尚不清楚:这是由于最初没有正确替换的模型值所致.从理论上讲,它可以处理评估${project.parent}的特殊情况,并在此父项目上创建一个新的PluginParameterExpressionEvaluator,而不是始终在当前项目上工作.如果您对此有强烈的想法,请随时创建 JIRA问题.

    第3部分:为什么没有子模块也能工作

    使用上面所说的内容,您现在可以推断出为什么在这种情况下它可以工作.让我们来解释一下Maven需要做什么来评估最终名称,就像必须注入Maven Jar插件中一样:

    • any-module上的JAR插件注入项目的最终名称,名为${project.parent.name}-any-module.
    • 感谢您从父项目继承,并且在最顶层的POM项目中声明了<finalName>,它继承了<finalName>${project.name}-${project.version}</finalName>.
    • Maven现在尝试为any-module内插${project.name}.
    • 此解析为${project.parent.name}-any-module,与以前相同.
    • Maven现在尝试为any-module内插${project.parent.name}.像以前一样,它可以正常工作:MavenProject已构建并且this maven naming conversion, I am making some tests with project.name and project.build.finalName to have an appropriate name.

      The pattern I defined to create project.name for the root artifact is company-${project.artifactId} and for the modules and sub-modules is ${project.parent.name}-${project.artifactId}:

      • company-any-artifact-any-module1
      • company-any-artifact-any-module2-any-submodule1
      • company-any-artifact-any-module2-any-submodule2

      The pattern for project.build.finalName is ${project.name}-${project.version}:

      • company-any-artifact-any-module1-1.0.jar
      • company-any-artifact-any-module2-any-submodule1-2.0.jar
      • company-any-artifact-any-module2-any-submodule2-3.0.war

      But instead of producing these files, maven gives me a StackOverflowError.

      2. The example to reproduce the error

      You can clone this example from github: https://github.com/pauloleitemoreira/company-any-artifact

      In github, there is the master branch, that will reproduce this error. And there is only-modules branch, that is a working example that uses ${project.parent.name} to generate the jar finalName as I want.

      Let's consider a maven project with one root pom artifact, one pom module and one submodule.

      -any-artifact
           |
           |-any-module      
                 |
                 |-any-submodule
      

      2.1 any-artifact

      <?xml version="1.0" encoding="UTF-8"?>
      <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.company</groupId>
          <artifactId>any-artifact</artifactId>
          <packaging>pom</packaging>
          <version>1.0-SNAPSHOT</version>
      
          <name>company-${project.artifactId}</name>
      
          <modules>
              <module>any-module</module>
          </modules>
      
          <!-- if remove finalName, maven will not throw StackOverflow error -->
          <build>
              <finalName>${project.name}-${project.version}</finalName>
          </build>
      </project>
      

      2.2 any-module

      <?xml version="1.0" encoding="UTF-8"?>
      <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>
      
          <parent>
              <artifactId>any-artifact</artifactId>
              <groupId>com.company</groupId>
              <version>1.0-SNAPSHOT</version>
          </parent>
      
          <groupId>com.company.any-artifact</groupId>
          <artifactId>any-module</artifactId>
          <packaging>pom</packaging>
      
          <name>${project.parent.name}-${project.artifactId}</name>
      
          <modules>
              <module>any-submodule</module>
          </modules>
      </project>
      

      2.3 any-submodule

      <?xml version="1.0" encoding="UTF-8"?>
      <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>
      
          <parent>
              <artifactId>any-module</artifactId>
              <groupId>com.company.any-artifact</groupId>
              <version>1.0-SNAPSHOT</version>
          </parent>
      
          <groupId>com.company.any-artifact.any-module</groupId>
          <artifactId>any-submodule</artifactId>
      
          <name>${project.parent.name}-${project.artifactId}</name>
      </project>
      

      3. Problem

      When try to mvn clean install, maven gives me a StackOverflowError:

      Exception in thread "main" java.lang.StackOverflowError
          at org.codehaus.plexus.util.StringUtils.isEmpty(StringUtils.java:177)
          at org.codehaus.plexus.util.introspection.ReflectionValueExtractor.evaluate(ReflectionValueExtractor.java:194)
          at org.codehaus.plexus.util.introspection.ReflectionValueExtractor.evaluate(ReflectionValueExtractor.java:163)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:266)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:174)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:429)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:174)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:429)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:174)
          at org.apache.maven.plugin.PluginParameterExpressionEvaluator.evaluate(PluginParameterExpressionEvaluator.java:143)
      

      It is important to know that the error occurs only when we are working with submodules. If we create a project with a root POM artifact and a jar module, the error don't occur.

      4. The question

      Why this error occurs only when we are using submodules?

      Any suggestion to solve my problem? Should I forget it and set project.name and project.build.fileName manually for each project, following the pattern I want?

      IMPORTANT UPDATED:

      Some answers just say to use &{parent.name}, but it does not work. Please, it is a question with a bounty, consider test your solution with Maven version 3.3.9, before answering this question.

      Maven version 3.3.9

      Edit - Adding details to the question with the phase when the error occurs, things are working fine until the prepare-package phase, but the StackOverflow occurs at the package phase on maven lifecycle for the project.

      解决方案

      The strict answer to your question is that ${project.parent.name} will not be resolved as part the model interpolation process. And in turn, you have a StackOverflowError, in a completely different place of the code, namely when... building the final JAR of your project.

      Part 1: The Model built is wrong

      Here's what happens. When you're launching a Maven command on a project, the first action it takes is creating the effective model of the project. This means reading your POM file, reasoning with activated profiles, applying inheritance, performing interpolation on properties... all of this to build the final Maven model for your project. This work is done by the Maven Model Builder component.

      The process of building the model is quite complicated, with a lot of steps divided in possibly 2 phases, but the part we're interested in here in the model interpolation part. This is when Maven will replace in the model all tokens denoted by ${...} with a calculated value. It happens after profiles are injected, and inheritance is performed. At that point in time, the Maven project, as represented by a MavenProject object, doesn't exist yet, only its Model is being built. And it is only after you have a full model that you can start constructing the Maven project from it.

      As such, when interpolation is done, it only reasons in terms of the information present in the POM file, and the only valid values are the ones mentioned in the model reference. (This replacement is performed by the StringSearchModelInterpolator class, if you want to look at the source code.) Quite notably, you will notice that the <parent> element in the model does not contain the name of the parent model. The class Model in Maven is actually generated with Modello from a source .mdo file, and that source only defines groupId, artifactId, version and relativePath (along with a custom id) for the <parent> element. This is also visible in the documentation.

      The consequence of all that, is that after model interpolation is performed, the token ${project.parent.name} will not be replaced. And, further, the MavenProject constructed from it will have a name containing ${project.parent.name} unreplaced. You can see this in the logs, in your sample project, we have

      [INFO] Reactor Build Order:
      [INFO] 
      [INFO] company-any-artifact
      [INFO] ${project.parent.name}-any-module
      [INFO] ${project.parent.name}-any-submodule
      

      Meaning that Maven consider the actual name of the project any-module to be ${project.parent.name}-any-module.

      Part 2: The weirdness begins

      We're now at a time when all of the projects in the reactor were correctly created and even compiled. Actually, everything should theoretically work just fine, but with only completely borked names for the projects themselves. But you have a strange case, where it fails at the creation of the JAR with the maven-jar-plugin. The build fails in your example with the following logs:

      [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ any-submodule ---
      [INFO] ------------------------------------------------------------------------
      [INFO] Reactor Summary:
      [INFO] 
      [INFO] company-any-artifact ............................... SUCCESS [  0.171 s]
      [INFO] ${project.parent.name}-any-module .................. SUCCESS [  0.002 s]
      [INFO] ${project.parent.name}-any-submodule ............... FAILURE [  0.987 s]
      [INFO] ------------------------------------------------------------------------
      [INFO] BUILD FAILURE
      [INFO] ------------------------------------------------------------------------
      

      meaning that something went wrong well after the model was built. And the reason is that the plugin injects the name of the project as a parameter:

      
      /**
       * Name of the generated JAR.
       *
       * @parameter alias="jarName" expression="${jar.finalName}" default-value="${project.build.finalName}"
       * @required
       */
      private String finalName;
      

      Notice project.build.finalName as the default value of the generated JAR name for the submodule. This injection, and the interpolation of the variables are done by another class called PluginParameterExpressionEvaluator.

      So what happens in this:

      • The JAR plugin on the any-submodule injects the final name of the project, named ${project.parent.name}-any-submodule.
      • Thanks for inheritance from the parent projects, and the declaration of <finalName> in your top-most POM project, it inherits <finalName>${project.name}-${project.version}</finalName>.
      • Maven now tries to interpolate ${project.name} for any-submodule.
      • This resolves to ${project.parent.name}-any-submodule, due to Part 1.
      • Maven tries now to interpolate ${project.parent.name} for any-submodule. This works correctly: the MavenProject is built and getParent() will be called on the project instance, returning the concrete Maven parent project. As such, ${project.parent.name} will try to resolve the name of any-module, which is actually ${project.parent.name}-any-module.
      • Maven now tries to interpolate ${project.parent.name}-any-module, but still on the any-submodule project instance. For PluginParameterExpressionEvaluator, the root "project" on which to evaluate tokens hasn't changed.
      • Maven now tries to interpolate ${project.parent.name} on any-submodule, which, again, works correctly and returns ${project.parent.name}-any-module.
      • Maven now tries to interpolate ${project.parent.name} on any-submodule... which works and returns ${project.parent.name}-any-module so it tries to evaluate ${project.parent.name}...

      And you can see the endless recursion happening here, which results in the StackOverflowError you have. Is this a bug in PluginParameterExpressionEvaluator? This is unclear: it reasons on model values that were not correctly replaced in the first place. In theory, it could handle the special case of evaluating ${project.parent} and create a new PluginParameterExpressionEvaluator working on this parent project, instead of always working on the current project. If you feel strongly about this, feel free to create a JIRA issue.

      Part 3: Why it works without the sub module

      With what has been said above, you could now deduce why it works in this case. Let's reason with what Maven needs to do to evaluate the final name, as has to be injected in the Maven Jar Plugin:

      • The JAR plugin on the any-module injects the final name of the project, named ${project.parent.name}-any-module.
      • Thanks for inheritance from the parent project, and the declaration of <finalName> in your top-most POM project, it inherits <finalName>${project.name}-${project.version}</finalName>.
      • Maven now tries to interpolate ${project.name} for any-module.
      • This resolves to ${project.parent.name}-any-module, same as before.
      • Maven tries now to interpolate ${project.parent.name} for any-module. Just like before, this works correctly: the MavenProject is built and getParent() will be called on the project instance, returning the concrete Maven parent project. As such, ${project.parent.name} will try to resolve the name of any-artifact, which is actually company-any-artifact.
      • Interpolation has succeeded and stops.

      And you don't have any errors.

      这篇关于具有显式finalName的Maven无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆