versions-maven-plugin on mutli module project with aggregator pom does not set versions on modules - maven

I have a multi module project with two POMs, one aggregates the modules the other one is the parent of the modules.
<groupId>company</groupId>
<artifactId>aggregator-pom</groupId>
<version>1.0.0</version>
<modules>
<module>module-A</module>
<module>module-B</module>
</modules>
Child module pom looks like:
<parent>
<groupId>company</groupId>
<artifactId>parent-pom</artificatId>
<version>2.0.0</version>
</parent>
<groupId>company</groupId>
<artifactId>module-A</artificatId>
<version>1.1.0</version>
I want to execute versions:set on the aggregator-project to update the versions on the modules (A, B), but it seems that the versions plugin does not support this use case. The excat call is:
build-helper:parse-version versions:set -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}-${SVN_REVISION}
So the intention is that the build-helper plugin reads the current version with the help of jenkins we append the svn revision number to the version. This should be done on every module defined in the aggregator project. If I call this for just one independent project it works well. If the versions-plugin does not support this use case how can I achieve this?

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.

Jenkins fails to build multi-module Maven project

I have a multi-module Maven project where I have multiple micro services as modules so I have modules listed in my parent pom.xml like below:
<modules>
<module>core</module>
<module>model-base</module>
<module>module1</module>
<module>module2</module>
...
<module>module5</module>
<module>module7</module>
<module>module6</module>
</modules>
Here the module7 is dependent on module5, 6 so I have dependencies listed like below in my module7 pom.xml:
<parent>
<artifactId>pojectA</artifactId>
<groupId>com.domain</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>module7</artifactId>
<dependencies>
<dependency>
<groupId>com.domain</groupId>
<artifactId>core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.domain</groupId>
<artifactId>module5</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.domain</groupId>
<artifactId>module6</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
When I run mvn clean package in my local the module5, 6 called before the module7 as expected but in Jenkins it is trying to build module 5 then module7 making build fail saying:
[ERROR] Failed to execute goal on project module7: Could not resolve dependencies for project module7:jar:1.0-SNAPSHOT: Could not find artifact module6:jar:1.0-SNAPSHOT -> [Help 1]
Do I need to run any other jobs or re-order the modules in my pom.xml, how is it differ from local to Jenkins? Appreciate any help on this.
The order of modules is not relevant. Maven recognizes which project depends on which other project(s) and sets the build order in the reactor accordingly. See POM Reference, Aggregation (or Multi-Module):
You do not need to consider the inter-module dependencies yourself when listing the modules, i.e. the ordering of the modules given by the POM is not important. Maven will topologically sort the modules such that dependencies are always build before dependent modules.
Add Pre-Step as per below attached screenshot. This will compile all your top modules.
Then we can execute which ever module we want.
As is probably quite well understood, the issue is that the dependencies between the child modules fail because they aren't installed in the local repository yet (because they are yet to be built). The goal that causes this (for me anyway) is mvn test, which is invoked by mvn package. Your local build probably works because at some point you've done a mvn install and this has bootstrapped your system.
In Jenkins the only way I've found to make these builds work is to use the Pre-build step invoking a Maven target of install, and then build the main step as usual.

Maven - import / group all modules of project

I have a parent project with around 20 child modules:
<project>
<modules>
<module>module-1</module>
<module>...</module>
<module>module-20</module>
</modules>
</project>
I would like to use this project as one single entity, with all 20 modules included, in other projects. What is the convenient way to do this in Maven?
Should I make a new child module which imports the other 20 modules and refer to this project? Should this be a JAR or a POM project?
<project>
<packaging>jar</packaging>
<dependencies>
<dependency>... module-1 ...</dependency>
<dependency>...</dependency>
<dependency>... module-20 ...</dependency>
</dependencies>
</project>
I think the way you mentioned in your question is a good idea. It is actually mentioned as a best practice in the Maven book, quoting:
If you have a set of dependencies which are logically grouped together. You can create a project with pom packaging that groups dependencies together.
You can create a new module called module-all, which would be of pom packaging, that simply has a dependency on each of the modules. The packaging should be pom because the primary artifact of this module will only be the pom.xml (there will be no sources to compile, no JAR...). Then, in your external projects, you can simply add a dependency to this new module (as <type>pom</type>) and every module-i dependencies will be included transitively.
There would be a cave-at if all of your modules did not share the same version: there would need to be a reference to a specific version of a specific module and you would have to update the module-all version each time a module's version changes. However, if they all share the same version, module-all release cycle would be in line with module-i's.

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 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.

Resources