Skip to content
bobby_dreamer

Creating FAT aka Uber JAR with Maven

java, maven1 min read

Earlier we have seen how to build a JAR file using Maven and see how the dependencies are copied to a separate dependency folder. Here we will see how Maven can create a JAR file which includes all the compiled Java classes from your project, and all compiled Java classes from all JAR files your project depends on. Basically it will be like all files combined into one file like an executable JAR file.

From what i have read Maven assembly plugin is not good in producing fat/uber jar, it may cause name conflict issue. Other recommended options are mentioned below, and does the same thing which is packaging all dependencies into one uber-JAR and with few additional things,

  • Maven shade plugin - This plugin is particularly useful as it merges content of specific files instead of overwriting them by relocating classes.
  • Maven one-jar plugin - This provides a custom class loader that knows how to load classes and resources from jars inside an archive, instead of from jars in the filesystem. Not actively maintained since 2012, so not going for this.

Run below command to create Maven project from command line

1mvn archetype:generate -DgroupId=com.bobbydreamer \
2 -DartifactId=uber_jar \
3 -DarchetypeArtifactId=maven-archetype-quickstart \
4 -DinteractiveMode=false

You project tree should look like this

tree
1D:\BigData\3. Java\Workspaces\Mavens\uber_jar>tree
2Folder PATH listing for volume New Volume
3Volume serial number is C415-8F09
4D:.
5├───.settings
6├───logs
7└───src
8 ├───main
9 │ ├───java
10 │ │ └───com
11 │ │ └───bobbydreamer
12 │ └───resources
13 └───test
14 ├───java
15 │ └───com
16 │ └───bobbydreamer
17 └───resources

Below is the Shade plugin configuration part of pom.xml

pom.xml
1<!-- Maven Shade Plugin -->
2 <plugin>
3 <groupId>org.apache.maven.plugins</groupId>
4 <artifactId>maven-shade-plugin</artifactId>
5 <version>2.3</version>
6 <executions>
7 <!-- Run shade goal on package phase -->
8 <execution>
9 <phase>package</phase>
10 <goals>
11 <goal>shade</goal>
12 </goals>
13 <configuration>
14 <transformers>
15 <!-- add Main-Class to manifest file -->
16 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
17 <mainClass>com.bobbydreamer.App</mainClass>
18 </transformer>
19 </transformers>
20 </configuration>
21 </execution>
22 </executions>
23 </plugin>

Here is the full XML file

pom.xml
1<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3 <modelVersion>4.0.0</modelVersion>
4
5 <groupId>com.bobbydreamer</groupId>
6 <artifactId>uber_jar</artifactId>
7 <packaging>jar</packaging>
8 <version>1.0-SNAPSHOT</version>
9
10 <name>uber_jar</name>
11 <url>http://www.bobbydreamer.com</url>
12
13 <!-- This is required for building successfully -->
14 <properties>
15 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16 <maven.compiler.source>1.7</maven.compiler.source>
17 <maven.compiler.target>1.7</maven.compiler.target>
18 </properties>
19
20 <dependencies>
21 <dependency>
22 <groupId>junit</groupId>
23 <artifactId>junit</artifactId>
24 <version>3.8.1</version>
25 <scope>test</scope>
26 </dependency>
27
28 <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
29 <dependency>
30 <groupId>org.apache.logging.log4j</groupId>
31 <artifactId>log4j-api</artifactId>
32 <version>2.14.1</version>
33 </dependency>
34
35 <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
36 <dependency>
37 <groupId>org.apache.logging.log4j</groupId>
38 <artifactId>log4j-core</artifactId>
39 <version>2.14.1</version>
40 </dependency>
41 </dependencies>
42
43 <build>
44 <!-- <finalName>uber_shade</finalName> -->
45 <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
46 <plugins>
47 <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
48 <plugin>
49 <artifactId>maven-clean-plugin</artifactId>
50 <version>3.1.0</version>
51 </plugin>
52 <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
53 <plugin>
54 <artifactId>maven-compiler-plugin</artifactId>
55 <version>3.8.0</version>
56 </plugin>
57
58 <plugin>
59 <artifactId>maven-surefire-plugin</artifactId>
60 <version>2.22.1</version>
61 </plugin>
62
63 <plugin>
64 <artifactId>maven-install-plugin</artifactId>
65 <version>2.5.2</version>
66 </plugin>
67
68 <plugin>
69 <artifactId>maven-deploy-plugin</artifactId>
70 <version>2.8.2</version>
71 </plugin>
72
73 <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
74 <plugin>
75 <artifactId>maven-site-plugin</artifactId>
76 <version>3.7.1</version>
77 </plugin>
78
79 <plugin>
80 <artifactId>maven-project-info-reports-plugin</artifactId>
81 <version>3.0.0</version>
82 </plugin>
83
84 </plugins>
85 </pluginManagement>
86
87 <plugins>
88
89 <plugin>
90 <artifactId>maven-jar-plugin</artifactId>
91 <version>3.0.2</version>
92 <configuration>
93 <archive>
94 <manifest>
95 <addClasspath>true</addClasspath>
96 <mainClass>com.bobbydreamer.App</mainClass>
97 <classpathPrefix>dependency-jars/</classpathPrefix>
98 </manifest>
99 </archive>
100 </configuration>
101 </plugin>
102
103 <!-- Copy project dependency -->
104 <plugin>
105 <groupId>org.apache.maven.plugins</groupId>
106 <artifactId>maven-dependency-plugin</artifactId>
107 <version>2.5.1</version>
108 <executions>
109 <execution>
110 <id>copy-dependencies</id>
111 <phase>package</phase>
112 <goals>
113 <goal>copy-dependencies</goal>
114 </goals>
115 <configuration>
116 <!-- exclude junit, we need runtime dependency only -->
117 <includeScope>runtime</includeScope>
118 <outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>
119 </configuration>
120 </execution>
121 </executions>
122 </plugin>
123
124
125 <!-- Maven Shade Plugin -->
126 <plugin>
127 <groupId>org.apache.maven.plugins</groupId>
128 <artifactId>maven-shade-plugin</artifactId>
129 <version>2.3</version>
130 <executions>
131 <!-- Run shade goal on package phase -->
132 <execution>
133 <phase>package</phase>
134 <goals>
135 <goal>shade</goal>
136 </goals>
137 <configuration>
138 <transformers>
139 <!-- add Main-Class to manifest file -->
140 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
141 <mainClass>com.bobbydreamer.App</mainClass>
142 </transformer>
143 </transformers>
144 </configuration>
145 </execution>
146 </executions>
147 </plugin>
148
149 </plugins>
150 </build>
151
152</project>

