Roughly speaking, you have two options
- Make a "fat" JAR with all required classes present
- Make a "thin" JAR that references other JAR files
What is most suitable for your situation is something only you can decide. Here's how you do it:
Make a "fat" JAR with all required classes present
To follow this approach, you use the Maven Shade Plugin. In the package phase, you would invoke its shade goal. That would copy classes from your dependencies as well as your application classes together into one JAR-file. It could look like this in the POM:
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>my-packaged-application</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.mycompany.MyApplication</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<!--
Shading signed JARs will fail without this.
http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
-->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
The advantage of this approach is that your application gets packaged as one file. The disadvantage is that it's rather large. Even when you change just a few lines of code for a new version, the whole file will be different.
Make a "thin" JAR that references other JAR files
In this approach, the JAR only contains your application classes. Its manifest file references the classpath, but you need to also provide the JAR file for the dependencies. To collect those, use the Maven Dependency Plugin, more specifically the copy-dependencies goal. You configure it like so:
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
Now you have all dependency JAR files in target/lib, and the last thing is make sure that the "thin" JAR references those. To do so, configure the Maven Jar Plugin:
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.mycompany.MyApplication</mainClass>
</manifest>
</archive>
</configuration>
In this approach, if you change just a few lines of your application code, only the application JAR will be replaced - the dependency JARs are left intact. On the downside, it requires you to distribute not one file but a directory structure: the application JAR file as well as the lib/ folder with its contents.