Maven project version as expression, not constant - maven

I want to version my parent project differently than the rest of the modules that depend on it, for which I want to have common version.
This is since my parent is defining dependencyManagement, distributionManagement, buildManagement, *Management... Parent project really has quite different lifecycle than the rest of the modules. It updates seldomly. It would almost never update if not changing the version for the rest of the modules.
I basically want to do
<parent>
<groupId>com.mycompany</groupId>
<artifactId>myparent</artifactId>
<version>5</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>myApp</artifactId>
<version>${next-version}</version>
and in the parent
<groupId>com.mycompany</groupId>
<artifactId>myparent</artifactId>
<version>5</version>
<properties>
<next-version>1.2.1-SNAPSHOT</next-version>
</properties>
While typing this it occurred to me - should this be done by having intermediate parent?

Well, it turns out that Maven itself has multiple levels of inheritance. They are in fact using intermediate parent poms. They have something like this:
org.apache:apache:16 > org.apache.maven:maven-parent:26 > org.apache.maven:maven:3.3.1-SNAPSHOT > org.apache.maven:maven-core:{inherited.from.parent}.

Related

Can modules referring to parent pom by relative path be depended on by 3rd parties?

I have a parent module, which defines its version as follows:
<groupId>org.group</groupId>
<artifactId>parent-id</artifactId>
<packaging>pom</packaging>
<version>${library.version}</version>
<properties>
<library.version>1.0.0</library.version>
</properties>
Then I have a sub module, which points to its parent as follows:
<parent>
<groupId>org.group</groupId>
<artifactId>parent-id</artifactId>
<version>${library.version}</version>
<relativePath>../../</relativePath>
</parent>
<artifactId>child-id</artifactId>
<packaging>jar</packaging>
And I depend on it in my other projects like so:
<dependency>
<groupId>org.group</groupId>
<artifactId>child-id</artifactId>
<version>1.0.0</version>
</dependency>
This results in the following error for me:
Failed to read artifact descriptor for org.group:child-id:1.0.0: Failure to find org.group:parent-id:pom:${library.version}
Can this problem be solved without resorting to mvn versions:set in my multi module project to manage explicit versions in all poms?
/edit: currently solved this problem with a workaround that makes using mvn versions:set a little easier.

Update parent version and artefactId

I want to dynamically update my parent version and artefactId.
Let's say I have the following pom.xml
<parent>
<groupId>com.company</groupId>
<artifactId>my-parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>my-child</artifactId>
<version>1.0-SNAPSHOT</version>
Is there any possibility to update (set) parent artefactId/version.
I.e. I can set a child version via versions plugin
mvn org.codehaus.mojo:versions-maven-plugin:2.7:set -DnewVersion=1.2.3-SNAPSHOT
Is there something like it for parent updating?
You can use versions:update-parent to update your parent pom to the latest version. I never heard of a plugin to change the artifactId.
I would be interested to know why more than parent pom is required.

Maven version not getting updated in the .POM file

I am using Maven for building my code. I created module based maven structure like below
Parent-POM
Sub-Parent1
SP1_Child1
SP1_Child2
SP1_Child3
Sub-Parent2
SP2_Child1
SP2_Child2
SP2_Child3
All my module versions, and external dependency versions are maintained in the Parent POM. Everything works fine when I do a complete mvn install, but when I try to build one sub module like SP1_Child1, then the build fails, because it is not able to identify the version of its dependencies. I checked the maven repository in my local machine, and all my modules were installed, but the .POM files do not have the version numbers. This is probably because the where the mvn install on the Parent POM is not replacing the ${module.version} with the actual version for the child modules.
Parent-POM
<project ..>
<groupId>the.company.project</groupId>
<artifactId>Parent-POM</artifactId>
<version>1.0-SNAPSHOT</version>
...
<properties>
<module.version>1.0</module.version>
</properties>
</project>
SP1_Child1
<project ..>
<parent>
...
</parent>
<groupId>the.company.project</groupId>
<artifactId>SP1_Child1</artifactId>
<version>${module.version}</version>
...
</project>
How how can my mvn install update the versions in the .POM files in the maven repository? Or how can I run one of my sub-modules without any version errors?
The default layout of a child pom should look like this.
<project ..>
<parent>
<groupId>the.company.project</groupId>
<artifactId>SP1_Child1</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>the.company.project</groupId>
<artifactId>SP1_Child1</artifactId>
...
</project>
But you child should not define version separately only in the parent element without using a property. The version is automatically inherited to the child module from the parent. If you have the same group you also don't need to define the group in child. You can use it like this:
<project ..>
<parent>
<groupId>the.company.project</groupId>
<artifactId>SP1_Child1</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>SP1_Child1</artifactId>
...
</project>
Taking the SP1_Child1 version from parent will be very annoying for you because it will force you to install a new version of the parent for any new version of the SP1_Child1 project.
There are 2 different possible situations :
You want to be able to manage different project, with different lifecycles.
Then you specify a version in the SP1_Child1 project, and you specify the version of SP1_Child1 to be used by other projects in the parent POM (in this case, the 2 values can be different).
Your application is monolithic, even if it is organized in different modules for convenience. Then in this case, the best is to do what khmarbaise advises, keep one version for all your projects, and inherit the version from the parent.

how to handle versions in maven?

