Differences between a multi-module project and a parent project
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).
Because when you are building some submodule, it should now some meta information, such as dependency version for example, and it's usually a better practice to put this dependencies into parent pom dependencyManagement
, because I would make all submodules use the same library version. Also there is another meta information that could be useful, like properties
.
So, all in all when you are building a particular submodule, maven should know some information which you usually want to set up in the parent pom.
I believe there can be more reasons for that, but it's the most obvious for me.
If you want to reuse modules in my opinion then you need these modules to be a library, and add them via dependency
tag as a library.