Build Fat Jar In Maven Multi-Module Project

I have used shade plugin same as you to create an uber jar. Maybe you call it a fat jar or shaded jar. Recently I wanted to build a fat jar in a Maven multi-module project. The exciting part was, it supposed to alter the final assembly based on different profiles. I’ll showcase the requirement in the following diagram so you can easily understand it.

Fat jar in maven multi module project based on profiles

The project has five modules and two profiles. You can find their relationships with each other in the following diagram.

Modules relationships with each other

Before diving into the POM I believe that you are well aware of the maven shade plugin. Also, I assume that you know how to deal with maven profiles. So let’s dive in. The following snippet is the pom of the root project.

<?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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.aptkode</groupId>
    <artifactId>maven-multimodule-uber-jar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>moduleA</module>
        <module>moduleB</module>
        <module>moduleC</module>
        <module>moduleD</module>
        <module>moduleE</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>3.2.2</version>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>14</release>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>profile-1</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>profile-2</id>
        </profile>
    </profiles>
</project>

I’m not going to list all pom files here. Have a look at the relationship diagram. Then you can easily identify what are the dependencies should be in module D and E. Tricky module is the module B. That is the module which should generate different artifacts based on the profile. If we select profile one, it should create an artifact embedding module D. If we select profile 2, then it should embed module E. So following code snippet shows how the pom looks like.

<?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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.aptkode</groupId>
        <artifactId>maven-multimodule-uber-jar</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>moduleB</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.aptkode</groupId>
            <artifactId>moduleA</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.aptkode</groupId>
            <artifactId>moduleC</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>profile-1</id>
            <dependencies>
                <dependency>
                    <groupId>com.aptkode</groupId>
                    <artifactId>moduleD</artifactId>
                    <version>1.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </profile>
        <profile>
            <id>profile-2</id>
            <dependencies>
                <dependency>
                    <groupId>com.aptkode</groupId>
                    <artifactId>moduleE</artifactId>
                    <version>1.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </profile>
    </profiles>
</project>

The secret lies in the profile section and I think you have noticed it. We need different dependencies according to the profile, so shade plugin will generate a fat jar based on the dependencies available to the profile. So for profile one, shade plugin will generate jar with module A, B, C and D. It will do the same for profile two and instead of D, it will add module E.

Finally, I’ll give you a few tips to build a fat jar in a Maven project, especially if you want to deploy it. If you are planning to deploy both module B and fat jar you need to have the following configuration in the maven shade plugin.

<shadedArtifactAttached>true</shadedArtifactAttached>

You can read more details about the functionality here. There are more features available in the shade plugin such as filtering content for the uber jar. Have a look at the official web site of the plugin. I hope you found something useful. Thanks for reading, Happy Coding. Read my latest articles below.

Leave a Comment

Your email address will not be published. Required fields are marked *