Controlling Maven final name of jar artifact
For Maven >= 3
<packaging>jar</packaging>
<build>
<finalName>WhatEverYouLikey</finalName>
</build>
See bug report/documentation.
(Credits to Matthew's and his comment)
For older Maven versions
You set the finalName
property in the plugin configuration section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<finalName>myJar</finalName>
</configuration>
</plugin>
As indicated in the official documentation.
Why is maven ignoring finalName and build-helper-maven-plugin when using deploy ?
No answer so far, so here is how I solved this problem.
I'm using the possibility offered by Maven (without any warning from Maven v3.2.1) to set the version of a pom externally : Allow continuous delivery friendly versions.
So I replace every <version>1.0.0-SNAPSHOT</version>
occurences in aggregator, parent, module (including dependencies) by <version>${revision}</version>
.
And to setup my timezoned timestamp in my release version, I use the "BUILD TIMESTAMP plugin" from Jenkins.
So the maven deploy command line in jenkins becomes in "Build > Goals and options" : deploy scm:tag -Drevision=1.0.0_$BUILD_TIMESTAMP
No offense to @khmarbaise, most credits to : Maven Release Plugin: Dead and Buried
How to make sure the distribution file for maven project have name that doesn't relate to a certain version, instead always contain the latest
This means that your remote build changes the version before or during the build.
Look at the gitlab build script to figure out what happens there.
Maven with an explicit finalName won't work properly
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}
forany-submodule
. - This resolves to
${project.parent.name}-any-submodule
, due to Part 1. - Maven tries now to interpolate
${project.parent.name}
forany-submodule
. This works correctly: theMavenProject
is built andgetParent()
will be called on the project instance, returning the concrete Maven parent project. As such,${project.parent.name}
will try to resolve the name ofany-module
, which is actually${project.parent.name}-any-module
. - Maven now tries to interpolate
${project.parent.name}-any-module
, but still on theany-submodule
project instance. ForPluginParameterExpressionEvaluator
, the root"project"
on which to evaluate tokens hasn't changed. - Maven now tries to interpolate
${project.parent.name}
onany-submodule
, which, again, works correctly and returns${project.parent.name}-any-module
. - Maven now tries to interpolate
${project.parent.name}
onany-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}
forany-module
. - This resolves to
${project.parent.name}-any-module
, same as before. - Maven tries now to interpolate
${project.parent.name}
forany-module
. Just like before, this works correctly: theMavenProject
is built andgetParent()
will be called on the project instance, returning the concrete Maven parent project. As such,${project.parent.name}
will try to resolve the name ofany-artifact
, which is actuallycompany-any-artifact
. - Interpolation has succeeded and stops.
And you don't have any errors.
Spring Boot control target JAR file name
You can specify the artefact-name with the maven boot plugin:
In this case, it will be NewJarName.jar
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<finalName>NewJarName</finalName>
</configuration>
</execution>
</executions>
</plugin>
Related Topics
Certain Unix Commands Fail with "... Not Found", When Executed Through Java Using Jsch
Why Does Changing the Returned Variable in a Finally Block Not Change the Return Value
The Performance Impact of Using Instanceof in Java
Java - How to Find the Redirected Url of a Url
How to Get Active User's Userdetails
How to Use Raw SQL Within a Spring Repository
Can Someone Explain Mappedby in JPA and Hibernate
Quickly Read the Last Line of a Text File
Jfreechart Scaling of Boxplots with Several Categories
Very Confused by Java 8 Comparator Type Inference
What's the Difference Between Softreference and Weakreference in Java
Jdbc Connection Failed, Error: Tcp/Ip Connection to Host Failed
How to Obtain Method Parameter Name Using Java Reflection
Difference Between @Before, @Beforeclass, @Beforeeach and @Beforeall
Make Documentbuilder.Parse Ignore Dtd References
Java.Lang.Outofmemoryerror: Gc Overhead Limit Exceeded
How to Get a Unique Computer Identifier in Java (Like Disk Id or Motherboard Id)