Is there a way to cascade the version of a parent pom? - maven

I have a root pom.xml that acts as a parent for several child pom.xml files, which is great if you have one or two child pom.xml files. I am working on a project that has 50+ child pom.xml files, and several releases going on at once. Everything is great until I need to update the version of the parent pom.xml files, which can be tedious. Is there a way to cascade the version of the parent pom.xml down to all child pom.xml files?
I had the idea to just create a property in the parent pom.xml for the current version, but that's not working.
EDIT
Here is a sample from my child pom.xml files:
<parent>
<groupId>myGroup</groupId>
<artifactId>myArtifactId</artifactId>
<version>1.0</version> <!-- This is the value that I would like to parameterize in my child pom.xmls -->
<relativePath>../../pom.xml</relativePath>
</parent>
As an aside, I am using Maven 3.0.3

You can do it this way:
Have an aggregator POM project, in which you specify all your child modules and then run this goal on the this aggregator project:
mvn versions:update-parent
This will update all child modules with the new parent version.
Alternatively you can use the same before each release:prepare goal of your child module, thus avoiding creating the aggregator module.
So in case you want to release a child module, you just run this goal:
mvn versions:update-parent release:prepare
This will ensure that the parent gets updated with a new version before it is being prepared for a release.
I read in your comment you are missing an scm tag. Example of usage in case of subversions might be:
<scm>
<developerConnection>scm:svn:https://your.domain/scm/svn/yourModule/trunk/</developerConnection>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<tagBase>https://your.domain/scm/svn/yourModule/tags</tagBase>
</configuration>
</plugin>
</plugins>
</build>
Release plugin does not work without a properly configured scm.
You do not need to configure the tagbase tag in release plugin in case you follow "trunk, tags, branches" best practice in your svn repository, see this answer.

I assume you having a thing like this:
+--root (pom.xml)
+--- module1 (pom.xml)
+---
In the root pom.xml:
<project ..>
<groupId>the.company.project</groupId>
<artifactId>the-artifact</artifactId>
<version>1.0-SNAPSHOT</version>
...
</project>
whereas in the childs you should have:
<project ..>
<parent>
<groupId>the.company.project</groupId>
<artifactId>the-artifact</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>the-artifact-child</artifactId>
</project>
For such purposes you should use the maven-release-plugin which handles the updating of the version in root as well in childs. If you don't use maven-release-plugin you can use the versions-maven-plugin which can handle the same things.

I had the same problem and what I did was slightly different than anything suggested so far. Assume that your project has the following folder structure:
parent
+-- child1
+-- child2_of_parent
+-- child3_of_parent
+-- child4
+-- child5_of_child4
Do note that except for child5_of_child4, all the rest of the projects have as parent the top level project parent. This is regardless of the folder structure.
Parent pom.xml:
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>1.1-SNAPSHOT</version>
All children pom.xml except for child5_of_child4 that has as parent child4:
<parent>
<groupId>...</groupId>
<artifactId>parent</artifactId>
<version>1.1-SNAPSHOT</version>
<relativePath>../parent</relativePath>
</parent>
You go to the parent directory and change its version from version from 1.1-SNAPSHOT to 1.2-SNAPSHOT. Then you do (more details here):
mvn versions:update-child-modules
As this is not recursive, it only works on the direct children of your parent project. In other words, all sub-modules will be updated to point to parent 1.2-SNAPSHOT except for child5_of_child4.

In your child pom.xml:
<parent>
<groupId>groupId</groupId>
<artifactId>parent.artifactId</artifactId>
<version>version</version>
<relativePath>../parent-pom</relativePath>
</parent>
<artifactId>child.artifactId</artifactId>

Just don't put the version in the child poms. It's inherited automatically. It will show up as a warning in Eclipse plugin if you edit there.

Related

project.build.sourceEncoding defined in Parent Pom Ignored in Child