This is the clean and package output

1[INFO] Scanning for projects...
2[INFO]
3[INFO] ---------------------< com.bobbydreamer:uber_jar >----------------------
4[INFO] Building uber_jar 1.0-SNAPSHOT
5[INFO] --------------------------------[ jar ]---------------------------------
6[INFO]
7[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ uber_jar ---
8[INFO]
9[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ uber_jar ---
10[INFO] Using 'UTF-8' encoding to copy filtered resources.
11[INFO] Copying 1 resource
12[INFO]
13[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ uber_jar ---
14[INFO] Changes detected - recompiling the module!
15[INFO] Compiling 1 source file to D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\classes
16[INFO]
17[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ uber_jar ---
18[INFO] Using 'UTF-8' encoding to copy filtered resources.
19[INFO] Copying 0 resource
20[INFO]
21[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ uber_jar ---
22[INFO] Changes detected - recompiling the module!
23[INFO] Compiling 1 source file to D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\test-classes
24[INFO]
25[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ uber_jar ---
26[INFO]
27[INFO] -------------------------------------------------------
28[INFO] T E S T S
29[INFO] -------------------------------------------------------
30[INFO] Running com.bobbydreamer.AppTest
31[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.013 s - in com.bobbydreamer.AppTest
32[INFO]
33[INFO] Results:
34[INFO]
35[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
36[INFO]
37[INFO]
38[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ uber_jar ---
39[INFO] Building jar: D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\uber_jar-1.0-SNAPSHOT.jar
40[INFO]
41[INFO] --- maven-dependency-plugin:2.5.1:copy-dependencies (copy-dependencies) @ uber_jar ---
42[INFO] Copying log4j-core-2.14.1.jar to D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\dependency-jars\log4j-core-2.14.1.jar
43[INFO] Copying log4j-api-2.14.1.jar to D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\dependency-jars\log4j-api-2.14.1.jar
44[INFO]
45[INFO] --- maven-shade-plugin:2.3:shade (default) @ uber_jar ---
46[INFO] Including org.apache.logging.log4j:log4j-api:jar:2.14.1 in the shaded jar.
47[INFO] Including org.apache.logging.log4j:log4j-core:jar:2.14.1 in the shaded jar.
48[INFO] Replacing original artifact with shaded artifact.
49[INFO] Replacing D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\uber_jar-1.0-SNAPSHOT.jar with D:\BigData\3. Java\Workspaces\Mavens\uber_jar\target\uber_jar-1.0-SNAPSHOT-shaded.jar
50[INFO] Dependency-reduced POM written at: D:\BigData\3. Java\Workspaces\Mavens\uber_jar\dependency-reduced-pom.xml
51[INFO] ------------------------------------------------------------------------
52[INFO] BUILD SUCCESS
53[INFO] ------------------------------------------------------------------------
54[INFO] Total time: 30.096 s
55[INFO] Finished at: 2021-07-30T22:55:21+05:30
56[INFO] ------------------------------------------------------------------------

Executing mvn clean package generates two JAR files,

  • uber_jar-1.0-SNAPSHOT.jar: the self-contained executable JAR
  • original-uber_jar-1.0-SNAPSHOT.jar: the normal JAR without the embedded dependencies but with the use of maven-jar-plugin and maven-dependency-plugin, we have copied the all the dependencies to a separate folder and made it to work.

JAR Execution output

References