POM.xml Inheritance and Aggregation

Project Inheritance

Elements in the POM that are merged are the following:

  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources

The Super POM is one example of project inheritance, however you can also introduce your own parent POMs by specifying the parent element in the POM, as demonstrated in the following examples.

Example 1

The Scenario

As an example, let us reuse our previous artifact, com.mycompany.app:my-app:1. And let us introduce another artifact, com.mycompany.app:my-module:1.

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-module</artifactId>  <version>1</version></project>

And let us specify their directory structure as the following:

.
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml

Note: my-module/pom.xml is the POM of com.mycompany.app:my-module:1 while pom.xml is the POM of com.mycompany.app:my-app:1

The Solution

Now, if we were to turn com.mycompany.app:my-app:1 into a parent artifact of com.mycompany.app:my-module:1,we will have to modify com.mycompany.app:my-module:1’s POM to the following configuration:

com.mycompany.app:my-module:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <parent>    <groupId>com.mycompany.app</groupId>    <artifactId>my-app</artifactId>    <version>1</version>  </parent>   <groupId>com.mycompany.app</groupId>  <artifactId>my-module</artifactId>  <version>1</version></project>

Notice that we now have an added section, the parent section. This section allows us to specify which artifact is the parent of our POM. And we do so by specifying the fully qualified artifact name of the parent POM. With this setup, our module can now inherit some of the properties of our parent POM.

Alternatively, if you want the groupId or the version of your modules to be the same as their parents, you can remove the groupId or the version identity of your module in its POM.

<project>  <modelVersion>4.0.0</modelVersion>   <parent>    <groupId>com.mycompany.app</groupId>    <artifactId>my-app</artifactId>    <version>1</version>  </parent>   <artifactId>my-module</artifactId></project>

This allows the module to inherit the groupId or the version of its parent POM.

[top]

Example 2

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 as in the following example?

.
 |-- 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>  <modelVersion>4.0.0</modelVersion>   <parent>    <groupId>com.mycompany.app</groupId>    <artifactId>my-app</artifactId>    <version>1</version>    <relativePath>../parent/pom.xml</relativePath>  </parent>   <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.

Project Aggregation

Project Aggregation is similar to Project Inheritance. But instead of specifying the parent POM from the module, it specifies the modules from the parent POM. By doing so, the parent project now knows its modules, and if a Maven command is invoked against the parent project, that Maven command will then be executed to the parent’s modules as well. To do Project Aggregation, you must do the following:

  • Change the parent POMs packaging to the value “pom”.
  • Specify in the parent POM the directories of its modules (children POMs).

[top]

Example 3

The Scenario

Given the previous original artifact POMs and directory structure:

com.mycompany.app:my-app:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-app</artifactId>  <version>1</version></project>

com.mycompany.app:my-module:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-module</artifactId>  <version>1</version></project>

directory structure

.
 |-- my-module
 |   `-- pom.xml
 `-- pom.xml
The Solution

If we are to aggregate my-module into my-app, we would only have to modify my-app.

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-app</artifactId>  <version>1</version>  <packaging>pom</packaging>   <modules>    <module>my-module</module>  </modules></project>

In the revised com.mycompany.app:my-app:1, the packaging section and the modules sections were added. For the packaging, its value was set to “pom”, and for the modules section, we have the element <module>my-module</module>. The value of <module> is the relative path from the com.mycompany.app:my-app:1 to com.mycompany.app:my-module:1’s POM (by practice, we use the module’s artifactId as the module directory’s name).

Now, whenever a Maven command processes com.mycompany.app:my-app:1, that same Maven command would be ran against com.mycompany.app:my-module:1 as well. Furthermore, some commands (goals specifically) handle project aggregation differently.

[top]

Example 4

The Scenario

But what if we change the directory structure to the following:

.
 |-- my-module
 |   `-- pom.xml
 `-- parent
     `-- pom.xml

How would the parent POM specify its modules?

The Solution

The answer? – the same way as Example 3, by specifying the path to the module.

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-app</artifactId>  <version>1</version>  <packaging>pom</packaging>   <modules>    <module>../my-module</module>  </modules></project>

Project Inheritance vs Project Aggregation

If you have several Maven projects, and they all have similar configurations, you can refactor your projects by pulling out those similar configurations and making a parent project. Thus, all you have to do is to let your Maven projects inherit that parent project, and those configurations would then be applied to all of them.

And if you have a group of projects that are built or processed together, you can create a parent project and have that parent project declare those projects as its modules. By doing so, you’d only have to build the parent and the rest will follow.

But of course, you can have both Project Inheritance and Project Aggregation. Meaning, you can have your modules specify a parent project, and at the same time, have that parent project specify those Maven projects as its modules. You’d just have to apply all three rules:

  • Specify in every child POM who their parent POM is.
  • Change the parent POMs packaging to the value “pom” .
  • Specify in the parent POM the directories of its modules (children POMs)

[top]

Example 5

The Scenario

Given the previous original artifact POMs again,

com.mycompany.app:my-app:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-app</artifactId>  <version>1</version></project>

com.mycompany.app:my-module:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-module</artifactId>  <version>1</version></project>

and this directory structure

.
 |-- my-module
 |   `-- pom.xml
 `-- parent
     `-- pom.xml
The Solution

To do both project inheritance and aggregation, you only have to apply all three rules.

com.mycompany.app:my-app:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <groupId>com.mycompany.app</groupId>  <artifactId>my-app</artifactId>  <version>1</version>  <packaging>pom</packaging>   <modules>    <module>../my-module</module>  </modules></project>

com.mycompany.app:my-module:1’s POM

<project>  <modelVersion>4.0.0</modelVersion>   <parent>    <groupId>com.mycompany.app</groupId>    <artifactId>my-app</artifactId>    <version>1</version>    <relativePath>../parent/pom.xml</relativePath>  </parent>   <artifactId>my-module</artifactId></project>

NOTE: Profile inheritance the same inheritance strategy as used for the POM itself.

Reference :

Leave a Comment