Creating simple Maven multi module project in Java
In this post, I will discuss how to create a simple Maven multi-module project. In multi-module projects, we have multiple modules to be built using Maven. We have external dependencies as well as internal dependencies between different modules. Let's figure out how we can create multi-modules projects in Maven and how the internal and external dependencies are handled by Maven during the build process?.
Technologies used:- Maven 3.3.3
- JDK 1.6
Simple Structure for Multi-Module Project
There are multiple ways to create the structure for multi-module maven projects. It depends on the project requirements, code repository structure, and project lifecycle (need for parent pom release, packaging, etc.). One of the simplest structures is given below:
Sample Project - RoketApp
In order to understand in a better way, let us create a sample multi-module project - RocketApp, similar to the above structure. RocketApp consist of two module - rocket-core & rocket-util .The rocket-core module is having a dependency on the rocket-util module.
You can create the above project structure manually or by using the Maven archetype.
Creating Manually:
Run the following command in the windows command prompt:
C:\>mkdir RocketApp
C:\>cd RocketApp
C:\RocketApp>mkdir parent
C:\RocketApp>mkdir rocket-core\src\main\java\com\pb\maven
C:\RocketApp>mkdir rocket-util\src\main\java\com\pb\maven
C:\RocketApp>mkdir rocket-util\src\test\java\com\pb\maven
Using Maven archetype:
An archetype is a template for a Maven project which is used by the Maven Archetype plugin to create new projects. There are many templates available, we will use the "maven-archetype-quickstart" template to create a new Java project. Please note that you should be connected to the internet so that Maven can download the necessary dependencies for creating a project using the quickstart template.Create rocket-util project:
mvn archetype:generate \
-DgroupId=com.pb.maven \
-DartifactId=rocket-util \
-Dversion=1.0-SNAPSHOT \
-DpackageName=com.pb.maven \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.0 \
-DinteractiveMode=false
Create rocket-core project:
mvn archetype:generate \
-DgroupId=com.pb.maven \
-DartifactId=rocket-core \
-Dversion=1.0-SNAPSHOT \
-DpackageName=com.pb.maven \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.0 \
-DinteractiveMode=false
Let's create a Java class - RocketEngine.java in rocket-util module and define method initialize().
RocketApp/rocket-util/src/main/java/com/pb/maven/RocketEngine.java:
package com.pb.maven;
public class RocketEngine
{
public static boolean intitialize(){
System.out.println("Rocket initialize ...");
return true;
}
}
Create a Junit Test - RocketEngineTest.java in the rocket-util module. This test will be executed by Maven during the build process.
RocketApp/rocket-util/src/test/java/com/pb/maven/RocketEngineTest.java:
package com.pb.maven;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class RocketEngineTest
{
@Test
public void testRocketEngine()
{
assertTrue( RocketEngine.intitialize());
}
}
Create a Java class - AppMain.java in the rocket-core module. Now we need to call RocketEngine.initialize() method defined under rocket-util module in AppMain.java in order to create dependency on the rocket-util module.
RocketApp/rocket-core/src/main/java/com/pb/maven/AppMain.java:
package com.pb.maven;
public class AppMain
{
public static void main( String[] args )
{
System.out.println("Launching rocket");
if(RocketEngine.intitialize())
{
System.out.println("Rocket ready to launch..");
}
}
}
Now we need to create Top-level POM and parent POM to include the multiple modules for Maven build.
Project Top Level POM:
Top-level POM contains a list of different modules of a project to be built. It can also contain multiple profiles for building a project. For example, it contains a profile for development build, a profile for production build, etc. The modules can be listed in any order. Maven build doesn't depend on the ordering of modules in the pom file. RocketApp/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- project coordinates -->
<groupId>com.pb.maven</groupId>
<artifactId>maven-multimodule</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Sample maven multi-module project</name>
<!-- Add project modules -->
<modules>
<module>parent</module>
<module>rocket-core</module>
<module>rocket-util</module>
</modules>
</project>
Project Parent POM:
POM is called a parent POM as it is inherited by all child POM. The dependencies in the parent will be available to all its child POM. So the dependencies which have been set in parent POM do not require to be in the child pom.xml file. If the same dependency is configured in parent and child pom.xml files but with different version numbers then the child pom.xml dependency version takes priority. The packaging type is should be - "pom" for parent pom.xml.
RocketApp/parent/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- project coordinates -->
<groupId>com.pb.maven</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>parent module</name>
<!-- set source file encoding to make build platform independent -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<!-- project dependencies -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Project Child POMs:
POM which inherits another POM file (Parent POM) is known as child POM. Child POM include the coordinate of parent POM under <parent> tag. As given below -
<parent>
<groupId>com.pb.maven</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
Here <relativePath> is an optional tag, If we do not provide <relativePath> in child POM then Maven will search parent pom in local repository first and then search remote repository.
RocketApp/rocket-util/pom.xml:
In child POMs dependencies will be inherited from parent POM. In this case - junit.4.12.jar file dependency is inherited from parent/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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- parent coordinates -->
<parent>
<groupId>com.pb.maven</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<!-- project coordinates -->
<groupId>com.pb.maven</groupId>
<artifactId>rocket-util</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>rocket-util</name>
</project>
Now we will add the local dependency of the rocket-util module in rocket-core POM. Here also remaining external dependency - junit.4.12.jar will be inherited from parent POM.
RocketApp/rocket-core/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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- parent coordinates -->
<parent>
<groupId>com.pb.maven</groupId>
<artifactId>parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<!-- project coordinates -->
<groupId>com.pb.maven</groupId>
<artifactId>rocket-core</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>rocket-core</name>
<!-- project dependencies-->
<dependencies>
<!-- local module dependency-->
<dependency>
<groupId>com.pb.maven</groupId>
<artifactId>rocket-util</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Build Project using Maven:
Now, it is time to build the multi-module project using Maven. The mechanism in Maven that handles multi-module projects is known as the reactor. Maven reactor does the following:
- List all the modules in the project to build.
- Sorts the projects into the correct build order, The reactor sorts all the projects in a way that guarantees any project is built before it is required.
- Builds the selected projects in build order.
C:\RocketApp>mvn clean install
Build Logs:
Note that we have added a rocket-core module before the rocket-util module in top-level POM. However, the Maven reactor sorts the modules in build order.
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] parent module
[INFO] rocket-util
[INFO] rocket-core
[INFO] Sample maven multi-module project
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building parent module 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
....
....
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running com.pb.maven.RocketEngineTest
Rocket initialize ...
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.1 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
....
....
....
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] parent module ...................................... SUCCESS [ 0.495 s]
[INFO] rocket-util ........................................ SUCCESS [ 3.273 s]
[INFO] rocket-core ........................................ SUCCESS [ 1.285 s]
[INFO] Sample maven multi-module project .................. SUCCESS [ 0.101 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.329 s
[INFO] Finished at: 2016-08-07T12:30:59+05:30
[INFO] Final Memory: 18M/140M
[INFO] ------------------------------------------------------------------------
Hope this article helped you to understand the basic multi-module java project build process using the Maven tool. If you have any comments or suggestions, please feel free to write in the comment section.
Thank you!! Very informational.
ReplyDeleteThank you
DeleteNice Post. Very useful information to everyone thanks for sharing.
ReplyDeleteDevOps Training
DevOps Online Training
DevOps Training in Hyderabad