Main Tutorials

Create a fat Jar file – Maven Shade Plugin

java jar with maven

In this tutorial, we will show you how to use Maven Shade Plugin to create a Jar together with its dependency Jars into a single executable Jar file, so called fat Jar or uber Jar.

Note
Maven Shade plugin is a better plugin to create fat/uber jar, if compare with assembly plugin, because it provides class relocating feature, to avoid same class name conflict in the classpath.

1. Review a Java project

Previous Java project (dateutils) will be reused, see following folder structure

one-jar-folder-structure
Note
This project has a single dependency – joda-time.jar

2. Pom.xml

Read below comment for self-explanatory.

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>
	<groupId>com.mkyong.core.utils</groupId>
	<artifactId>dateUtils</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>dateUtils</name>
	<url>http://maven.apache.org</url>

	<properties>
		<jdk.version>1.7</jdk.version>
		<jodatime.version>2.5</jodatime.version>
		<junit.version>4.11</junit.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>joda-time</groupId>
			<artifactId>joda-time</artifactId>
			<version>${jodatime.version}</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>dateutils</finalName>
		<plugins>

			<!-- download source code in Eclipse, best practice -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>false</downloadJavadocs>
				</configuration>
			</plugin>

			<!-- Set a compiler level -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>${jdk.version}</source>
					<target>${jdk.version}</target>
				</configuration>
			</plugin>

		<!-- Maven Shade Plugin -->
		<plugin>
		  <groupId>org.apache.maven.plugins</groupId>
		  <artifactId>maven-shade-plugin</artifactId>
		  <version>2.3</version>
		  <executions>
		     <!-- Run shade goal on package phase -->
		    <execution>
			<phase>package</phase>
			<goals>
				<goal>shade</goal>
			</goals>
			<configuration>
			  <transformers>
				<!-- add Main-Class to manifest file -->
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
					<mainClass>com.mkyong.core.utils.App</mainClass>
				</transformer>
			  </transformers>
			</configuration>
		      </execution>
		  </executions>
		</plugin>

		</plugins>
	</build>

</project>

3. Package It

To produces the final Jar, just package it :


$ mvn package

[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ dateUtils ---
[INFO] Building jar: /Users/mkyong/dateUtils/target/dateutils.jar
[INFO] 
[INFO] --- maven-shade-plugin:2.3:shade (default) @ dateUtils ---
[INFO] Including joda-time:joda-time:jar:2.5 in the shaded jar.
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing /Users/mkyong/dateUtils/target/dateutils.jar with /Users/mkyong/dateUtils/target/dateUtils-1.0-SNAPSHOT-shaded.jar
[INFO] Dependency-reduced POM written at: /Users/mkyong/dateUtils/dependency-reduced-pom.xml
[INFO] Dependency-reduced POM written at: /Users/mkyong/dateUtils/dependency-reduced-pom.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.594s
[INFO] Finished at: Tue Oct 21 15:24:28 MYT 2014
[INFO] Final Memory: 17M/42M
[INFO] ------------------------------------------------------------------------

Two jar files will be created in the target folder.

  1. dateutils.jar – Project and dependency classes in a single jar, this is what you want.
  2. original-dateutils.jar – Only your project classes

P.S The generated dependency-reduced-pom.xml is for reference only, just ignore it.

4. Review It

List out the content of dateutils.jar


$ jar tf target/dateutils.jar 

META-INF/MANIFEST.MF
META-INF/
com/
com/mkyong/
com/mkyong/core/
com/mkyong/core/utils/
com/mkyong/core/utils/App.class
META-INF/maven/
META-INF/maven/com.mkyong.core.utils/
META-INF/maven/com.mkyong.core.utils/dateUtils/
META-INF/maven/com.mkyong.core.utils/dateUtils/pom.xml
META-INF/maven/com.mkyong.core.utils/dateUtils/pom.properties
META-INF/LICENSE.txt
META-INF/NOTICE.txt
org/
org/joda/
org/joda/time/
org/joda/time/base/
org/joda/time/base/AbstractDateTime.class
org/joda/time/base/AbstractDuration.class
//...
org/joda/time/Weeks.class
org/joda/time/YearMonth$Property.class
org/joda/time/YearMonth.class
org/joda/time/YearMonthDay$Property.class
org/joda/time/YearMonthDay.class
org/joda/time/Years.class
META-INF/maven/joda-time/
META-INF/maven/joda-time/joda-time/
META-INF/maven/joda-time/joda-time/pom.xml
META-INF/maven/joda-time/joda-time/pom.properties
MANIFEST.MF

Manifest-Version: 1.0
Build-Jdk: 1.7.0_05
Built-By: mkyong
Created-By: Apache Maven 3.1.1
Main-Class: com.mkyong.core.utils.App
Archiver-Version: Plexus Archiver

Run it


$ java -jar target/dateutils.jar 

2014-10-21

Download Source Code

Download it – dateUtils-maven-shade-plugin.zip (10 KB)

References

  1. Apache Maven Shade Plugin
  2. Apache Maven Assembly Plugin
  3. Create A Fat Jar File – Maven One-JAR Example
  4. Create a fat Jar file – Maven Assembly Plugin
  5. How to create a jar file with Maven

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
9 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
gopi naik
6 years ago

hi ,
As i see, shaded plugin will create two jars
1. dateutils.jar
2. original-dateutils.jar

Can we avoid of creating the original-dateutils.jar.
We have a requirement in which we need only the uber jar.

Shivi Goel
6 years ago

I have some third party jars which are not part of central repo that i need to include in the executable jar. Currently I have then under project base directory. It seems Maven assembly and shade plugin doesn’t include external dependencies in fat jar. Could you please help if it is possible to build executable jar which is having external libraries included?

gianna giavelli
4 years ago

apparently some of the dependent jars are signed and when they get sharded to fat jar java complains of a security error. So I can use the maven signing plugin, but not sure what is best way any thoughts or is there any way to have direct integration with the shard plugin?

Soonho
3 years ago

Thanks for your instruction. Regarding to “mvn package”, when I ran this command in the window 10 then I got this error message.

C:\Users\SK\Documents\NetBeansProjects>mvn package
‘mvn’ is not recognized as an internal or external command,
operable program or batch file.

I am using Netbeans 11. Is there a way to run the “mvn package” inside the netbeans?
I also built the project. The project made a fat jar. But, when I run the jar file, I got this error message:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread “main” java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
at java.base/sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:335)
at java.base/sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:268)
at java.base/java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
at java.base/java.util.jar.JarVerifier.update(JarVerifier.java:230)
at java.base/java.util.jar.JarFile.initializeVerifier(JarFile.java:758)
at java.base/java.util.jar.JarFile.ensureInitialization(JarFile.java:1035)
at java.base/java.util.jar.JavaUtilJarAccessImpl.ensureInitialization(JavaUtilJarAccessImpl.java:69)
at java.base/jdk.internal.loader.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:873)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:807)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:719)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:642)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:600)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:416)
at java.base/sun.launcher.LauncherHelper.loadMainClass(LauncherHelper.java:760)
at java.base/sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:655)

