当前位置: 首页 > 面试题库 >

具有显式finalName的Maven无法正常工作

盛超
2023-03-14
问题内容

1.背景

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

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

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

  • 公司任何工件任何模块1
  • 公司-任何工件-任何模块2-任何子模块1
  • 公司-任何工件-任何模块2-任何子模块2

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

  • 公司任何人工制品任何模块1-1.0.jar
  • 公司-任何工件-任何模块2-任何子模块1-2.0.jar
  • 公司-任何工件-任何模块2-任何子模块2-3.0.war

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

2.重现该错误的示例

您可以从github克隆此示例:https : //github.com/pauloleitemoreira/company-any-
artifact

在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 any-子模块

<?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
Model Builder
组件完成。

建立模型的过程非常复杂,许多步骤可能分为两个阶段,但是我们在模型插值部分对此感兴趣。这是Maven在模型${...}中用计算值替换所有标记所用的时间。它在注入配置文件并执行继承之后发生。在那个时候,以MavenProject对象表示的Maven项目还不存在,只有它Model正在构建中。只有拥有完整的模型之后,您才能开始从中构建Maven项目。

这样,完成插值时,仅根据POM文件中存在的信息进行解释,唯一有效的值是模型参考中提到的值。(StringSearchModelInterpolator如果要查看源代码,则由类执行此替换。)值得注意的是,您会注意到<parent>模型中的元素
包含父模型的名称。类ModelMaven中实际上是与生成MODELLO从源.mdo文件,和其源仅定义groupIdartifactIdversionrelativePath(连同定制id)的<parent>元件。这在文档中也可见。

所有这些的结果是,在执行模型插值后,${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部分:怪异开始

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

[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] ------------------------------------------------------------------------

表示在建立模型后出现了一些问题。原因是该插件将项目名称作为参数注入:

/**
 * Name of the generated JAR.
 *
 * @parameter alias="jarName" expression="${jar.finalName}" **default-

value=”${project.build.finalName}”*
* @required
/
private String finalName;

注意project.build.finalName,将其作为子模块生成的JAR名称的默认值。注入和变量的插值由另一个称为的类完成PluginParameterExpressionEvaluator

那么这会发生什么:

  • 上的JAR插件any-submodule注入了项目的最终名称,名为${project.parent.name}-any-submodule
  • 感谢您从父项目继承,并在<finalName>最顶层的POM项目中声明,它继承了<finalName>${project.name}-${project.version}</finalName>
  • Maven的现在尝试插值${project.name}any-submodule
  • ${project.parent.name}-any-submodule由于第1部分,因此解决为。
  • Maven的现在尝试插值${project.parent.name}any-submodule。这可以正常工作:MavenProject已构建并将getParent()在项目实例上调用,返回具体的Maven父项目。因此,${project.parent.name}将尝试解析的名称any-module,实际上是${project.parent.name}-any-module
  • Maven现在尝试进行插值${project.parent.name}-any-module但仍在any-submodule项目实例上。对于PluginParameterExpressionEvaluator"project"评估令牌的根没有改变。
  • Maven现在尝试在${project.parent.name}上进行插值any-submodule,该插值再次可以正常工作并返回${project.parent.name}-any-module
  • Maven现在尝试${project.parent.name}any-submodule…上进行插值,该方法可以工作并返回,${project.parent.name}-any-module因此它尝试评估${project.parent.name}

您会看到这里发生了无尽的递归,从而导致了StackOverflowError您的拥有。这是错误PluginParameterExpressionEvaluator吗?尚不清楚:这是因为最初没有正确替换的模型值。从理论上讲,它可以处理评估的特殊情况${project.parent}PluginParameterExpressionEvaluator在此父项目上创建新工作,而不是始终在当前项目上工作。如果对此有强烈的想法,请随时创建JIRA问题。

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

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

  • 上的JAR插件any-module注入了项目的最终名称,名为${project.parent.name}-any-module
  • 感谢您从父项目继承,并在<finalName>最顶层的POM项目中声明,它继承了<finalName>${project.name}-${project.version}</finalName>
  • Maven的现在尝试插值${project.name}any-module
  • 解析为${project.parent.name}-any-module,和以前一样。
  • Maven的现在尝试插值${project.parent.name}any-module。像以前一样,它可以正常工作:生成了MavenProjectgetParent()并将在项目实例上调用,返回具体的Maven父项目。因此,${project.parent.name}将尝试解析的名称any-artifact,实际上是company-any-artifact
  • 插值成功并且停止。

而且您没有任何错误。



 类似资料:
  • 问题内容: 我有一个数据库表 mytable ,它的列 名称 为Varchar格式,列 日期 为Datetime值。我想用按日期分组的某些参数来计算名称。这是我的工作: 似乎这里的范围语法有问题,如果我这样做的话,它确实可以正确计数以’a’开头的所有字段。但是,上面的查询为n返回0,尽管应该计算包含至少一个字母的所有字段。 问题答案: 你写: 似乎这里的范围语法有问题 的确如此。MySQL的LIK

  • 问题内容: 最近,我开始在Node.js上将MongoDB与Mongoose结合使用。 当我将Model.find方法与条件和字段一起使用时,猫鼬无法正常工作。 这不起作用: 顺便说一句,如果我删除了’_id’部分,这确实可行! 在MongoDB Shell中,两者都可以正常工作。 问题答案: 我通过谷歌搜索解决了这个问题:

  • 问题内容: 我每天都使用TimedRotatingFileHandler记录Django日志并轮换使用,但是检查日志文件,奇怪的问题是昨天的日志被截断了,今天的日志很少,昨天的日志丢失了! Django 1.4 uwsgi 1.4.9 Python 2.6 我从uwsgi开始8个django实例。setting.py是 我错过了什么?为什么旧的日志丢失了? 问题答案: 您不应该同时从多个进程登录到

  • 问题内容: 我正在尝试使用node-imagemagick库调整图像的大小,但无法正常工作。 我用来调整大小的代码是 引发错误 问题答案: 在Windows上,您还需要安装imagemagick exe。nodejs imagemagick库只是imagemagick exe的包装器。因此,只有安装了imagemagick exe并转换并标识可执行文件在路径中后,它才能起作用。

  • 问题内容: 我正在尝试使AspectJ编织工作在一个简单的Maven项目中,并且不确定它出了什么问题:当我使用“ mvn exec:java”运行代码时,看不到预期的输出。 我确定代码可以正常工作,因为我在STS中尝试了相同的方法,在这里工作良好。我只是想让AspectJ在Maven项目中工作。 任何有关如何调试此类问题的提示将不胜感激。 外观文件与代码位于同一文件夹中: Java文件: 问题答案

  • 问题内容: 这个问题已经在这里有了答案 : 字符串替换方法不替换字符 (5个答案) 2年前关闭。 我正在尝试将所有特殊字符替换为“%”,例如: 我的正则表达式是: 在在线工具中*它可以正常运行,但在Java中 弦保持不变。 *我尝试过:http : //www.regexplanet.com/ http://regex101.com/和其他 问题答案: 字符串是不可变的。您忘了将新变量重新分配给: