Maven – Create a fat Jar file – One-JAR example

java jar with maven

In this tutorial, we will show you how to use Maven build tool, One-JAR plugin to create a single Jar together with its dependency Jars into a single executable Jar file, so called fat Jar.

Tools used :

  1. Maven 3.1.1
  2. JDK 1.7
  3. Joda-time 2.5

1. Create a simple Java project

Create a Java project from the Maven quick start template.


$ mvn archetype:generate -DgroupId=com.mkyong.core.utils -DartifactId=dateUtils 
 -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

The following files and folder structure will be created.


.
|____dateUtils
| |____pom.xml
| |____src
| | |____main
| | | |____java
| | | | |____com
| | | | | |____mkyong
| | | | | | |____core
| | | | | | | |____utils
| | | | | | | | |____App.java
| | |____test
| | | |____java
| | | | |____com
| | | | | |____mkyong
| | | | | | |____core
| | | | | | | |____utils
| | | | | | | | |____AppTest.java

Make it support Eclipse.


$ mvn eclipse:eclipse

Imports the project into Eclipse IDE.

one-jar-folder-structure

2. Update Pom.xml

Update pom.xml to declare the jodatime dependencies. For output to a Jar format, make sure the packaging tag is set to ‘jar’. Read the comments 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>

		  <!-- Make this jar executable -->
		  <plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-jar-plugin</artifactId>
			<configuration>
			   <archive>
			     <manifest>
				<mainClass>com.mkyong.core.utils.App</mainClass>
			     </manifest>
			   </archive>
			</configuration>
		  </plugin>
						
		</plugins>
	</build>
	
</project>

3. Get CurrentDate with JodaTime

Update the generated App.java with the following content :

App.java

package com.mkyong.core.utils;

import org.joda.time.LocalDate;

public class App {

	public static void main(String[] args) {

		System.out.println(getLocalCurrentDate());
	}

	//Print current date with JodaTime
	private static String getLocalCurrentDate() {
		
		LocalDate date = new LocalDate();
		return date.toString();
		
	}

}

4. Jar File

Maven package the project to generate the final Jar file. A new dateutils.jar is created in the $project/target folder.


$ mvn package

List out the jar content.


$ jar tf target/dateutils.jar 

META-INF/
META-INF/MANIFEST.MF
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

Try to run this Jar file.


$ java -jar dateutils.jar 
Exception in thread "main" java.lang.NoClassDefFoundError: org/joda/time/LocalDate
	at com.mkyong.core.utils.App.getLocalCurrentDate(App.java:14)
	at com.mkyong.core.utils.App.main(App.java:9)
Caused by: java.lang.ClassNotFoundException: org.joda.time.LocalDate
	at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
	... 2 more

Above is the expected error message, because the joda-time.jar is missing.

5. One-Jar Example

Update pom.xml to use One-Jar plugin, it will create a single Jar together with its dependency Jars.

pom.xml

<project>

  <build>
     <plugins>

	<!-- Includes the runtime dependencies -->
	<plugin>
		<groupId>org.dstovall</groupId>
		<artifactId>onejar-maven-plugin</artifactId>
		<version>1.4.4</version>
		<executions>
		  <execution>
			<goals>
				<goal>one-jar</goal>
			</goals>
		  </execution>
		</executions>
	</plugin>

	</plugins>
  </build>

  <!-- One-Jar is in the googlecode repository -->
  <pluginRepositories>
	<pluginRepository>
		<id>onejar-maven-plugin.googlecode.com</id>
		<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
	</pluginRepository>
  </pluginRepositories>
	
</project>

Package it again, two jars will be created in the “target” folder – dateUtils.jar and dateUtils-one-jar.jar.


$ mvn package

The dateUtils-one-jar.jar is the final fat-jar you want, list out the jar content :


$ jar tf target/dateutils.one-jar.jar 

META-INF/MANIFEST.MF

main/dateutils.jar
lib/joda-time-2.5.jar

com/
com/simontuffs/
com/simontuffs/onejar/
.version
OneJar.class
com/simontuffs/onejar/Boot$1.class
com/simontuffs/onejar/Boot$2.class
com/simontuffs/onejar/Boot$3.class
com/simontuffs/onejar/Boot.class
com/simontuffs/onejar/Handler$1.class
com/simontuffs/onejar/Handler.class
com/simontuffs/onejar/IProperties.class
com/simontuffs/onejar/JarClassLoader$1.class
com/simontuffs/onejar/JarClassLoader$2.class
com/simontuffs/onejar/JarClassLoader$ByteCode.class
com/simontuffs/onejar/JarClassLoader$FileURLFactory$1.class
com/simontuffs/onejar/JarClassLoader$FileURLFactory.class
com/simontuffs/onejar/JarClassLoader$IURLFactory.class
com/simontuffs/onejar/JarClassLoader$OneJarURLFactory.class
com/simontuffs/onejar/JarClassLoader.class
com/simontuffs/onejar/OneJarFile$1.class
com/simontuffs/onejar/OneJarFile$2.class
com/simontuffs/onejar/OneJarFile.class
com/simontuffs/onejar/OneJarURLConnection.class
src/
src/com/
src/com/simontuffs/
src/com/simontuffs/onejar/
src/OneJar.java
src/com/simontuffs/onejar/Boot.java
src/com/simontuffs/onejar/Handler.java
src/com/simontuffs/onejar/IProperties.java
src/com/simontuffs/onejar/JarClassLoader.java
src/com/simontuffs/onejar/OneJarFile.java
src/com/simontuffs/onejar/OneJarURLConnection.java
doc/
doc/one-jar-license.txt

One-Jar plugin puts the runtime dependencies in the lib folder, for example lib/joda-time-2.5.jar, and the main jar in the main folder, for example main/dateutils.jar. In additional, it also creates many simontuffs classes to help loads the included Jars correctly.

Try to run the final fat-jar.


$ java -jar dateutils.one-jar.jar 

2014-10-18

Done.

Download Source Code

Download – maven-one-jar-example.zip (6 KB)

References

  1. onejar-maven-plugin official page
  2. Joda Time
  3. How to create a jar file with Maven

About the Author

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

Comments

Leave a Reply

avatar
newest oldest most voted
James Green
Guest
James Green

This should be discouraged in favour of the maven-assembly-plugin which, in contrast, is officially maintained and released to Central.

If you need more control to avoid clashes, the maven-shade-plugin is again official and maintained, unlike onejar.

? ?
Guest
? ?

is it like maven-assembly-plugin ?

mkyong
Guest
mkyong

The way it “JAR” the project dependencies is different. The main problem of assembly is if your project has many dependencies it may cause name override issue, in this case, give one-jar a try :)

https://code.google.com/p/onejar-maven-plugin/

Tito
Guest
Tito

Nice tutorial.
For the past few days I’ve been trying, without success, to create a jar with my dependencies which includes some native libraries from http://sigar.hyperic.com.
Could you try this yourself?
Thank you for your work.

mkyong
Guest
mkyong

Not sure what to try, refer to this one-jar usage page – http://onejar-maven-plugin.googlecode.com/svn/mavensite/usage.html

To include native libraries, you need to define

${project.build.directory}/dllextract

test.dll