Work with the Gradle build system and Kotlin DSL. Use when editing `build.gradle.kts`, `settings.gradle.kts`, `gradle.properties`, lockfiles, dependency versions, or troubleshooting Gradle build behavior.
Guidance for working with Gradle build system.
Look for these files to determine if dependency locking is enabled:
gradle.lockfile (project dependencies)buildscript-gradle.lockfile (buildscript classpath)*/gradle.lockfile (module-specific)*/buildscript-gradle.lockfile (module-specific buildscript)If dependency locking is enabled, update lockfiles after changing dependencies:
./gradlew dependencies --write-locks
To force refresh before updating:
./gradlew dependencies --refresh-dependencies --write-locks
When investigating dependency issues:
*.lockfile files./gradlew dependencies
./gradlew dependencies --configuration runtimeClasspath
./gradlew build # Build and test
./gradlew check # Run all checks (tests, linting)
./gradlew test # Run unit tests
./gradlew clean # Clean build outputs
Guidance for using the Gradle Shadow plugin to create fat JARs with relocated dependencies.
Error: Cannot read field "forJava" because "parsedFileName" is null
Cause: The shadow plugin's minimize() feature uses jdependency library to analyze class usage. When certain JAR files have unusual filenames or metadata, jdependency fails to parse them, resulting in a NPE.
When it happens:
Fix: Remove minimize() from your ShadowJar configuration:
// BEFORE (may cause NPE)
tasks.withType<ShadowJar>().configureEach {
minimize()
}
// AFTER (stable)
tasks.withType<ShadowJar>().configureEach {
// Use include/exclude filters instead
dependencies {
include { it.moduleGroup == "com.example" }
}
}
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
tasks.withType<ShadowJar>().configureEach {
archiveClassifier.set("")
relocate("org.eclipse.jgit", "com.mycompany.shaded.jgit")
relocate("com.google.common", "com.mycompany.shaded.guava")
}
Only include specific dependencies in the shadow JAR:
tasks.withType<ShadowJar>().configureEach {
dependencies {
include { it.moduleGroup == "com.example" && it.moduleName == "library" }
include { it.moduleGroup == "com.google.guava" }
}
}
Exclude specific dependencies (include everything else):
tasks.withType<ShadowJar>().configureEach {
dependencies {
exclude { it.moduleGroup == "io.vavr" }
exclude { it.moduleGroup == "org.slf4j" }
exclude { it.moduleName == "some-library" }
}
}
Common relocation patterns for popular libraries:
| Original Package | Relocated Package |
|---|---|
org.eclipse.jgit | com.mycompany.shaded.jgit |
com.google.common | com.mycompany.shaded.guava |
org.apache.commons | com.mycompany.shaded.commons |
When publishing a Gradle plugin with shadow:
archiveClassifier.set("") to make shadow JAR the main artifactgradlePlugin {
plugins {
register("my.plugin.id") {
implementationClass = "com.mycompany.MyPlugin"
}
}
}
If using dependency locking with the shadow plugin, note that it may create additional configurations (e.g., shadow, shadowMinimizeApi). After updating dependencies, verify lockfiles include these configurations:
./gradlew dependencies --write-locks
SPDX-FileCopyrightText: Copyright © 2026 Caleb Cushing
SPDX-License-Identifier: CC-BY-NC-SA-4.0