Pau*_*ulo 18 java stack-overflow maven maven-package
1.背景
我的Maven项目有很多的模块和子模块与jars和wars一切工作.我也可以在服务器上部署它而没有任何问题.
我决定遵循这个maven命名转换,我正在进行一些测试project.name并project.build.finalName拥有一个合适的名称.
我定义project.name为根工件创建的模式是company-${project.artifactId},对于模块和子模块是${project.parent.name}-${project.artifactId}:
模式project.build.finalName是${project.name}-${project.version}:
但maven没有生成这些文件,而是给了我一个StackOverflowError.
2.重现错误的示例
你可以从github克隆这个例子:https://github.com/pauloleitemoreira/company-any-artifact
在github中,有一个master分支,它将重现此错误.还有only-modules分支,这是一个工作示例,用于${project.parent.name}生成finalName我想要的jar .
让我们考虑一个带有一个根pom工件,一个pom模块和一个子模块的maven项目.
-any-artifact
|
|-any-module
|
|-any-submodule
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
重要的是要知道只有在我们使用子模块时才会发生错误.如果我们使用根POM工件和jar模块创建项目,则不会发生错误.
这个问题
为什么只有在我们使用子模块时才会出现此错误?
有什么建议可以解决我的问题吗?我应该忘记它并按照我想要的模式手动设置project.name和project.build.fileName手动完成每个项目吗?
重要更新:
一些答案只是说使用&{parent.name},但它不起作用.Maven version 3.3.9在回答这个问题之前,请考虑使用赏金来考虑您的解决方案.
Maven版本3.3.9
编辑 - 在错误发生时使用阶段向问题添加详细信息,直到prepare-package阶段工作正常,但StackOverflow发生在package项目的maven生命周期阶段.
严格回答你的问题是,${project.parent.name}会不会被解析为部分型号插值处理.反过来,你有一个StackOverflowError完全不同的代码,即...构建项目的最终JAR.
这是发生了什么.当您在项目上启动Maven命令时,首先要执行的操作是创建项目的有效模型.这意味着读取您的POM文件,使用激活的配置文件进行推理,应用继承,对属性执行插值...所有这些都为您的项目构建最终的Maven模型.这项工作由Maven Model Builder组件完成.
构建模型的过程非常复杂,许多步骤可能分为两个阶段,但我们在模型插值部分对这里感兴趣的部分.这是Maven将在模型中替换所有用${...}计算值表示的标记.它在注入配置文件后发生,并执行继承.在那个时间点,由一个MavenProject对象表示的Maven项目尚不存在,只有它Model正在构建.只有在你拥有一个完整的模型之后,才可以从中开始构建Maven项目.
因此,在进行插值时,仅根据POM文件中存在的信息进行推理,并且唯一有效的值是模型参考中提到的值.(StringSearchModelInterpolator如果您想查看源代码,则此替换由类执行.)值得注意的是,您会注意到<parent>模型中的元素不包含父模型的名称.类ModelMaven中实际上是与生成MODELLO从源.mdo文件,和其源仅定义groupId,artifactId,version和relativePath(连同定制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
Run Code Online (Sandbox Code Playgroud)
这意味着Maven的考虑项目的实际名称any-module是${project.parent.name}-any-module.
我们现在正处于反应堆中的所有项目都正确创建甚至编译的时候.实际上,理论上一切都应该工作得很好,但项目本身只有完全不知名的名字.但是你有一个奇怪的例子,它在创建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] ------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
这意味着在模型建立之后出现了问题.原因是该插件将项目名称作为参数注入:
Run Code Online (Sandbox Code Playgroud)/** * 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.
那么这会发生什么:
any-submodule注入JAR插件的项目的最终名称,名称${project.parent.name}-any-submodule.<finalName>最顶层POM项目中的声明,它继承了<finalName>${project.name}-${project.version}</finalName>.${project.name}的any-submodule.${project.parent.name}-any-submodule由于第1部分,这解决了.${project.parent.name}的any-submodule.这工作正常:MavenProject构建并将getParent()在项目实例上调用,返回具体的Maven父项目.因此,${project.parent.name}将尽力解决的名字any-module,这实际上是${project.parent.name}-any-module.${project.parent.name}-any-module,但仍然在any-submodule项目实例上.因为PluginParameterExpressionEvaluator,"project"评估令牌的根没有改变.${project.parent.name}上any-submodule,这又可以正常工作并返回${project.parent.name}-any-module.${project.parent.name}上any-submodule......这工作,并返回${project.parent.name}-any-module所以它试图评估${project.parent.name}...你可以看到这里发生的无休止的递归,这导致StackOverflowError你拥有.这是一个错误PluginParameterExpressionEvaluator吗?这一点尚不清楚:它的原因是模型值首先没有被正确替换.理论上,它可以处理评估${project.parent}和创建PluginParameterExpressionEvaluator此父项目的新工作的特殊情况,而不是始终处理当前项目.如果您对此有强烈的感受,请随时创建JIRA问题.
通过以上所述,您现在可以推断出它在这种情况下的工作原理.让我们了解Maven需要做什么来评估最终名称,因为必须在Maven Jar插件中注入:
any-module注入JAR插件的项目的最终名称,名称${project.parent.name}-any-module.<finalName>最顶层的POM项目中声明它继承<finalName>${project.name}-${project.version}</finalName>.${project.name}的any-module.${project.parent.name}-any-module,和以前一样.${project.parent.name}的any-module.就像以前一样,这个工作正常:MavenProject构建并将getParent()在项目实例上调用,返回具体的Maven父项目.因此,${project.parent.name}将尽力解决的名字any-artifact,这实际上是company-any-artifact.而且你没有任何错误.
| 归档时间: |
|
| 查看次数: |
6488 次 |
| 最近记录: |