Call hierachy of properties in pom.xml - maven

I have a maven project with multiple nested projects. All of them do always have the same version. Untill now, if I want to increase the version, I went through all pom.xml files and changed the version number.
Now, I wanted to outsource the version to the properties tag of the parent pom.xml file. It works, for all nested projects, but not for the parent pom itself.
In which order are the attributes in the pom.xml called? I can not reference
the project version in the parent pom.xml file.
The code snippet shows the parent pom.xml
<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">
<groupId>com.my.project</groupId>
<artifactId>my.project</artifactId>
<packaging>pom</packaging>
<version>${projectVersion}</version>
<properties>
<projectVersion>1.0.0</projectVersion>
...
</properties>
<modules>
<module>my.project.service</module>
<module>my.project.db</module>
...
</modules>
I expect the pom to take the version number defined in the properties. But it failes building with the error invalid reference format

I expect the pom to take the version number defined in the properties.
But it failes building with the error invalid reference format
By running a maven goal from the parent project, maven first binds the artifact/group/version in the current build process, so it uses the version defined here :
<version>${projectVersion}</version>
I can not reference the project version in the parent pom.xml file.
In this case, you could "cheat" by creating an aggregator/multimodule project that defines a not used/fake version (1.0-NOT-USED for example) that has as unique module the parent pom. When you build the aggregator/multimodule project, you can now pass as parameter the version to use in the parent project and all its modules.
As a side note, to use a central version for a set of projects, you should use the flatten maven plugin that relieves you from the hell version management.

Related

Packaging for reactor multi module build?

I suppose I've made something wrong failing to find answer for basic philosophical question:
What is the correct packaging for reactor build module for multi module maven project?
I'm using pom but I don't feel it's correct since the pom artifact is used by no one:
<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.example.project</groupId>
<artifactId>reactor-build</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>../config</module>
<module>../module1</module>
<module>../module2</module>
</modules>
</project>
The packaging pom is the only allowed packaging for aggregator projects, that is to say a project with modules like the one you have, and also for parent projects. From Inheritance:
The packaging type required to be pom for parent and aggregation (multi-module) projects.
Any attempt to use a different packaging will result in an error when trying to build the project, such as the following when using jar (or keeping the default):
[ERROR] 'packaging' with value 'jar' is invalid. Aggregator projects require 'pom' as packaging.

Does incrementing depending module version should increment parent module version?

I have parent module A that has module B as its dependency. If I increment version of B for just a simple bug fix, that does not change any API or break anything, do I still need to increment version of A?
Example:
A:1.10.0 --> B:2.5.0
fixing B to 2.5.1
In this case, A on Maven depends on older version of B, therefore, it seems it make sense to increate the version of A, too; so to have:
A:1.10.1 --> B:2.5.1
even though we didnt change anything in A.
Is this correct?
Yes, you are correct. If you change version of any of the dependency, you will need to build and release parent project again. This will create the new released version of your parent module A.
(Here, I am assuming that parent module A packaging type is other than pom. If the packaging type is pom, then its a different story altogether.)
Edited:
When you say parent project, you will declare its packaging as pom. It will have it's own version.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>parent</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>web-project</module>
</modules>
</project>
You can also refer to some modules (child projects) in your parent pom declaration.
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>parent</artifactId>
<version>0.1-SNAPSHOT</version>
</parent>
<artifactId>web-project</artifactId>
<packaging>war</packaging>
Then for submodules there is no need to declare any version for it. Parent version will be carried over to the child project. You can override version in the child project but that's not a common practice. So your parent pom version will be incremented automatically when you release it with maven. And this new version will be carried over to child projects (modules) also.
See this - Maven project version inheritance - do I have to specify the parent version?
So parent module A, I was referring to the above case.
And maven repo - can be of two types - local repository and remote repository. Local repo is where maven looks for resolviing dependencies. This is on your machine. If maven doesn't find it there, maven retrieve those depedencies from remote repository.

maven versions:set not updating parent pom

