Maven Multi Module
As project size and complexity increases, it makes sense to split the project into multiple modules. While it is always possible to split the project into multiple projects and link them as dependencies, it complicates the build process. In Maven, the preferred approach is to structure the project as multi module project and delegate the rest to Maven.
In this tutorial, we go through a simple multi module project. Download the example code from GitHub Maven Examples and extract it to some location before going further.
Simple Multi Module Project
The Simple Multi Module project contains two modules - app and util. The util module provides a static method that joins multiple strings using Apache Commons Lang library and the app module calls it. Snippet from App.java is shown below
simple-multi/app/src/main/java/app/App.java
public class App {
public static void main(String[] args) {
System.out.println(new App().greet("World!"));
}
public String greet(String name) {
return Util.join("Hello ", name);
}
}
To build the project, run
$ cd simple-multi
$ mvn clean test
Maven builds both the modules in proper order, runs tests and outputs nice little summary.
Structure of multi module project
The layout of Simple Multi is
The directory simple-multi
is the top directory of the multi module project. It contains the parent POM also known as top-level POM, but the top level directory doesn’t contain any source folder.
Along with parent POM, the top level directory also contains two sub folders – app
and util
. These module folders are regular maven projects with source directories and pom.xml.
The top level as well as module POM differs slightly from the regular POM and let’s see what they holds.
Top Level POM
Maven Multi Module Project requires a parent POM at the project’s top level directory. The contents of the file is
simple-multi/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.codetab</groupId>
<artifactId>simple-multi</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>app</module>
<module>util</module>
</modules>
</project>
It defines project coordinates - groupId, artifactId and version - as in any normal project, but the packaging type is specified as pom instead of usual jar or war. Since top level project doesn’t contain any source directory, packaging is set as pom. The modules/module
elements add the modules - app and util.
To sum up, the top level POM specifies packaging type as pom and lists all sub modules.
Maven Reactor
While declaring the modules in parent POM there is no need to bother about their ordering as Maven uses software component called reactor to properly order the modules. In simple-multi, maven builds util module and then app as app depends on util.
Module POM
Next, let’s explore the util module folder. It contains normal source folders and its own pom.xml. The contents of util/pom.xml
is as below
util/pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codetab</groupId>
<artifactId>simple-multi</artifactId>
<version>1.0</version>
</parent>
<artifactId>util</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
The parent
element specifies the coordinates (groupId,artifactId and version) of parent project i.e. simple-multi, while the coordinates of util module is defined using just the artifactId
element. There is no need to specify groupId and version for module as they are derived from the parent. The dependencies/dependency
block defines the dependencies of util module - commons-lang3 and junit.
Next, let’s see the app/pom.xml
which is similar to util/pom.xml
except the dependencies block
which is as below
app/pom.xml
....
<dependencies>
<dependency>
<groupId>org.codetab</groupId>
<artifactId>util</artifactId>
<version>1.0</version>
</dependency>
....
</dependencies>
The app module uses methods from util module and for this, the app/pom.xml
specifies util as dependency.
To summarize,
The top level project (parent project),
- defines top level pom.xml which specifies the project coordinates with packaging type as pom and lists its sub modules
- contains module folders
- there are no source folders in top level project
Each module folder is nothing but normal maven project directory, however the pom.xml contains
parent
element specifies module’s parent- module coordinates is specified in the
artifactId
element. ThegroupId
andversion
are not specified as they are derived from parent coordinates - when one module depends on another module, then dependency is specified in
dependencies/dependency
element.
How to execute multi module project
We can compile, test and package a multi module with
$ mvn clean package
However, running a multi module with maven-exec-plugin is a two-step process. To run the project do as follows
$ cd simple-multi
$ mvn clean install
$ mvn exec:java -pl app -Dexec.mainClass=app.App
The install phase install the modules to local $HOME/.m2 repository and then we run the project. The option -pl app tells exec plugin to use app module and run its class app.App. Without install, build fails as maven is unable to download and resolve the util module dependency.
It is quite cumbersome to install the project in local repository before each run, especially in development phase. Fortunately, we can directly execute a multi module in Eclipse IDE without install. In the later chapter Eclipse and Maven Multi Module, we show how to create multi module project in Eclipse and run it straight away.
In the next tutorial, we extend the simple-multi example and convert it into a hierarchical multi module with multiple parent POM.