Effective Project Management with Parent POM

Effective Project Management with Parent POM

Project Object Model or POM is an XML file that contains information about project configuration details used by Maven to build the project.

Let us first create a simple POM with minimal information for my-module-1

<project>
  <modelVersion>1.0.0</modelVersion>
  <groupId>com.myApp.app</groupId>
  <artifactId>my-module-1</artifactId>
  <version>1</version>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.10.1</version>
    </dependency>
  </dependencies>
</project>

For my-module-2

<project>
  <modelVersion>1.0.0</modelVersion>
  <groupId>com.myApp.app</groupId>
  <artifactId>my-module-2</artifactId>
  <version>1</version>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.10.1</version>
    </dependency>
  </dependencies>
</project>

The project structure looks like:

.my-app
 |-- my-module-1
 |   `-- pom.xml
 |-- my-module-2
 |   `-- pom.xml
 `-- pom.xml

Since both my-module-1 and my-module-2 have the same dependency, this is where the parent POM comes into the picture. Let us create our parent POM with Project Inheritance.

Here we specify the parent POM in the children POM, and all the dependencies, plugin configuration, and plugin lists are merged and used while building the project. Our parent pom.xml looks like:

<project>
  <modelVersion>1.0.0</modelVersion>
  <groupId>com.myApp.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.10.1</version>
    </dependency>
  </dependencies>
</project>

Now the child pom.xml (my-module-1) will look like:

<project>
  <parent>
    <groupId>com.myApp.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>
  <modelVersion>1.0.0</modelVersion>
  <groupId>com.myApp.app</groupId>
  <artifactId>my-module-2</artifactId>
  <version>1</version>
</project>

This ensures that the dependencies get inherited. One advantage is that it lets you share dependencies, plugins, etc., by providing reuse. It also ensures that there are no conflicting versions among shared dependencies.

Another way to use a parent POM is through project aggregation. But here, instead of specifying the parent POM in the modules, the parent POM will specify the corresponding modules to build. This ensures that the Maven command invoked in the project parent will also invoke those of the module as well.

Now our parent POM becomes:

<project>
  <modelVersion>1.0.0</modelVersion>
  <groupId>com.myApp.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.10.1</version>
    </dependency>
  </dependencies>
  <modules>
    <module>my-module-1</module>
    <module>my-module-2</module>
  </modules>
</project>

And the child pom.xml becomes:

<project>
  <modelVersion>1.0.0</modelVersion>
  <groupId>com.myApp.app</groupId>
  <artifactId>my-module-1</artifactId>
  <version>1</version>
</project>

In conclusion, a parent POM is a powerful way to ensure minimal dependency conflict among modules and promotes reuse. We can either use inheritance or aggregation methods for using a parent POM.

Cheers