Java › Build Tools: Maven & Gradle

How would you configure a Maven or Gradle build to produce a shaded/fat JAR containing all dependencies bundled into a single executable JAR file?

Advanced

Answer

Maven's maven-shade-plugin (or Gradle's Shadow plugin) merges the compiled application classes together with the classes from every dependency JAR into one self-contained "fat" or "shaded" JAR, additionally configuring a manifest Main-Class entry so the result can be run directly via java -jar -- this is valuable for simple deployment scenarios (avoiding needing to separately manage a classpath of many individual dependency JARs), though it can introduce dependency conflicts if multiple bundled dependencies each contain resources at the same path (requiring explicit merge strategies), and produces a notably larger artifact than a thin JAR relying on an external classpath.
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals><goal>shade</goal></goals>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>com.example.Main</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>
Real-world example A command-line utility distributed to end users is packaged as a single shaded JAR bundling all its dependencies, letting users run it with a single `java -jar tool.jar` command without needing to separately download and manage a classpath of a dozen individual dependency JARs.

Common follow-ups: What merge strategy conflicts commonly arise when shading multiple dependencies that each bundle a META-INF/services file at the same path?;When would a thin JAR with an external classpath be preferable to a shaded fat JAR?