Module inheritance vs aggregation

The inheritance of a parent pom is usefull if you have properties that are valid for several projects. From what I understood you already got that part right ;-)

What you call aggregating modules has a valid practical use too. You can group several submodules into a single pom. If you want to build your project you mostly don't want to build every module sperately but join them into one single application. This can be done by such a pom that references all the submodules as such. It can't be done with just the concept of a parent pom as it knows nothing of the other modules.


There is a great problem in the definition of these concepts in the Maven community. You are right with stating that a parent-pom is inheritance and module-pom is composition. But unfortunately the separation of these two concepts have no history in Maven. The Maven documentation says clearly that it is better to separate them. This would result in this ideal structure

app-api/
app-impl/
app-war/
app-parent/
pom.xml

Where pom.xml is the module pom.

But almost every project you will see in the open source sector does not distinguish between them.

This has a reason: Many plugins do not distiguish between them as well. And even Maven itself assumes another setting: If <relativePath> is not set Maven assumes that the parent is at ... So every project has to point to <relativePath>../app-parent</relativePath> as parent.

The most popular plugin that has huge problems with the mentioned structure is the maven-release-plugin! You will face strange problems when you do not follow the assumption that the module-pom is the parent-pom.

The worst bug is that the release-plugin cannot replace version-properties in your parent and fails because of SNAPSHOT-Dependencies. Your parent perhaps will contain something like this

<properties>
    <app-api.version>1.1-SNAPSHOT</app-api.version>
    <app-impl.version>1.2-SNAPSHOT</app-impl.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>myorg</groupId>
            <artifactId>app-api</artifactId>
            <version>${app-api.version}</version>
        </dependency>

        <dependency>
            <groupId>myorg</groupId>
            <artifactId>app-impl</artifactId>
            <version>${app-impl.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Normally while releasing these properties would automatically be set to their release versions 1.1 and 1.2. But the release-plugin (tested up to version 2.2.2) fails with a message that the module cannot be released with snapshot dependencies.

If you only "skip" some module-poms this might not be a problem when you define <relativePath> correctly. But you have to try and expect some bugs in Maven plugins. Besides these bugs you are totally right to seperate the poms and I would give it a try if you have the time to make a sandboxed release.


The short answer IIUC is, you don't inherit from your aggregation-only poms. You do when your aggregator is the same as your parent, as in the canonical maven structure. But if you separate aggregator from parent, don't inherit from the aggregator

Tags:

Maven