I guess that it is related to the security files which I need to remove from each jar.
Do you have any advice on how to fix it out?

Here is my pom.xml file:

4.0.0
com.mycompany
FSPFoodPriceMonitoring
1.0-SNAPSHOT
jar

UTF-8
13
13

com.google.maps
google-maps-services
0.9.3

com.opencsv
opencsv
4.0

mysql
mysql-connector-java
5.1.21

org.apache.poi
poi
4.1.2

commons-net
commons-net
3.3

commons-io
commons-io
2.4

com.sun.mail
javax.mail
1.6.0

org.jsoup
jsoup
1.13.1

org.glassfish
javax.json
1.0.4

org.apache.tika
tika-parsers
1.24

org.apache.tika
tika-core
1.24

net.sourceforge.htmlunit
htmlunit
2.40.0

FSPFoodPriceMonitoring

org.apache.maven.plugins
maven-eclipse-plugin
2.9

true
false

org.apache.maven.plugins
maven-compiler-plugin
2.3.2
<!– I removed this because of an error message

${jdk.version}
${jdk.version}

–>

org.apache.maven.plugins
maven-shade-plugin
2.3

package

shade

fsp.FSPFoodpriceMonitoringMain

regin
9 years ago

thanks mkyong! really helpful

Anant Kashyap
3 years ago

Hi,

I have created a thin jar for my project with no external dependencies and used maven-dependency-plugin with copy-dependencies as a goal so running maven copy command downloads all the required jars into the selected folder. But now I need to create a semi-fat jar with the selected dependencies within the main jar and exclude all the other remaining jars. Also is it possible to keep the main jar as thin jar only and keep the selected jars in a folder inside the target folder and keep the other jars in a separate folder?

Srini
4 years ago

I am trying to include a third party jar (this is not in rep!) in the dateutils.jar file that the above creates. But it is not getting included.
I did: (i) created “lib” folder under the basedir of project and copied “includeMe.jar” in it and (ii) Edited pom.xml like below:
Not sure what I am missing.
Thanks

Edited pom.xml:
Under


com.my.test
includeMe
1.0.0.0-SNAPSHOT
system
${basedir}/lib/includeMe.jar

Aryasindhu Sahu
7 years ago

Hi Daitri,

You can achieve this by following these steps :
1) Create a jar using shade plugin, dont include property file in the jar.
2) getResourceAsStream is not required if the file is in the same location as the jar file, use new File(“fileName.extn”);

Check if the jar file is containing all the files you need by opening it in a decompiler, eg JDGui

datri
9 years ago

I have an uber jar that I am executing with java -jar option, but I also have a requirement to specify -cp option with that command. However, java program is not passing along the value I specify with -cp option to the ClassLoader. How can I make sure that java program passes along the value specified with -cp option to the ClassLoader? I am trying read a properties file from the location specified in the -cp option using the getResourceAsStream method which is failing currently because of this……Any help is much appreciated