Creating a fat JAR with Gradle, find dependencies at runtime.

By Steve Claridge on 2022-11-09.

You are building a Java application that creates a JAR (not a Spring/Web/Enterprise WAR/EAR project) using an IDE, e.g. IntelliJ, and using Gradle as your build mechanism. Your project uses a bunch of dependencies, you add them to you build.gradle file and this works fine when you build and run from within the IDE.

For example if your project use SQLite you'd add this to the Gradle build config:

implementation group: 'org.xerial', name: 'sqlite-jdbc', version: '3.7.2'

Gradle pulls this dependency from a Maven repository, stores it in the local Gradle dependency directory and makes if findable by the project when you run it from your IDE's run command.

The problem is when you want to run your project from outside of the IDE, your dependencies still need to be found at runtime, but the IDE doesn't do the work for you now. You have two options, either you manually copy all of your dependencies into a directory and then reference them from your java command-line, or, you create a fat JAR.

A fat JAR is simply a JAR file that contains all of your code and all of the JARs that your code depends on. Obviously this means the JAR will be much bigger. This is how Spring Boot works from a single JAR, it bundles the project code, an HTTP server and all dependencies together.

To create a fat JAR from Gradle, you simply add the following section in the build.gradle config file:

jar {
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

You might also want to check out How to fix no main manifest attribute error.