How to use a multi-module setup in maven? - spring

In Parent component, I am adding child modules inside tag.
<!-- Parent pom.xml -->
<groupId>com.acc.app</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
<modules>
<module>../child1/pom.xml</module>
<module>../child2.pom.xml</module>
</modules>
Where child1 and child2 are different packages outside Parent.
The purpose is that when I build parent, all children should also build automatically. In my local I am able to build Parent and all children but getting an error in Jenkins server.
Error: child1/pom.xml does not exist.
child2/pom.xml does not exist.

Related

Maven release plugin and using a single version in the parent pom

I have a multi-module maven project.
I hold the version in one location in the parent pom.xml as a property
and then use this in the parent pom.xml:
<project>
<artifactId>autoav</artifactId>
<version>${autoAvVersion}</version>
...
<properties>
<autoAvVersion>19.3.24-SNAPSHOT</autoAvVersion>
</properties>
</project>
And use this in the child module :
<project>
<groupId>com.mycompany.analysis</groupId>
<version>${autoAvVersion}</version>
<artifactId>analysisCore</artifactId>
<parent>
<groupId>com.mycompany.analysis</groupId>
<version>${autoAvVersion}</version>
<artifactId>autoav</artifactId>
<relativePath>../autoAV</relativePath>
</parent>
...
</project>
Maven release plugin, after running prepare+perform on the child project only (just for testing one module), changed my child pom version from
<version>${autoAvVersion}</version>
to
<version>19.3.25-SNAPSHOT</version>
So i suppose the release plugin did not think of cases using a single point version.
(By the way if i omit the version tag in the child, so it effectively gets it from the parent, the version tag without the property [19.3.25-SNAPSHOT] is still added to the child
Is there any solution to this ?

Build child module without building parent module if there is some changes in parent pom

I have a multi module project with more than 70 modules and it takes 3 Hrs to build the project with tests.
Parent pom.xml
...
<version>${revision}</version>
<properties>
<app.version>1.0</app.version
<properties>
.....
<modules>
<module>a<module>
<module>b<module>
<module>c<module>
.....
...
Child pom.xml
<parent>
<groupId>com.test</groupId>
<artifactId>parent</artifactId>
<version>${revision}</version>
</parent>
<artifactId>b</artifactId>
How to build only module b only if we change the version number in parent pom.xml
After upgrading the parent POM to a new version (and the reference to it in b's pom.xml), you could run :
mvn --projects b <maven_phase_you_want> # or mvn -pl b [...]
From Maven's help :
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path
However, this only works if the old version of your parent POM is already in your local repository, or at least is available (it have been deployed on a repository manager). Otherwise, you'll get an error because, even if specifying --projects b, Maven will try to resolve parent POM (that he won't find) for other modules a and c.

How to set project version to all projects for multimodule projects (with Versions-Maven-plugin)?

I have a multi module project that goes deeper then level 1. I'm starting to use 'versions-maven-pluging'.
From my topmost parent pom I ran :
mvn versions:set -DnewVersion=13.0.2
Then I got these (sample) pom files for the topmost parent and it's first child module:
Level 0
<project>
<groupId>com.company</groupId>
<artifactId>_parent-company</artifactId>
<version>13.0.0</version>
<modules>
<module>../subproject1</module>
</modules>
</project>
Level 1
<project>
<parent>
<groupId>com.company</groupId>
<artifactId>_parent-company</artifactId>
<version>13.0.2</version>
</parent>
<groupId>com.company</groupId>
<artifactId>_parent-subproject1</artifactId>
<version>13.0.0</version>
<packaging>pom</packaging>
<modules>
<module>../subproject1.1</module>
</modules>
</project>
Level 2
<project>
<parent>
<groupId>com.company</groupId>
<artifactId>_parent-subproject1</artifactId>
<version>13.0.0</version>
</parent>
<groupId>com.company.subproject1</groupId>
<artifactId>_parent-subproject1.1</artifactId>
<version>13.0.0</version>
<packaging>pom</packaging>
</project>
When I check the module of the parent in level 0, I see the version is unchanged. Then, the version in level 1, was changed so that is ok. Finally, in the level 2 project, nothing changed.
If I get to the level 1 parent directory, I can run a command to update the child submodule of this level (but not without errors since the repo was not updated for parent 13.0.2).
mvn versions:update-child-modules
Is there a way to change everyone from first parent to the lowermost leave project? For now we are building a single version of everything so no need to create versions for each parent.
Is there a simple workflow that could make simpler? For now this is what I'm about to do:
1- Manually change the version of the topmost parent.
Run theses (in level 0 directory):
mvn versions:set -DnewVersion=13.0.2
mvn -N install
Run theses (in level 1 directory):
mvn versions:set -DnewVersion=13.0.2
Strangely enough, when I run version:set in level 1, I get the proper result. The parent and all children project POMs are set with version 13.0.2. Any idea what could I be doing wrong?

In a multi-module build, why does a child module need to be told where to find the parent POM?

Consider the following scenario of a flat multi-module layout:
| parent-pom
| - pom.xml
| module1
| - pom.xml
Where parent-pom/pom.xml is the parent POM of all modules:
<groupId>my-group</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
...
...
<module>../module1</module>
Now, the pom.xml of module1 contains the following parent section:
<parent>
<groupId>my-group</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
</parent>
I'm starting with a clean local repository; none of the artifacts is pre-built, everything done from scratch. Trying to execute mvn install on parent-pom will result in an error, because the Maven reactor will look for my-group:base-pom in the local repository, fail (because it's not there) and then look for ../pom.xml.
Fine. My question is this: if the build of module1 is invoked through the build of parent-pom, why does Maven even have to look for the parent's pom.xml anywhere? when Maven comes to build module1, it already knows the following things:
The physical location, of the file system, of my-group:parent-pom:1.0.0.
The fact that module1 is rooted in my-group:parent-pom:1.0.0.
Why look elsewhere?
The Introduction to the POM:Project Inheritance:Example 2 told us as the following: -
The Scenario
However, that would work if the parent project was already installed in our local repository or was in that specific directory structure (parent pom.xml is one directory higher than that of the module's pom.xml).
But what if the parent is not yet installed and if the directory structure is
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml
The Solution
To address this directory structure (or any other directory structure), we would have to add the <relativePath> element to our parent section.
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
As the name suggests, it's the relative path from the module's pom.xml to the parent's pom.xml.
EDITED:
The getRelativePath told us as the following
Get the relative path of the parent pom.xml file within the check out. The default value is ../pom.xml. Maven looks for the parent pom first in the reactor of currently building projects, then in this location on the filesystem, then the local repository, and lastly in the remote repo. relativePath allows you to select a different location, for example when your structure is flat, or deeper without an intermediate parent pom. However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM. This feature is only for enhancing the development in a local checkout of that project.
I hope this may help.

What does the parent tag in Maven pom represent?

E.g.:
<parent>
<groupId>mycompany.trade.com</groupId>
<artifactId>mycompany.trade.</artifactId>
<version>1.1.1.0-SNAPSHOT</version>
</parent>
Does it mean that Maven will search for parent pom?
If yes, where, in which order? May be in folder up 1 level? Or in local repository or in repo?
Yes, maven reads the parent POM from your local repository (or proxies like nexus) and creates an 'effective POM' by merging the information from parent and module POM.
See also Introduction to the POM
One reason to use a parent is that you have a central place to store information about versions
of artifacts, compiler-settings etc. that should be used in all modules.
The common dependencies,Properties,constants etc can be definded in central parent project pom.xml
The main important thing is the parent project cannot be distributed and it looks quite similar to a regular "pom.xml" except that it also has a packaging tag
<groupId>com.company.demo</groupId>
<artifactId>MavenInheritance</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
The child now able to inherit this using
<parent>
<groupId>com.company.demo</groupId>
<artifactId>MavenInheritance</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
As the name suggests, we can point out a parent pom.xml file for the current pom.xml file. Doing so, dependencies, properties, constants and many more defined at the parent pom.xml file also get merged with the current pom.xml (child pom.xml) file. Say you have a parent tag in your projects pom.xml that looks like below:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
Then maven reads that parent POM from your local repository (or from repository managers like sonatype, jfrog, etc that you have configured) and creates a Resultant POM by combining the parent POM and your module’s POM.
To see the combined result use the following mvn command:
mvn help:effective-pom
This is the practice that is used in multi-modules projects where we need to inherit the dependencies from the parent projects.

Resources