I've following parent pom file:
<?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.xyz</groupId>
<artifactId>abc</artifactId>
<version>1.0.0.36</version>
<packaging>pom</packaging>
<name>Common Data Access Framework</name>
<build>
<pluginManagement>
...
...
Now when I run following command from the same folder where I have this parent pom file:
mvn versions:set -DnewVersion=9.9.9.9
It will update the version details in all child modules and pom file "except" it's own (the parent). This is really strange as I'm running it from the very same folder.
I have hit a similar problem yesterday. The cause was that my parent pom.xml had leading whitespace before the xml tag. After removing it version:set worked as expected, setting the version across all poms,parent and children.
I don't know if this was the solution in your case but I'm posting this to save another poor soul hours of stupid debugging.
Tried the following here with Maven 3.3.3's mvn version:set -DnewVersion=... in the root folder:
- root
- sub-1
- sub-2
If the subs are just childs (with <parent>root</parent>), just the root POM's <project>/<version> is updated. The subs <parent>/<version>s are not!
If the subs are childs and modules, the root POM's <project>/<version> and the subs <parent>/<version>s are updated.
If the subs are just modules only the root POM's <project>/<version> is updated as expected.
This is different to your result but it's no less strange because versions:set says:
Sets the current project's version and based on that change propagates that change onto any child modules as necessary.
The sub modules were childs at each of two topmost runs mentioned above.
UPDATE
The reason for the parent POM not updated can be that 9.9.9.9 is not a standard Maven version:
Maven: The Complete Reference, 3.1.1 Project versions:
A project’s version number is used to group and order releases. Maven versions contain the following parts: major version, minor version, incremental version, and qualifier. In a version, these parts correspond to the following format:
<major version>.<minor version>.<incremental version>-<qualifier>
Developing Applications Using Continuous Integration, 7.1 How Version Numbers Work in Maven:
If you use a nonstandard versioning scheme, Maven release and version plug-in goals might not yield the expected results. Because basic string comparison is performed on nonstandard versions, version comparison calculates the order of versions incorrectly in some cases.

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.

Maven - How/Why/Should it work to set the parent version to be based on a property defined in the parent pom?

I have the following POM structures:
/home/projects/parent/pom.xml
<project>
<groupId>com.my.group</groupId>
<artifactId>project-super-parent</artifactId>
<version>${major.version}.${minor.version}</version>
<packaging>pom</packaging>
<properties>
<major.version>7</major.version>
<minor.version>5</minor.version>
<current.release.version>${major.version}.${minor.version}-SNAPSHOT</current.release.version>
...
</properties>
....
</project>
/home/projects/module1/pom.xml
<project>
<groupId>com.my.group</groupId>
<artifactId>module1</artifactId>
<version>${current.release.version}</version>
<packaging>jar</packaging>
<parent>
<groupId>com.my.group</groupId>
<artifactId>project-super-parent</artifactId>
<version>${major.version}.${minor.version}</version>
<relativePath>../parent</relativePath>
</parent>
...
</project>
Notice that the module does not know the version of it's parent - it uses a property defined in the parent, so this is a kind of a chicken & an egg problem.
The weird thing is - that this works - so when I want to change the major version of the product - I only change a single pom file (the parent).
The limitations to this solution is that I have to have all POM files on the file system.
My questions are: should this even work? How exactly does it work? Is it likely to stop working when I upgrade to maven 3? Is this a commonly used solution or an abuse of the system?
Currently using Maven 2.2.1 and Java 7.
Is this a commonly used solution or an abuse of the system?
That is not common, at least I have never seen it before. The versioning you have in parent/pom.xml and module1/pom.xml will cause a confusion. The parent has a RELEASED version of 7.5, while module1 has a SNAPSHOT version of 7.5. You should not be developing 7.5-SNAPSHOT if 7.5 is already released.
The simplest way to avoid duplication is to maintain the version only in the parent. You can just omit the version declaration in module1. Take a look another project, e.g. maven-3 source code for example. You will be able to see the the version is only declared in the parent pom, and not in any of its child poms.
maven-release-plugin will help you handle the version upgrade and release them for you.
Omitting the version element from the child pom gives error.
Property can be used in Main pom and the same can be inherited by child pom's. When you run the Main pom, build will result in success. Problems are
That you can not build the child pom independently
This does not work in case of transitive dependencies
if you upgrade to Maven 3 in future than it will give error "Non-resolvable parent pom
These problems can be resolved if we are able to update the project pom file as part of the build process before it gets installed in local repository

Resources