Reading — step 1 of 4
Learn
Gradle is THE most-used build tool for the JVM (and increasingly outside it). Build files are Groovy scripts. Understanding the DSL is essential for any JVM dev.
Anatomy of a build.gradle
plugins {
id 'java'
id 'application'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.slf4j:slf4j-api:2.0.9'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}
application {
mainClass = 'com.example.Main'
}
tasks.test {
useJUnitPlatform()
}
Every line is Groovy. The blocks (plugins { }, dependencies { }) are closures with delegates. id 'java' invokes a method id with arg 'java'.
Tasks
Gradle's unit of work is a task. Plugins (like java) add tasks (compileJava, test, jar, assemble, etc.).
Custom task:
task hello {
doLast {
println "hello from gradle"
}
}
// In Gradle 7+:
tasks.register('hello') {
doLast {
println "hello"
}
}
Run with gradle hello or ./gradlew hello.
Task with type:
tasks.register('greet', GreetTask) {
name = 'Ada'
greeting = 'Hello'
}
class GreetTask extends DefaultTask {
@Input String name
@Input String greeting = 'Hi'
@TaskAction
void execute() {
println "$greeting, $name!"
}
}
Dependencies between tasks
tasks.register('first') { ... }
tasks.register('second') {
dependsOn 'first'
...
}
// Or:
tasks.named('compileJava') {
dependsOn 'generateProto'
}
Configuration vs execution
Gradle splits into:
- Configuration phase — top-level code in build.gradle runs to define tasks
- Execution phase — selected tasks'
doFirst/doLast/@TaskActionblocks run
This split confuses newcomers. Code OUTSIDE a doLast runs every time you invoke gradle, even for unrelated tasks. Code INSIDE only runs when that task executes.
Multi-project builds
A settings.gradle lists subprojects:
rootProject.name = 'monorepo'
include 'lib-foo'
include 'lib-bar'
include 'app-web'
Each subproject has its own build.gradle.
Shared config in allprojects { ... } or subprojects { ... }:
allprojects {
repositories { mavenCentral() }
}
subprojects {
apply plugin: 'java'
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}
}
Plugins
java,java-library,application— Java basicsgroovy— adds Groovy compilationkotlin('jvm')— Kotlinorg.springframework.boot— Spring Bootcom.github.johnrengelman.shadow— fat JARsjacoco— code coverage
Kotlin DSL
Gradle now supports build.gradle.kts (Kotlin DSL) — better IDE support, slightly more verbose. Many new projects use it. The Groovy DSL is still widely supported.
Why Groovy was chosen
- Closures + delegates → declarative-looking code with full programming power
- No type ceremony for build scripts
- IDE smart enough (mostly) thanks to
@DelegatesTo
Compared to Maven's pure-XML or Bazel's Starlark, Gradle's Groovy DSL is the most flexible at the cost of tooling complexity.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…