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.