I have all these version numbers throughout parent pom and children poms including the parent reference like so
<parent>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-core</artifactId>
<version>${parent.version}</version>
</parent>
and dependency references to other child projects like so
<dependency>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-shared</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
and finally the declaration of the version of the thing we are building
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>artifcat</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ifp-shared</name>
<url>http://maven.apache.org</url>
EDIT based on some answers which solved half the question...
We want to have all the versions be ${project.version} since it is really just one project with one release number.
I can seem to do ${project.version} in the dependency but this does not work in the parent xml code above. Is there another way? (man, I should really just switch to gradle).
thanks,
Dean
<parent>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-core</artifactId>
<version>1.2.3-SNAPSHOT</version> <!-- real version-->
</parent>
<artifactId>blah</artifactId>
<!-- No version here, will be inherited -->
<dependency>
<groupId>com.cigna.ifp</groupId>
<artifactId>ifp-shared</artifactId>
<version>${project.version}</version>
</dependency>
project.version is what you want. Not parent.version.
You need to use dependencyManagement tag to centerilize the versions in the parent pom for the dependencies.
See this question and answers
differences between dependencymanagement and dependencies in maven
For you your own modules, some of the properties are inherited from the parent pom. You will need to declare the parent version in each child but you don't need to declare a groupId/version in your child poms if you want them to be same as their parent's.
We switched to gradle which works fabulously now. Every automated build a new version is released as 1.2.x where x is the next build number. Downstream, projects depend on 1.2.+. This allows every release to be official so QA can test it, reject it or go, yup, build 1.2.568 is the release we will release to the world. Projects can depend on 1.2. but then they don't get bug fixes. This seems to work much better than all that snapshot nonsense as you give QA a snapshot and they approve and you have to change and do another build. We want every build to look official so they can release the one that happens to pass all QA tests.

Warning on using project.parent.version as the version of a module in Maven 3

In maven multi-module projects where I want each of the modules to always keep the same version as the parent, I've typically done something like the following in the module's pom.xml:
<parent>
<groupId>com.groupId</groupId>
<artifactId>parentArtifactId</artifactId>
<version>1.1-SNAPSHOT</version>
</parent>
<groupId>com.groupId</groupId>
<artifactId>artifactId</artifactId>
<packaging>jar</packaging>
<version>${project.parent.version}</version>
<name>name</name>
Since I started using maven 3.0-alpha-5, I get the following warning for doing so.
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.groupid.artifactId:name:jar:1.1-SNAPSHOT
[WARNING] 'version' contains an expression but should be a constant. # com.groupid.artifactId:name::${project.parent.version}, /Users/whaley/path/to/project/child/pom.xml
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
I'm curious to know what the real problem with tying a module's version to the parent version is, if any? Or is this a case of a general warning when any expression, regardless of whether it's project.parent.version, is used for the version element.
I'm curious to know what the real problem with tying a module's version to the parent version is, if any? Or is this a case of a general warning when any expression, regardless of whether it's project.parent.version, is used for the version element.
Well, that would be easy to test. Because I was curious, I just did it for you using the following pom:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>parent</artifactId>
<groupId>com.mycompany</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>module</artifactId>
<version>${myversion}</version>
<name>module</name>
<url>http://maven.apache.org</url>
<properties>
<myversion>1.0-SNAPSHOT</myversion>
</properties>
...
</project>
And maven is indeed complaining:
[WARNING] 'version' contains an expression but should be a constant. # com.mycompany:module:${myversion}, /home/pascal/Projects/maven-maven3-testcase/module/pom.xml
To be honest, I think that maven is right here, it doesn't make much sense to use a property for the <version> element (at least not for project.version) and it's nice to have maven complaining about it.
And if you want to use the parent pom version in sub-modules, just remove the <version> tag from the child poms, they will inherit the version from the parent. What you are currently doing is unnecessary.
I might be late here to discuss on this. I got a simple solution for this WARNING.
First of all, if you want that all child modules will take same version as parent, then you just remove <version> tag from child POM and as you include <parent> in child POM, that should be there.
In absence of <version> in child POM, it will automatically take Parent POM version.
Now if you want to use property in parent POM version and want to get the same in all child-modules, you can go through as follow.
There is no limitation on using property in <version> part of parent or child POM. But if you use your own xml tag for specifying that or you use your own property, then WARNING comes, (although this is just warning, everything works as expected).
But if you want to get rid of this WARNING, you can follow these steps:
Create <properties> inside POM.xml as below
<properties>
<revision>1.0.0</revision> <!-- Put your version -->
</properties>
In <version> of the POM.xml, put as follow
<version>${revision}</version>
Sample code snippet (for multi-module project):
<groupId>abc.xyz</groupId>
<artifactId>pqr</artifactId>
<!-- <version>1.0.0</version> -->
<version>${revision}</version>
<packaging>pom</packaging>
<description>Parent POM</description>
<properties>
<revision>1.0.0</revision>
</properties>
Note: Instead of <revision>, if you use any other name (for example, <my.version>), you will face that WARNING
Now if you want to pass version during mvn deploy, you can use mvn deploy "-Drevision=1.0.0-SNAPSHOT" and similarly for mvn install also.
Now if above configuration, you want to use as Parent POM, and you want to use same version in all child module, that can also be done. In each child module POM, use below
<parent>
<groupId>abc.xyz</groupId>
<artifactId>Parent</artifactId>
<!-- <version>1.0.0</version> -->
<version>${revision}</version>
</parent>
<groupId>abc.xyz</groupId>
<artifactId>Child</artifactId>
<!-- <version>1.0.0</version> --> <!-- Automatically inherit parent POM version -->
<name>Demo</name>
For reference, you can go through maven multi module setup
It seems that the warning is correct. See MNG-4717: "the pom that gets deployed will not have the property value resolved, so
anyone depending on that pom will pick up the dependency as being the
string uninterpolated with the ${ } and much hilarity will ensue in your
build process." "However, if one uses flatten-maven-plugin the deployed pom gets a resolved value."

Resources