A common requirement for a Java application is that can be deployed by copying a single file. For simple applications that depend only on the standard Java SE class libraries, this requirement is satisfied by creating a JAR file containing all of the (compiled) application classes.
Things are not so straightforward if the application depends on third-party libraries. If you simply put dependency JAR files inside an application JAR, the standard Java class loader will not be able to find the library classes, and your application will not start. Instead, you need to create a single JAR file that contains the application classes and associated resources together with the dependency classes and resources. These need to be organized as a single namespace for the classloader to search.
The such a JAR file is often referred to as an UberJAR.
The procedure for creating an UberJAR is straight-forward. (I will use Linux commands for simplicity. The commands should be identical for Mac OS, and similar for Windows.)
Create a temporary directory, and change directory to it.
$ mkdir tempDir
$ cd tempDir
For each dependent JAR file, in the reverse order that they need to appear on the application's classpath, used the jar
command to unpack the JAR into the temporary directory.
$ jar -xf <path/to/file.jar>
Doing this for multiple JAR files will overlay contents of the JARs.
Copy the application classes from the build tree into the temporary directory
$ cp -r path/to/classes .
Create the UberJAR from the contents of the temporary directory:
$ jar -cf ../myApplication.jar
If you are creating an executable JAR file, include an appropriate MANIFEST.MF as described here.
If your project is built using Maven, you can get it to create an UberJAR using either the "maven-assembly" or "maven-shade" plugins. See the Maven Assembly topic (in the Maven documentation) for details.
Some of advantages of UberJARs are self-evident:
In addition, if you use an appropriate tooling to create the UberJAR, you will have the option of excluding library classes that are not used from the JAR file. However, that this is typically done by static analysis of the classes. If your application uses reflection, annotation processing and similar techniques, you need to be careful that classes are not excluded incorrectly.
UberJARs also have some disadvantages:
1 - Some open source library licenses allow you to use the library only of the end-user is able to replace one version of the library with another. UberJARs can make replacement of version dependencies difficult.