Performing maven release in multimodule project failing - maven

I have a multimodule(module1,module2,module3) project which has an aggregator pom to build all the modules.
Now the reactor build order is
module1
module2
module3
Also module2 has dependency on module1 and module3 has dependency on module2,Now to account for the dependency I am using ${project.version} to specify the module1 version in module2 pom, similarly I am using ${project.version} in module 3 pom to refer to module2.Now the snapshot jobs are executed successfully but when i try to release all the modules using the aggregator pom(which is the parent pom for all the modules) the build fails saying that it cannot release project due to non released dependencies.Is there a way to solve this problem?
I am using Maven 3.0.4 maven-release-plugin:2.0-beta-8 for the project.
Also it is necessary for module2 to use the latest version of module1 which is also true for module3 and module2.And it is necessary to release all of them together as I would want the modules to be released only when all of them are built successfuly.
parent pom
<project>
<groupid>com.mycompany</groupid>
<artifactid>parent</artifactid>
<version>1.0.0</version>
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
..
</project>
module1 pom
<project>
<parent>
<groupid>com.mycompany</groupid>
<artifactid>parent</artifactid>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupid>com.mycompany</groupid>
<artifactid>module2</artifactid>
<dependencies>
..
..
</dependencies>
module2 pom
<project>
<parent>
<groupid>com.mycompany</groupid>
<artifactid>parent</artifactid>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupid>com.mycompany</groupid>
<artifactid>module2</artifactid>
<dependencies>
<dependency>
<groupid>com.mycompany</groupid>
<artifactid>module1</artifactid>
<version>${project.version}</version>
</dependency>
..
..
..
</dependencies>
..
</project>

Things to check
1) Make sure any dependencies under the same parent are specified with ${project.version}
2) Make sure each module does not explicitly declare it's own version but only specifies a parent, which in turn will set the version.
3) Make sure each project does not explicitly declare a groupId, that should come from the parent.
4) Make sure there are not SNAPSHOT dependencies. The only place that SNAPSHOT should occur in all modules is in the parent pom.
5) Make sure all your poms have a packaging declared, the parent should be pom.

Related

Is it necessary to install maven submodule dependencies before building the client submodule?

Given
<modules>
<module>A</module>
<module>B</module>
</module>
</modules>
in a parent pom.xml. And in B/pom.xml
<dependency>
<groupId>foo.bar</groupId>
<artifactId>A</artifactId>
</dependency>
Then - what is the process here? It feels "wrong" to need to do
mvn -pl A clean package install
and then
mvn -pl B clean package
in order to get the A dependency of B available before building the latter. It seems maven should know how to sort this out. What am I missing?
Update In response to (good) questions from #Tunaki
Both A and B have :
<parent>
<groupId>org.myco.mypkg</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
And the GAV is correct for A and also correctly referenced in B
<groupId>org.myco.mypkg</groupId>
<artifactId>A</artifactId>
<name>Name of A</name>
<version>1.0.0</version>

Avoid wrong version interpolation if child's pom version is different from those of the parent's aggregator pom and its sub modules

