maven module build. Not specifying version with children modules - maven

We have a multi-module build. I have a parent module that builds 17 other modules and one of those modules itself is another multi-module build that builds three others.
In my parent module:
<groupId>com.veggicorp.foobar</groupId>
<artifactId>foobar-parent</artifactId>
<version>5.4.3</version>
<properties>
<!-- Definition of versions for third party jars -->
</properties>
<dependencyManagement>
<!-- Another way to specify dependencies throughout the project -->
</dependencyManagement>
<modules>
<!-- List o' Modules -->
</modules>
By using properties to specify versions (and using dependencyManagement), I found I can get rid of almost any sort of version numbering in the child modules. This makes it very simple to maintain a complex project since most of the changes will take place in the parent. When we do a new version, I don't have to update 21 other pom.xml files.
However, there is one sore spot: I have to specify the parent version:
<parent>
<groupId>com.veggicorp.foobar</groupId>
<artifactId>foobar-parent</artifactId>
<version>5.4.3</version> <!-- Must Specify -->
</parent>
<artifactId>foo-server</artifactId>
<!-- No need for a version -->
<build>
....
Note that I don't need to specify the version of the child. It takes the parent's version by default. However, I have to fill in the parent's version number despite the fact that all of this sits in a single Git repository, and that all of the modules are unique for this project and are not used anywhere else. We won't even be deploying these modules' jars to our Maven repository. It's one big gigantic build.
I know I can use the version plugin to update all of these modules, but that means our developers must remember to use that plugin when they create a new version of the project. (I don't have much faith in our developers. Heck, we have directions on our wiki on how to tie your shoes.)
So, is there a way where our child modules -- which get checkedout with the parent module in a single big Git repo -- can avoid having the parent version number embedded in them?

The answer is no, you have to include the parent information in all the child modules and that information has to include the version.
However once you have set this up you can use the versions plugin to mange the versions of all your poms see http://www.mojohaus.org/versions-maven-plugin/
example, from the top level:
mvn versions:set -DnewVersion=1.1
will change all the children and the parent.

Related

Should you include those dependencies in your pom that are already the dependencies of some of your dependencies?

Say there are two dependencies you need: A and B. And at the same time A is already a dependency of B. So do you still want/need to add A along with B as dependencies in your pom?
I believe this may be needed when A and B are external libraries where the version of A needed may be different than the version of A that B is depending on.
But how about when both your module and A and B are modules in the same project? i.e. knowing their versions are all going to be in sync.
If your module uses APIs from B it's best practice to add it explicitly to your pom, even though it's not strictly necessary. If you upgrade A, it could well be that it doesn't use B anymore and then you'll get a build failure without any changes to your module code.
Regarding versions, you should manage those with dependencyManagement in a parent pom. You can then skip the version for the managed dependencies in the child poms. The version in the dependencyManagement overrides the version in transitive dependencies, ensuring you use the same version everywhere.
If all modules are in the same project, they should also share the same project version. Typically, this will be a snapshot version, e.g. 1-SNAPSHOT
Each module will use something like:
<project>
<artifactId>A</artifactId>
<version>1-SNAPSHOT</version>
And refer to A and B like this in other modules:
<dependency>
<groupId>com.yourcompany</groupId>
<artifactId>A</artifactId>
<version>${project.version}</version>
</dependency>
To set a non-SNAPSHOT version before you build a release, you can for example use the maven-dependency-plugin's versions:set goal.

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.

How do I default sub-module versions in a Maven multi-module project using snapshots?

I looked at previous questions on the topic and it seems people were a step ahead of where am I at the moment.
I am currently trying to use the maven release plugin to my multi module project. I start from scratch (more exactly, I retrieved some old projects to put in a new multi module project).
I have a POM parent that I defines as:
<groupId>com.somestuff</groupId>
<artifactId>stuff</artifactId>
<version>10.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name> stuff </name>
My child modules inherits the parent using:
<parent>
<groupId>com.somestuff</groupId>
<artifactId>stuff</artifactId>
<version>10.0.0-SNAPSHOT</version>
</parent>
So since it’s a new project, I specify the dependencies between modules as snapshots. For example, if module A depends on module B, I will add to A’s POM the part:
<dependencies>
<dependency>
<groupId>com.somestuff</groupId>
<artifactId>divarmiclient</artifactId>
<version>10.0.0-SNAPSHOT </version>
</dependency>
</dependencies>
The result is when I try to do a “mvn release:prepare”, Maven will yell that there is snapshot dependencies. But since it’s a whole new project, and that versions prior to 10 don’t exist, I have no idea how to default the version values of the modules.
My question is, how shall I default the module values ? How do I do in order to make my multi-module project acceptable from a snapshot perspective ?
For clarification, you're saying your structure is:
theparent
pom.xml
A/
pom.xml
B/
pom.xml
And the following assumptions all hold true:
theparent, A, and B are currently on same version
releases will always be kicked off from 'theparent' level so they remain on same version
A depends on B, always same version
Then the solution is as follows:
<dependency>
<groupId>com.somestuff</groupId>
<artifactId>B</artifactId>
<version>${project.version}</version>
</dependency>

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

maven: parent-version

I don't understand what is the parent version and for what it should be good?
We use svn in our team and when I did update for the project the last time I notcied that the parent version is changed:
local pom.xml
<parent>
<artifactId>foo</artifactId>
<groupId>bar</groupId>
<version>0.42-SNAPSHOT</version>
</parent>
svn pom.xml
<parent>
<artifactId>foo</artifactId>
<groupId>bar</groupId>
<version>0.45-SNAPSHOT</version>
</parent>
When does parent version change and for what it should be good?
A parent POM contain settings that apply to all child modules. This may include declaring plugin settings or choosing dependency versions.
A parent POM is no different to any other Maven artifact. It can change and when it does the version number must increment. Typically you want to always be using the latest available version of your parent.
You can use the Maven versions plugin to help manage versions, including forcing an update to the latest available parent version.
Parent pom and child pom come into picture if you have a multi-module project. For example like the below
/myapp
|- pom.xml --> parent pom
|+ module1/
| - pom.xml --> child pom
| - src/
|- module2/
There can be several such hierarchies. There are 2 ways to define this inheritance
Add a xml block in parent pom to tell it which are the dependent modules. OR
Add a xml block in a module to tell whose is it's parent. (This is your case)
This means that, the child pom is dependent on parent and will try to find the the concerned artifact with 0.45-SNAPSHOT version. This version has changed probably due to a newer build of parent has taken place replacing the version.

Resources