Gradle Kotlin DSL and Groovy DSL, dependency management, version catalogs, build lifecycle, task configuration, multi-project builds, and performance optimization for Java/Kotlin projects.
Last Updated: 2025-10-26
Use this skill when:
Alternatives: Maven (convention over configuration), Bazel (monorepos), sbt (Scala)
Prerequisites: JDK 11+ installed, Gradle 8.0+ (8.10 latest as of 2024)
# Initialize project with wrapper
gradle init --type java-application --dsl kotlin
# Use wrapper (ensures consistent Gradle version)
./gradlew build # Unix/macOS
gradlew.bat build # Windows
# Upgrade wrapper
./gradlew wrapper --gradle-version 8.10
Kotlin DSL (build.gradle.kts) - Recommended for new projects:
// Type-safe, IDE support, refactoring
plugins {
kotlin("jvm") version "1.9.24"
application
}
repositories {
mavenCentral()
}
dependencies {
implementation("com.google.guava:guava:32.1.3-jre")
testImplementation(kotlin("test"))
}
application {
mainClass.set("com.example.AppKt")
}
tasks.test {
useJUnitPlatform()
}
Groovy DSL (build.gradle) - Legacy, but still common:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.9.24'
id 'application'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.google.guava:guava:32.1.3-jre'
testImplementation 'org.jetbrains.kotlin:kotlin-test'
}
application {
mainClass = 'com.example.AppKt'
}
test {
useJUnitPlatform()
}
project/
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew # Unix wrapper script
├── gradlew.bat # Windows wrapper script
├── settings.gradle.kts # Project settings
├── build.gradle.kts # Root build file
├── gradle.properties # Build properties
└── src/
├── main/
│ ├── java/
│ ├── kotlin/
│ └── resources/
└── test/
├── java/
├── kotlin/
└── resources/
// build.gradle.kts
dependencies {
// Compile and runtime
implementation("org.slf4j:slf4j-api:2.0.9")
// Compile only (not in runtime classpath)
compileOnly("org.projectlombok:lombok:1.18.30")
// Runtime only
runtimeOnly("org.postgresql:postgresql:42.6.0")
// API (exposed to consumers, use sparingly)
api("com.google.guava:guava:32.1.3-jre")
// Test dependencies
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// Annotation processing
annotationProcessor("org.projectlombok:lombok:1.18.30")
kapt("com.google.dagger:dagger-compiler:2.48")
}
# gradle/libs.versions.toml
[versions]
kotlin = "1.9.24"
junit = "5.10.0"
guava = "32.1.3-jre"
[libraries]
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
guava = { module = "com.google.guava:guava", version.ref = "guava" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
// build.gradle.kts - Use catalog
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.guava)
testImplementation(libs.junit.jupiter)
}
plugins {
alias(libs.plugins.kotlin.jvm)
}
// Force specific version
configurations.all {
resolutionStrategy {
force("com.google.guava:guava:32.1.3-jre")
}
}
// Exclude transitive dependency
dependencies {
implementation("com.example:lib:1.0") {
exclude(group = "org.slf4j", module = "slf4j-log4j12")
}
}
// Replace dependency
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("org.slf4j:slf4j-simple"))
.using(module("org.slf4j:slf4j-nop:2.0.9"))
}
}
// View dependency tree
// ./gradlew dependencies --configuration compileClasspath
Initialization → Configuration → Execution
↓ ↓ ↓
settings.gradle build.gradle Task execution
// Define custom task
tasks.register("hello") {
doLast {
println("Hello, Gradle!")
}
}
// Configure existing task
tasks.named<Test>("test") {
useJUnitPlatform()
maxHeapSize = "1G"
testLogging {
events("passed", "skipped", "failed")
}
}
// Task with inputs/outputs (incremental builds)
tasks.register<Copy>("processTemplates") {
from("src/templates")
into("$buildDir/generated")
expand(project.properties)
inputs.dir("src/templates")
outputs.dir("$buildDir/generated")
}
// Task dependencies
tasks.named("build") {
dependsOn("processTemplates")
}
// Define task class
abstract class GenerateVersionTask : DefaultTask() {
@get:Input
abstract val version: Property<String>
@get:OutputFile
abstract val outputFile: RegularFileProperty
@TaskAction
fun generate() {
outputFile.get().asFile.writeText("version=${version.get()}")
}
}
// Register task
tasks.register<GenerateVersionTask>("generateVersion") {
version.set(project.version.toString())
outputFile.set(layout.buildDirectory.file("version.properties"))
}
# Run specific task
./gradlew build # Build project
./gradlew clean # Clean build directory
./gradlew test # Run tests
./gradlew assemble # Build without tests
# Task selection
./gradlew :app:build # Build specific subproject
./gradlew build -x test # Exclude test task
# Parallel execution
./gradlew build --parallel # Parallel subproject builds
# Information
./gradlew tasks # List available tasks
./gradlew dependencies # Show dependency tree
./gradlew properties # Show project properties
multi-project/
├── settings.gradle.kts
├── build.gradle.kts # Root build file
├── app/
│ └── build.gradle.kts
├── core/
│ └── build.gradle.kts
└── utils/
└── build.gradle.kts
// settings.gradle.kts
rootProject.name = "multi-project"
include("app", "core", "utils")
// Optional: change project directory
project(":app").projectDir = file("application")
// build.gradle.kts (root)
plugins {
kotlin("jvm") version "1.9.24" apply false
}
allprojects {
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
}
subprojects {
apply(plugin = "org.jetbrains.kotlin.jvm")
dependencies {
// Common dependencies for all subprojects
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
}
tasks.withType<Test> {
useJUnitPlatform()
}
}
// app/build.gradle.kts
plugins {
application
}
dependencies {
implementation(project(":core"))
implementation(project(":utils"))
implementation("com.google.guava:guava:32.1.3-jre")
}
application {
mainClass.set("com.example.app.MainKt")
}
// settings.gradle.kts
includeBuild("../shared-library")
// Now can depend on included build
dependencies {
implementation("com.example:shared-library:1.0")
}
// gradle.properties
org.gradle.caching=true
// build.gradle.kts
tasks.withType<Test> {
outputs.cacheIf { true }
}
# Local cache (default: ~/.gradle/caches)
./gradlew build --build-cache
# Remote cache (for teams/CI)
# buildCache {
# remote<HttpBuildCache> {
# url = uri("https://cache.example.com")
# }
# }
# Enable configuration cache
./gradlew build --configuration-cache
# gradle.properties
org.gradle.configuration-cache=true
# gradle.properties
org.gradle.parallel=true
org.gradle.workers.max=4
org.gradle.caching=true
# gradle.properties
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=true
# Generate performance report
./gradlew build --profile
# Report at: build/reports/profile/profile-*.html
# Scan for insights (requires Gradle account)
./gradlew build --scan
// Core plugins (no version)
plugins {
java
application
}
// Community plugins (from Gradle Plugin Portal)
plugins {
id("org.springframework.boot") version "3.2.0"
id("io.spring.dependency-management") version "1.1.4"
}
// Apply to subprojects only
plugins {
kotlin("jvm") version "1.9.24" apply false
}
// Java projects
plugins {
java
`java-library` // For libraries (exposes API)
application // For executables
}
// Kotlin projects
plugins {
kotlin("jvm") version "1.9.24"
kotlin("plugin.spring") version "1.9.24"
}
// Spring Boot
plugins {
id("org.springframework.boot") version "3.2.0"
}
// Shadow (fat JAR)
plugins {
id("com.github.johnrengelman.shadow") version "8.1.1"
}
// Configure Java plugin
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
withSourcesJar()
withJavadocJar()
}
// Configure application plugin
application {
mainClass.set("com.example.MainKt")
applicationDefaultJvmArgs = listOf("-Xmx512m")
}
// Configure Shadow plugin
tasks.shadowJar {
archiveBaseName.set("myapp")
archiveClassifier.set("")
archiveVersion.set("1.0.0")
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
tasks.test {
useJUnitPlatform()
// Test selection
filter {
includeTestsMatching("*Test")
excludeTestsMatching("*IntegrationTest")
}
// Logging
testLogging {
events("passed", "skipped", "failed")
showStandardStreams = false
}
// Parallelization
maxParallelForks = Runtime.getRuntime().availableProcessors()
// Reports
reports {
html.required.set(true)
junitXml.required.set(true)
}
}
// Create separate source set
sourceSets {
create("integrationTest") {
compileClasspath += sourceSets.main.get().output
runtimeClasspath += sourceSets.main.get().output
}
}
configurations["integrationTestImplementation"].extendsFrom(configurations.testImplementation.get())
tasks.register<Test>("integrationTest") {
testClassesDirs = sourceSets["integrationTest"].output.classesDirs
classpath = sourceSets["integrationTest"].runtimeClasspath
useJUnitPlatform()
}
# WRONG: Direct gradle command (version varies by machine)
gradle build
# CORRECT: Use wrapper (consistent version)
./gradlew build
// WRONG: Configuration in doLast (runs at execution)
tasks.register("bad") {
doLast {
project.dependencies.add("implementation", "com.example:lib:1.0")
}
}
// CORRECT: Configuration at configuration time
dependencies {
implementation("com.example:lib:1.0")
}
// WRONG: Deprecated configurations
dependencies {
compile("com.example:lib:1.0") // Removed in Gradle 7
testCompile("junit:junit:4.13.2")
}
// CORRECT: Modern configurations
dependencies {
implementation("com.example:lib:1.0")
testImplementation("junit:junit:4.13.2")
}
// WRONG: Scattered versions
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:3.2.0")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:3.2.0")
}
// CORRECT: Version catalogs or properties
val springBootVersion = "3.2.0"
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
implementation("org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion")
}
# Build lifecycle
./gradlew clean # Clean build directory
./gradlew build # Compile, test, assemble
./gradlew assemble # Build without tests
./gradlew test # Run tests only
# Information
./gradlew tasks # List available tasks
./gradlew dependencies # Show dependency tree
./gradlew projects # List subprojects
./gradlew properties # Show project properties
# Performance
./gradlew build --parallel # Parallel execution
./gradlew build --build-cache # Enable build cache
./gradlew build --profile # Generate performance report
./gradlew build --scan # Upload build scan
# Debugging
./gradlew build --info # Info logging
./gradlew build --debug # Debug logging
./gradlew build --stacktrace # Show stack traces
# Build performance
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
org.gradle.workers.max=4
# JVM settings
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m
# Daemon
org.gradle.daemon=true
# Project properties
version=1.0.0
group=com.example
# generate_buildscript.py - Generate Gradle dependencies
import json
with open('dependencies.json') as f:
deps = json.load(f)
for dep in deps:
config = dep.get('configuration', 'implementation')
print(f'{config}("{dep["group"]}:{dep["name"]}:{dep["version"]}")')
// build.gradle.kts - Use generated dependencies
val generatedDeps = providers.exec {
commandLine("python", "generate_buildscript.py")
}.standardOutput.asText.get()
// Note: This is illustrative; in practice, use version catalogs
maven-configuration.md - Alternative JVM build systembuild-system-selection.md - Choosing between Gradle, Maven, Bazelbazel-monorepos.md - Alternative for large-scale projectsbuild-optimization.md - Build caching strategiescicd/github-actions-workflows.md - Gradle in CI pipelinesGradle is the dominant build system for JVM projects, offering flexibility and performance:
Key Takeaways:
--parallel for multi-module projects2024 Benchmark Data: Gradle 8.x with configuration cache and parallel execution is 2-3x faster than Maven for multi-module builds, and competitive with Bazel for JVM-only projects (Bazel excels at polyglot monorepos).
Gradle's flexibility makes it ideal for complex JVM projects, Android development, and polyglot builds requiring custom logic.