Problem description
We have a Maven aggregator pom with some child poms (modules) all having the same version:
pom.xml (parent zoo, version 2.0.0)
|-- pom.xml (child module cat, version 2.0.0)
|-- pom.xml (child module dog, version 2.0.0)
|-- ...
Within the dependency management section all children are declared with the project version to ease declaration of dependencies.
The parent pom looks like
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
<packaging>pom</packaging>
<modules>
<module>cat</module>
<module>dog</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<version>${project.version}</version>
</dependency>
<!-- other child modules go here -->
</dependencies>
</dependencyManagement>
The child poms are defined as
<parent>
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dog</artifactId>
</dependency>
</dependencies>
There is another pom which declares the parent pom as its parent too (inheritance) but is not listed as sub module in this parent (no aggregation). This pom has a different version.
<parent>
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>boo</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dog</artifactId>
</dependency>
</dependencies>
Actually we have expected that the version of the dependency com.acme.dog is pulled from the dependency management section of the parent pom com.acme.zoo and is equal to 2.0.0. However the Maven documentation on project interpolation and variables says
One factor to note is that these variables are processed after inheritance as outlined above. This means that if a parent project uses a variable, then its definition in the child, not the parent, will be the one eventually used.
That is: in the reactor build the variable ${project.version} used in the dependency management section of the parent pom com.acme.zoo is evaluated with respect to com.acme.bar and equal to 1.0.0 what is not as intended.
Note
There is a workaround with using a variable in the parent pom which has to be kept in sync with the parent pom versions. However, this solution is incompatible with the Maven Release Plugin.
Question
How can we achieve the desired behaviour
aggregator pom with children having the same version
declaration of children in the dependency management section to ensure that all dependencies have the same version
use of inheritance together with different versions
compatibility with maven-release-plugin
without the pitfalls of project interpolation of variables?
The maven release plugin is able to change the versions of the dependencies managed in the parent pom.
So if you define your maven parent like this:
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cat</module>
<module>dog</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
<!-- other child modules go here -->
</dependencies>
</dependencyManagement>
As you see the versions of the parent and the managed dependency are the same. I set them to a SNAPSHOT version because the release plugin will create the final versions on release:perform
Your child poms can stay as you had them.
Because in your setup, your parent project is also the reactor you can then call
mvn release:perform -DautoVersionSubmodules=true
which will update the version of the parent in all submodules when you run this command. That option is essentially the same as if you run
mvn versions:update-child-modules
meaning it will change the child poms.
After you run the mvn release:perform command your parent pom will look like this:
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>cat</module>
<module>dog</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<version>2.0.1-SNAPSHOT</version>
</dependency>
<!-- other child modules go here -->
</dependencies>
</dependencyManagement>
and your child poms like this
<parent>
<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.1-SNAPSHOT</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>cat</artifactId>
<dependencies>
<dependency>
<groupId>com.acme</groupId>
<artifactId>dog</artifactId>
</dependency>
</dependencies>
The final versions will only exist in the tag created by the release:prepare command.
PS: You may define other versions for the final and the next development version when they are prompted after running the release:prepare command.
The simplest solution is modify pom of zoo and replace <version>${project.version}</version> with <version>2.0.0</version>
Please note:
when you change version to next number, for example 2.0.1, with
versions-maven-plugin, dependency management section will be also
updated.
Spring use simplest solution, see
http://central.maven.org/maven2/org/springframework/spring-framework-bom/4.2.7.RELEASE/spring-framework-bom-4.2.7.RELEASE.pom
Summary: using <version>${project.version}</version> in dependency management is wrong idea.
From Maven Introduction to the pom : http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
Project Inheritance > Example 1 > The Solution
Alternatively, if we want the groupId and / or the version of your
modules to be the same as their parents, you can remove the groupId
and / or the version identity of your module in its POM.
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>
My approach to that is to track it in the child POM. It's a bit less typing overall, close to where the actual dependency lives and is low maintenance for most projects. YMMV
<dependencies>
...
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>foo-sibling</artifactId>
<version>${project.version}</version>
</dependency>
...
</dependencies>

Maven: POM modules and submodules hierarchy

My project is structured like this:
.
|--module
| `-- pom.xml
| --submodule
| `-- pom.xml
`-- pom.xml
The POM's (simplified):
Project:
<project>
<modelVersion>4.0.0</modelVersion>
<artifactId>project</artifactId>
<name>Project</name>
<groupId>org.myorg</groupId>
<version>1.0.6-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module</module>
</modules>
(...)
</project>
Module:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.myorg</groupId>
<artifactId>project</artifactId>
<version>1.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>module</artifactId>
<name>Module</name>
<groupId>org.myorg</groupId>
<version>1.0.6-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>submodule</module>
</modules>
(...)
</project>
Submodule:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.myorg</groupId>
<artifactId>module</artifactId>
<version>1.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>submodule</artifactId>
<name>Submodule</name>
<groupId>org.myorg</groupId>
<version>1.0.6-SNAPSHOT</version>
<packaging>jar</packaging>
(...)
</project>
When run maven install in POM's project or module the project is built sucessfully. But, when run in submodule occours this error:
Failed to execute goal on project submodule: Could not find artifact org.myorg:project:pom:1.0.6-SNAPSHOT
Why my submodule not find the POM project? The relative path is specified.
The first thing which i noticed is that every sub-module which has a parent contains the line:
<relativePath>../pom.xml</relativePath>
which is useless, cause it's default in maven or in other word just remove it.
Furthermore in a multimodule build you shouldn't define the version. In case if the groupId is always the same you can omit the groupId as well, cause the current module inherits the version from it's parent.
module: pom.xml
<project>
<parent>...
</parent>
<artifactId>module</artifactId>
<packaging>pom</packaging>
<name>Module</name>
<modules>
<module>submodule</module>
</modules>
(...)
</project>
Apart from that you can't go into a sub-module and call
mvn install
If you like to install a separate module of a multi-module build you should use a thing like this:
mvn -amd -pl submodule install
which will do what you like to do, but usually you should install a full mulit-module build unless you exactly know what you are doing.
The options -amd is an abbrevation for --also-make-dependents. The -pl is an abbreviation for --projects to define a list of project which should be made during the call.
First you need to run mvn install on root project it will creates the artifact in your local maven repo. From the second time on wards you can run sub module only. If you don't run on root project maven wont create any artifact for your project so when you run on sub module it unable to find the artifact from the maven repo.

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