Why this two-way definition?
It is not mandatory. It is a design choice.
Why not define just in the parent?
If you define them only in the modules
tag of the parent pom, you will only use the reactor/aggregation feature of Maven.
1) Aggregation (<modules>
declaration in the super aggregator project) provides mainly these features:
- Collects all the available modules to build
- Sorts the projects into the correct build order
- Builds the selected projects in order
Aggregation module is enabled by declaring the modules to aggregate in the parent pom:
<modules>
<module>my-child</module>
<module>my-other-child</module>
</modules>
But aggregation doesn't provide inheritance.
2) Project inheritance (<parent>
declaration in the child modules) provides the inheritance of multiple things from the parent declaration to the child module :
From the actual documentation, most elements from the parent POM are inherited by its children:
groupId
version
description
url
inceptionYear
organization
licenses
developers
contributors
mailingLists
scm
issueManagement
ciManagement
properties
dependencyManagement
dependencies
repositories
pluginRepositories
build
plugin executions with matching ids
plugin configuration
reporting
profiles
Inheritance is enabled by declaring the parent artifact in the child poms:
<parent>
<groupId>my-group</groupId>
<artifactId>my-parent</artifactId>
<version>1.0.0</version>
</parent>
<!-- You can note that groupId and version are not filled for the current project.
These are optional as inherited from the parent -->
<artifactId>my-artifact</artifactId>
In fact, you can use project inheritance, project composition, none of them or both.
It is really a design choice that should be done according to the relation between the projects and their requirements.
You may refer to this interesting point on the Maven documentation about these two features:
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.
To illustrate using an example.
Here is a multi-module project's parent pom.xml.
<!-- PARENT POM -->
<groupId>com.example</groupId>
<artifactId>parent-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>child-module</module>
</modules>
And here is the Child Pom.
<!-- CHILD POM -->
<parent>
<groupId>com.example</groupId>
<artifactId>parent-demo</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>chile-module</artifactId>
Here, child-module
inherits parent-demo
, but parent-demo
does not use any inheritance.
And if you want, your parent-demo
to also use inheritance, you can configure your parent-demo
like below.
<!-- PARENT POM -->
<parent>
<groupId>com.example</groupId>
<artifactId>parent-deps</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../parent-deps</relativePath>
</parent>
<artifactId>parent-demo</artifactId>
<packaging>pom</packaging>
<modules>
<module>child-module</module>
</modules>
And now, your parent-demo
is also inheriting configurations from parent-deps
which are cascaded down to child-module
as well (unless ofcourse parent-demo
decides to override them).