Understanding Maven Module Inheritance and Aggregation for Multi‑Module Project Builds

This article explains Maven's inheritance and aggregation features, including the super POM, parent POM configuration, module aggregation syntax, reactor build order, dependency management, property definitions, and useful command‑line options, all illustrated with a simple multi‑module demo.

IT Niuke
IT Niuke
IT Niuke
Understanding Maven Module Inheritance and Aggregation for Multi‑Module Project Builds

Module Inheritance

In Maven a child pom.xml can inherit common configuration from a parent pom by declaring a <parent> element. The inheritable elements include: groupId and version (the artifactId is not inherited)

dependencies
dependencyManagement
properties
repositories
distributionManagement
build

(plugins, plugin management, source/output directories, etc.)

Super POM

Every Maven project automatically inherits from the built‑in super POM . The super POM is located inside Maven’s lib directory in the JAR maven-model-builder.jar at the path org/apache/maven/model/pom-4.0.0.xml. It defines default repository addresses, default resource directories ( src/main/resources, src/test/resources), and default build output directories, illustrating Maven’s “convention over configuration”.

<project>
  <modelVersion>4.0.0</modelVersion>
  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots><enabled>false</enabled></snapshots>
    </repository>
  </repositories>
  <pluginRepositories>…</pluginRepositories>
  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
  </build>
</project>

Custom Parent POM

To use a custom parent, add a <parent> section with the parent coordinates:

<parent>
    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <version>...</version>
    <relativePath>...</relativePath>
</parent>

The relativePath points to the parent’s pom.xml. Its default value is ../pom.xml. If the parent and child are placed side‑by‑side, adjust the path, e.g. <relativePath>../parent/pom.xml</relativePath>. Maven resolves the parent in this order: the specified relative path, then the local repository, then remote repositories.

Typical Spring Boot parent:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
</parent>

Module Aggregation

Aggregating modules allows a multi‑module project to be built with a single command. In the aggregator’s pom.xml add a <modules> section where each <module> value is the relative directory of a child module, not its artifactId:

<modules>
    <module>demo-a</module>
    <module>demo-b</module>
    <module>demo-c</module>
</modules>

If a module directory is renamed, update the path accordingly, e.g.:

<modules>
    <module>demo-aa</module>
    <module>demo-b</module>
    <module>demo-c</module>
</modules>

When the aggregator resides in a sibling directory, use relative paths such as ../demo-a.

Reactor Build Order

Running mvn clean install on the aggregator builds the aggregator first, then its child modules in dependency order (bottom‑up). Maven automatically builds required modules, but cyclic dependencies are prohibited. Example error for a cycle between demo-a and demo-c:

Each project listed is a relative path to the directory containing the module. The projects in the reactor contain a cyclic reference : Edge between ‘Vertex{label=‘com.ls.maven:demo-c:1.0.0’}’ and ‘Vertex{label=‘com.ls.maven:demo-a:1.0.0’}’ introduces a cycle in the graph com.ls.maven: demo-a:1.0.0 → demo-b:1.0.0 → demo-c:1.0.0 → demo-a:1.0.0

Selective Reactor Build

For large projects you can limit the build to specific modules using the -pl (projects list) and -am (also make required dependencies) options. Example: mvn clean install -pl demo-b -am Relevant usage snippet (excerpt):

usage: mvn [options] [<goal(s)>] [<phase(s)>]
Options:
 -am, --also-make            If project list is specified, also build projects required by the list
 -amd, --also-make-dependents If project list is specified, also build projects that depend on the list
 -pl, --projects <arg>       Comma‑delimited list of reactor projects to build instead of all projects.
                               A project can be specified by [groupId]:artifactId or by its relative path

Dependency Management and Property Configuration

Common dependency versions and configuration can be centralized in the parent POM using <dependencyManagement> and <properties>.

Example: centralizing the MySQL connector version in the parent:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
    </dependencies>
</dependencyManagement>

Child modules can then declare the dependency without a version:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

Define a property in the parent:

<properties>
    <mysql-connector-java.version>8.0.29</mysql-connector-java.version>
</properties>

Reference it with ${mysql-connector-java.version} in the dependency definition. The same technique can be used to centralize versions for the demo modules.

Version Update Workflow

When the project version changes (e.g., from 1.0.2 to 1.0.3), batch‑replace the version string in the IDE and run mvn clean install to verify the build.

Summary

Super POM is Maven’s top‑level POM that provides default repository, resource, and build directory configurations.

The <parent> element lets a child POM inherit configuration from a parent POM.

Parent modules should use <packaging>pom</packaging>.

The <relativePath> element specifies the parent’s location (default ../pom.xml).

Aggregation groups multiple modules for a single build; <module> values are directory paths, not artifactIds.

The Maven reactor builds modules in dependency order and forbids cyclic references.

Selectively building modules is possible with -pl and -am options. <dependencyManagement> centralizes dependency versions; <properties> defines reusable variables referenced via ${...}.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MavendependencyManagementpropertiesmodule aggregationmodule inheritanceparent pomreactor build
IT Niuke
Written by

IT Niuke

Focused on IT technology sharing, original and innovative content. IT Niuke, we grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.