Given a 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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme</groupId>
<artifactId>acme-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<java-version>1.8</java-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<com.acme.dynamite-version>0.0.1-SNAPSHOT</com.acme.dynamite-version>
// etc
</properties>
</project>
and child 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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.acme</groupId>
<artifactId>child</artifactId>
<version>dev-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>com.acme</groupId>
<artifactId>acme-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dynamite</artifactId>
<version>${com.acme.dynamite-version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
The property, com.acme.dynamite-version, which is explicitly referenced in the child pom is resolved, however project.build.sourceEncoding is ignored. The Jenkins build of 'mvn clean install' throws a warning:
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
Is there a way to get the child pom to recognize project.build.sourceEncoding? This is not a multi module project, I am just trying to consolidate properties in one place
Properties defined in a parent POM are inherited in the child POM... but for that, the parent POM defining those properties needs to be installed before the child is built. And this is the issue here:
Your parent, having a version 0.0.1-SNAPSHOT, right-fully declares the property <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>. However, that version of the parent defining this property is not installed in your local repository.
When trying to build the child project, Maven will look-up any dependencies and parent POM in your local repo. It will find the version of the parent without that property and continue the build. Then, the maven-resources-plugin will emit this warning because no encoding have been set. (Setting the project.build.sourceEncoding also sets by default the encoding used by this plugin).
The solution is to build the parent first.
In a multi-module Maven project, you simply need to build the parent: Maven will order the reactor in such a way that dependant projects are built first; so in this case, the parent would be built first, and then the child (or module in this case), thereby ensuring that all properties defined in the parent are accessible to the child.
Outside of a multi-module Maven project, the idea is still the same, but you then need to perform two distinct builds: first the parent to install the right version into your local repository, and then the child. Note that when such parents are not used as aggregator projects, but more as building blocks consolidating common properties for children to inherit from, it would be preferable to have a distinct release cycle with it: consider making a release of your parent, so that every child can inherit that particular version.
You need to add the maven-resources-plugin in order to activate filtering, like here:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<configuration>
...
<encoding>UTF-8</encoding>
...
</configuration>
</plugin>
</plugins>
...
</build>

maven pom.xml dependencies order vs classpath/build path order

I am trying to understand the connection between the dependencies in a project's pom.xml file and the order of the java classpath/build path (my question is also regarding the inheritance of poms).
So far I wasn't able to find a detailed step-by-step explanation.
I have noticed for sure that it's not "the same", meaning, sometimes dependencies I have in my pom.xml will not appear in the build path in eclipse or will not be in the same order(after committing mvn eclipse:eclipse -$someflag) .
Let's assume for example I have the following Parent pom:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>SOME_GROUP_ID</groupId>
<artifactId>PARENT</artifactId>
<version>SOME_VERSION</version>
<name>${project.groupId}:${project.artifactId}</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SOME_OTHER_ARTIFACT1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<modules>
<module>CHILD</module>
</modules>
</project>
and that some other project's pom.xml inherits it:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>SOME_GROUP_ID</groupId>
<artifactId>PARENT</artifactId>
<version>SOME_VERSION</version>
</parent>
<artifactId>CHILD</artifactId>
<name>${project.groupId}:${project.artifactId}</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>SOME_OTHER_ARTIFACT2</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
My questions are: If I now run mvn eclipse:eclipse -$someflag on CHILD project:
Should the build path for CHILD project contain: PARENT, SOME_OTHER_ARTIFACT1, SOME_OTHER_ARTIFACT2 for sure? not for sure? when and why one of them should/shouldn't appear in the build path?
Should the classpath file for CHILD project contain: PARENT, SOME_OTHER_ARTIFACT1, SOME_OTHER_ARTIFACT2 for sure? not for sure? when and why one of them should/shouldn't appear in the build path?
Is it related to the flag (i.e $someflag) that was used when running mvn eclipse:eclipse?
Should the jars in the library appear also in the order of the dependencies in the project that is being initialized? i.e PARENT, SOME_OTHER_ARTIFACT1, SOME_OTHER_ARTIFACT2 (from top to bottom) necessarily? When and why should the order be different?
Thank you
Re "my question is also regarding the inheritance of poms"
See Maven: The Complete Reference, Project Inheritance:
You can avoid repeating yourself if your projects make use of inheritance via the parent element. When a project specifies a parent, it inherits the information in the parent project’s POM. It can then override and add to the values specified in this parent POM.
... and Multi-module vs. Inheritance:
There is a difference between inheriting from a parent project and being managed by a multimodule project. A parent project is one that passes its values to its children. A multimodule project simply manages a group of other subprojects or modules.

How to build one module into another module of same project in maven using in pom.xml

I have a maven project which contains two modules.
module-1
module-2.
How can i build the module-2 by adding dependency in module-1's pom.xml.
Finally when the build is done, the module-1.jar contains files of module-1 also.
thanks in advance,
Ubedulla.
The best sturcture for such project is like this:
+-- pom.xml (root)
+--- module-1
! +--- pom.xml
+--- module-2
+--- pom.xml
So the root pom contains the modules definition like this:
<project ..>
<groupId>groupId<groupId>
<artifactId>the-root</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
...
<modules>
<module>module-1</module>
<module>module-2</module>
</modules>
So a module like module-1 look like this:
<project ..>
<parent>
<groupId>groupId<groupId>
<artifactId>the-root</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module-1</artifactId>
...
And module-2 look like this:
<project ..>
<parent>
<groupId>groupId<groupId>
<artifactId>the-root</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>module-2</artifactId>
...
<dependencies>
<dependency>
<groupId>${project.groupId}<groupId>
<artifactId>module-1</artifactId>
<version>${project.version}</version>
</dependency>
If you follow the best practice you don't need entries like ../module-1 etc.
One of the ways (assuming modules are jar projects):
Create a parent maven pom project
Create 1st jar maven project (module 1)
Create 2nd jar maven project(module 2) having module-1 as dependency in its pom.
Then you add in the parent project inside its pom the modules in this manner:
.....
<modules>
<module>../module-1</module>
<module>../module-2</module>
</modules>
......
In this case module-1 and module-2 artifactId.
Then all you need is to install the parent project using maven and all the rest will be created.

How do I setup maven sub-projects with inter-dependencies?

I'm having a hard time setting up a set of related maven projects with interdependencies between them.
Here's my simplified case:
pom.xml -- parent pom
\base\
pom.xml
src\main\java\Base.java -- this is just a simple class
\derived\
pom.xml
src\main\java\Derived.java -- this is a simple class that needs Base class to compile successfully, and has a main function
My goals are:
be able to compile, on my machine, all projects:
i.e. mnv clean compile is successful in \
be able to compile, on my machine, just one project:
i.e. mnv clean compile is successful in \base\ and \derived\ (though this may not work by design: Inter Project Dependencies in Maven)
[edit: found the answer for this one: base needs to be published locally before derived in compiled: i.e. in \base, do mvn clean compile install instead of doing just doing mvn clean compile. Once this is done, doing mvn clean compile in \derived works fine. Still, it would be great to do this without touching global state, i.e. without having to install base -- so if anyone knows a way of achieving this, please add it as an answer]
be able to run derived project on my machine (mvn exec:run or equivalent) direcly from the source tree:
i.e. mvn exec:run in \derived\ should compile (if needed) and run the derived.jar
the "shared component" use case: push the base artifact to the shared repository, where other people can consume it as a maven dependency (i.e. compile time dependency):
i.e. mvn clean compile ??? will push this to the shared repository specified in ~/.m2/config.xml
the "image directory" use case: push the derived artifact and its depedencies to a local directory, where it can be run via "java -jar ..." or it can exposed as an ftp/http share for other people to get it. I.e., use cases like those:
mvn clean compile ??? will push derived.jar and dependencies (like base.jar) to ~/.m2/maven.repo/.../derived or equivalent, and then I can cd ~/.m2/maven.repo/.../derived and run java -jar derived.jar to run it.
mvn clean compile ??? will push base.jar to ~/.m2/maven.repo/.../base (or derived.jar to its corresponding dir), which is already exposed as a download point via local web or ftp server.
How do I do the goals above?
Here's the relevant section from parent pom:
...
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo</groupId>
<artifactId>parentpom</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parentpom</name>
<modules>
<module>base</module>
<module>derived</module>
</modules>
...
Here's the relevant section from base pom.xml:
...
<parent>
<groupId>com.foo</groupId>
<artifactId>parentpom</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo.base</groupId>
<artifactId>base</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>base</name>
...
Here's the relevant section from derived pom.xml:
...
<parent>
<groupId>com.foo</groupId>
<artifactId>parentpom</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.foo.derived</groupId>
<artifactId>derived</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>derived</name>
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>base</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
...
Thank you in advance for your help.
Your parent pom looks good but your module/derived poms don't: There are several issues which will produce some problems etc.
First you are using different groupId's for the derived/base module. If you have a multi-module build you shouldn't do this. Furthermore, the version of derived/base is inherited by the parent and shouldn't be set explicit which means you should have something like the following:
<modelVersion>...</...>
...
<parent>
<groupId>com.foo</groupId>
<artifactId>parentpom</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>base</artifactId>
<packaging>jar</packaging>
<name>base</name>
The groupId is usually inherited. But sometimes you have a larger number of modules that may be sub-modules of sub-modules which results in a structure like this:
+--- parent (pom.xml)
+--- mod1 (pom.xml)
+--- mod11 (pom.xml)
+--- mod12 (pom.xml)
+--- mod2 (pom.xml)
In Such cases, the mod1 itself is a a pom packaging module:
<modelVersion>...</...>
...
<groupId>com.company.project<groupId>
<artifactId>parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>mod1</module>
<module>mod2</module>
</modules>
mod1:
<parent>
<groupId>com.company.project<groupId>
<artifactId>parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>com.company.project.mod1</groupId>
<artifactId>mod1</artifactId>
<packaging>pom</packaging>
<modules>
<module>mod11</module>
<module>mod12</module>
</modules>
mod11:
<parent>
<groupId>com.company.project.mod1</groupId>
<artifactId>mod1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>mod11</artifactId>
<packaging>pom</packaging>
<modules>
<module>mod11</module>
<module>mod12</module>
</modules>
If you need to make a dependency between modules the solution is:
<parent>
<groupId>com.company.project.mod1</groupId>
<artifactId>mod1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>mod11</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<!-- This shouldn't be a dep which is packaging: pom -->
<groupId>${project.groupId}</groupId>
<artifactId>mod2</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
To compile the whole project with all sub modules in one just go to parent folder and:
mvn clean package
will compile etc. If you like to compile only a single project you can do this by (from parent):
mvn -pl mod1
which will work only if you have installed the whole project once before. Another solution is:
mvn -am -pl mod1
To make the artifacts acessible for others the simplest solution is to install a repository manager and do:
mvn deploy
All others can use and artifact as a SNAPSHOT dependency.

Maven versioning of multi-module projects with parent POM

This is a slightly different version of this previous question, in that I have separate multi-module and parent POMs: In a Maven project, how can I automatically update the version all child modules, plus the parent?
I am trying to update my POMs to go from a development snapshot version to a released version number. I have googled the issue to death, tried the release and version plug-in, and nothing seems to be able to handle my fairly simple setup.
Following published Maven best practices, and trying not to duplicate information when I can avoid to, I ended up with the structure below for my multi-module project.
There is a single version defined by the common pom-parent.xml; and B depends on A.
I find it a bit surprising that the standard plug-ins can't handle what seems to be a fairly basic setup, am I missing something?
None of the workarounds I have come up with are completely satisfactory:
define the product version as a property is a bit flaky, the same module source could get different versions because of a user settings.xml or other trick
merge the root pom.xml and pom-parent.xml and move the product-wide build steps I currently maintain in the root pom into a dedicated module; and hope that the std plug-ins will then work... not tried.
Any suggestion?
root/pom-parent.xml: parent of all the POMs below
<project...>
<groupId>acme</groupId>
<artifactId>ParentPom</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
root/pom.xml: multi-module projects with A and B as submodules
<project ...>
<parent>
<groupId>acme</groupId>
<artifactId>ParentPom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>acme</groupId>
<artifactId>Product</artifactId>
<packaging>pom</packaging>
<modules>
<module>A</module>
<module>B</module>
</modules>
root/A/pom.xml:
<project ...>
<parent>
<groupId>acme</groupId>
<artifactId>ParentPom</artifactId>
<relativePath>../parent-pom.xml</relativePath>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>acme</groupId>
<artifactId>A</artifactId>
<packaging>jar</packaging>
root/B/pom.xml:
<project ...>
<parent>
<groupId>acme</groupId>
<artifactId>ParentPom</artifactId>
<relativePath>../parent-pom.xml</relativePath>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>acme</groupId>
<artifactId>B</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>acme</groupId>
<artifactId>A</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
If you have a structure like the following:
root
+-- pom.xml (1.0-SNAPSHOT)
!
+-- module1
! +-- pom.xml (1.0-SNAPSHOT)
+-- module2
+-- pom.xml (1.0-SNAPSHOT)
all modules (module1 and module2) using root as their parent like this:
<parent>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
If you want to factor out other default setup like pluginManagement or dependencyManagement for other projects as well you have to use a separate parent pom which must be a separate maven project which contains only the pom.xml. Furthermore this project will be deployed and released separately. If you do so you can use this as parent in the root pom of the above structure.
If you like to make a release you will go simply into the root folder of the above structure and the version number etc. will automatically incremented.
mvn -B release:prepare release:perform

Resources