Reactorization in maven.

Dushyanth N Gowda
Version 1
Published in
4 min readJan 12, 2023

What is reactorization?

The mechanism of handling multi-module projects in maven is called a reactor and the process of creating a reactor is called Reactorization.

Why do we need reactorization?

If we have multiple projects which hold common dependencies/plugins/build configurations then we can use a reactor to define all these configurations in the parent module and consume them in child modules.

Advantages of the reactor.

  • Reduces duplication.
  • Builds modules in a single command and order which we define.
  • Share the same configurations across all the modules.
  • Easy management of modules by updating only in the parent module.

How to create a reactor.

Parent module.

A reactor consists of the Parent and Sub modules(child modules).

The Parent module should be of packaging type POM along with groupId and version in its pom.xml.

<packaging>pom</packaging>

Add all the child modules in the Modules section in the order we want to build.

<modules>
<module>Child1</module>
<module>Child2</module>
<module>Child3</module>
</modules>

Now it’s time to add the configurations.

  • Add the dependencies in the dependencyManagement section.
  • Add the plugins in the pluginManagement section.

Example for parent pom:

<project>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>Child1</module>
<module>Child2</module>
<module>Child3</module>
</modules>
<scm>
<!-- Link to your source code -->
</scm>
<build>
<plugins>
<plugin>
<groupId>plugin-groupId</groupId>
<artifactId>plugin-1</artifactId>
<version>1.0.7</version>
</plugin>
<pluginManagement>
<plugins>
<plugin>
<groupId>plugin-groupId</groupId>
<artifactId>plugin-2</artifactId>
<version>3.5.4</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-1</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-2</artifactId>
<version>2.0</version>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-3</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-4</artifactId>
<version>1.1.4</version>
<exclusions>
<exclusion>
<groupId>dependency-5</groupId>
<artifactId>dependency-5</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Child1</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Child2</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>Child3</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>Child1</module>
<module>Child2</module>
<module>Child3</module>
</modules>
</profile>
<profile>
<id>no-tests</id>
<modules>
<modules>
<module>Child1</module>
<module>Child3</module>
</modules>
</modules>
</profile>
</profiles>
</project>

Child modules.

A child module should have information regarding the parent module.

<parent>
<artifactId>parent</artifactId>
<groupId>com.group.id</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>

We do not need to add groupId or version tag to the child module as this will inherit this information from the parent module. We need a unique artifactId and the packaging type (jar/war).

For the dependencies and plugins, we need to mention the groupId, artifcatId, and scope tag. We do not need to mention the version for any of the dependencies/plugins as it’s already defined in the parent pom and the child module uses the same, but if we want to override with other versions then we can add a version tag in the child module. As we are maintaining the standard version in the parent pom and if we update the version then child modules will inherit the same version, so it’s just updated once and used everywhere.

That’s it, now if we trigger build for the parent module then it builds the child module in the order we defined in the modules section.

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] parent [pom]
[INFO] Child1 [jar]
[INFO] Child2 [jar]
[INFO] Child3 [jar]
...
[INFO] Reactor Summary for parent 1.0.0-SNAPSHOT:
[INFO] parent ......................................... SUCCESS [ 1.272 s]
[INFO] Child1 ......................................... SUCCESS [ 0.077 s]
[INFO] Child2.......................................... SUCCESS [ 0.980 s]
[INFO] Child3.......................................... SUCCESS [ 0.438 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Once the build completes, the child module will have the jar generated in its respective target folder.

Example for sub-modules:

<!-- Child1 module -->
<project >
<parent>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>Child1</artifactId>
<packaging>jar</packaging>
<scm>
<!-- Link to your source code -->
</scm>
<dependencies>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-1</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-2</artifactId>
<scope>runtime</scope>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-3</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

<!-- Child2 module -->
<project >
<parent>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>Child2</artifactId>
<packaging>jar</packaging>
<scm>
<!-- Link to your source code -->
</scm>
<dependencies>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-1</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>{project.groupId}</groupId>
<artifactId>Child1</artifactId>
<scope>runtime</scope>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-3</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

<!-- Child3 module -->
<project >
<parent>
<groupId>group</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>Child3</artifactId>
<packaging>jar</packaging>
<scm>
<!-- Link to your source code -->
</scm>
<dependencies>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-2</artifactId>
<scope>runtime</scope>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-3</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>groupId-1</groupId>
<artifactId>dependency-4</artifactId>
<version>1.0.7</version> <!-- overriding the version dedined in parent pom -->
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

Additional information.

We can use the profiles section in the Parent module to handle different configs or change the build order.

<profiles>
<profile>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>Child1</module>
<module>Child2</module>
<module>Child3</module>
</modules>
</profile>
<profile>
<id>no-tests</id>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
<modules>
<module>Child1</module>
<module>Child3</module>
</modules>
</profile>
</profiles>

If we run mvn install it builds all three modules by default.

If we want our reactor to build only two modules and skip the integration tests then we can use the second profile.

We need to pass the id given in the profile section.

mvn install -P no-tests

This builds only Child1 and Child3 modules while skipping the integration tests (if we provide this property to the test plugin).

In the same way, we can define other configurations of individual modules in the profiles section.

You can read more about Profiles here.

In case there are no profiles defined and there is a necessity to build only one module then we can use this command to trigger build for individual or multiple modules.

mvn install -pl Child1

mvn install -pl Child1, Child3

Read more about Reactor here.

About the Author:
Dushyanth Gowda is a React Developer here at Version 1.

--

--