草庐IT

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

coder 2023-08-27 原文

1.背景

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

我决定遵循this maven naming conversion,我对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-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任意子模块
    <?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发生在项目的maven生命周期的package阶段。

    最佳答案

    对您问题的严格回答是,作为模型插值过程的一部分,${project.parent.name}将被而不是解决。反过来,您在代码的完全不同的地方(即在……构建项目的最终JAR时)具有StackOverflowError

    第1部分:建立的模型是错误的

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

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

    这样,进行插值时,仅根据存在于POM文件中的信息进行解释,唯一有效的值为mentioned in the model reference。 (如果要查看源代码,则由 StringSearchModelInterpolator 类执行此替换。)值得注意的是,您会注意到模型中的<parent>元素确实而不是包含父模型的名称。实际上,Maven中的Model类是使用Modello从源.mdo文件生成的,并且该源仅为groupId元素定义了 artifactId , version , relativePath and id (以及自定义的<parent>)。这也是可见的in the documentation

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

    我们现在是在 react 堆中所有项目都已正确创建甚至编译的时候。实际上,理论上所有内容都应该可以正常工作,但项目本身的名称完全不正确。但是您遇到了一个奇怪的情况,在使用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] ------------------------------------------------------------------------
    

    表示在建立模型后出现了一些问题。原因是插件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;
    


    注意project.build.finalName是子模块生成的JAR名称的默认值。注入(inject)和变量的内插由另一个称为 PluginParameterExpressionEvaluator 的类完成。

    那么这会发生什么:
  • any-submodule上的JAR插件将注入(inject)项目的最终名称${project.parent.name}-any-submodule
  • 感谢您从父项目继承,并在最顶层的POM项目中声明<finalName>,它继承了<finalName>${project.name}-${project.version}</finalName>
  • Maven现在尝试为${project.name}插值any-submodule
  • 由于第1部分的缘故,此解析为${project.parent.name}-any-submodule
  • 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,用于评估 token 的根"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,而不是始终在当前项目上工作。如果您对此深有感触,请随时创建a JIRA issue

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

    通过上面所说的,您现在可以推断出在这种情况下它为什么起作用了。让我们来解释一下Maven需要做什么来评估最终名称,就像必须注入(inject)Maven Jar插件中一样:
  • any-module上的JAR插件将注入(inject)项目的最终名称${project.parent.name}-any-module
  • 感谢您从父项目继承,并在最顶层的POM项目中声明<finalName>,它继承了<finalName>${project.name}-${project.version}</finalName>
  • Maven现在尝试为${project.name}插值any-module
  • 与以前一样,解析为${project.parent.name}-any-module
  • Maven现在尝试为${project.parent.name}插值any-module。像以前一样,它可以正常工作:生成MavenProject并将在项目实例上调用 getParent() ,返回具体的Maven父项目。因此,${project.parent.name}将尝试解析any-artifact的名称,该名称实际上是company-any-artifact
  • 插值已成功并停止。

  • 而且您没有任何错误。

    关于java - 具有显式finalName的Maven无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40336878/

    有关java - 具有显式finalName的Maven无法正常工作的更多相关文章

    1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

      我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

    2. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

      我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

    4. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

      我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

    5. ruby - 无法运行 Rails 2.x 应用程序 - 2

      我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

    6. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

      我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

    7. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

      我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

    8. java - 等价于 Java 中的 Ruby Hash - 2

      我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

    9. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

      关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

    10. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

      在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

    随机推荐