What is the `dependencies {}` block in a Gradle build script, and how do you add a dependency to a specific configuration inside it?
answer
- dependencies {} = where deps are declared
- line = configurationName(notation)
- config name chooses classpath
- plugins create the config methods
- Kotlin parens+quotes; Groovy terser
basics
~10 sThe dependencies {} block is where you declare a module's dependencies. Inside it you call a configuration name like implementation(...) with the dependency coordinates (group:name:version) to attach a dependency to that configuration.
solid answer
~40 sThe `dependencies {}` block in `build.gradle(.kts)` is the DSL where you declare which external modules (or projects) your module needs. Inside it, each line is a method call whose **name is the configuration** and whose **argument is the dependency notation**. So `implementation("com.google.guava:guava:33.0.0-jre")` adds Guava to the `implementation` configuration. The configuration determines *which classpath(s)* the dependency lands on — `implementation` (compile + runtime), `compileOnly`, `runtimeOnly`, `testImplementation`, etc. The plugins you apply create the available configurations: the `java` plugin adds `implementation`/`compileOnly`/`runtimeOnly`/`testImplementation`/`testRuntimeOnly`, and `java-library` additionally adds `api`. In Kotlin DSL the calls look like function invocations with parentheses; in Groovy DSL you can omit parentheses (`implementation 'group:name:version'`).
code
kotlin · 8 linesplugins { `java-library` }
dependencies {
api("com.google.guava:guava:33.0.0-jre")
implementation("org.slf4j:slf4j-api:2.0.13")
runtimeOnly("ch.qos.logback:logback-classic:1.5.6")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
}go deeper
Know it's the block where you list dependencies and that each line is configuration("group:name:version").
Explain that plugins create the configurations and the name selects the target classpath; note Kotlin vs Groovy DSL differences.
Discuss how the available configuration set derives from the plugin stack and the implications of choosing each.
Frame conventions for consistent dependency declaration (DSL choice, configuration discipline) across a large build.
## What the block is Every Gradle module (subproject) has a `build.gradle` (Groovy) or `build.gradle.kts` (Kotlin) script. The `dependencies {}` block is the standard place to declare dependencies. It's a configuration block on the project; inside it, the receiver exposes a method per **configuration**. ## The shape of a declaration ``` <configurationName>(<dependency notation>) ``` - **configurationName** — e.g. `implementation`, `api`, `compileOnly`, `runtimeOnly`, `testImplementation`. This is literally a method created by the applied plugins. If you call a configuration that doesn't exist (e.g. `api` without `java-library`), the build fails with an unknown-method error. - **dependency notation** — most commonly the `group:name:version` string coordinate. (Other notations like `project(...)`, files, and maps exist but belong to neighboring topics.) ## Kotlin vs Groovy DSL ```kotlin // build.gradle.kts (Kotlin DSL) plugins { `java-library` } dependencies { api("com.google.guava:guava:33.0.0-jre") implementation("org.slf4j:slf4j-api:2.0.13") testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") } ``` ```groovy // build.gradle (Groovy DSL) plugins { id 'java-library' } dependencies { api 'com.google.guava:guava:33.0.0-jre' implementation 'org.slf4j:slf4j-api:2.0.13' testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' } ``` Kotlin DSL requires parentheses and double quotes and gives you type-safe accessors + IDE completion for configuration names. Groovy DSL allows the terser space-separated, single-quoted form. ## Plugins create configurations The block is empty of meaningful methods until a plugin contributes configurations: - `java` → `implementation`, `compileOnly`, `runtimeOnly`, `annotationProcessor`, `testImplementation`, `testCompileOnly`, `testRuntimeOnly`, … - `java-library` → all of the above **plus** `api`, `compileOnlyApi`. So the available configuration names are a function of your plugin set. Choosing the right configuration name is choosing which classpath(s) the dependency affects — that's the substance of declaring dependencies.
- Why might calling `api(...)` in the dependencies block fail?Because `api` is only created by the `java-library` plugin. Without it applied, `api` is an unknown method and the build fails.
- What does the configuration name in each line actually control?Which classpath(s) the dependency lands on — compile, runtime, test, etc. — and, for `api` vs `implementation`, whether it's exposed transitively to consumers.
saying these in an interview costs you the question
- Thinking the configuration name is arbitrary — it must be a real configuration created by an applied plugin.
- Assuming all configuration names exist by default (e.g. `api` without `java-library`).
- Mixing up Kotlin DSL (parentheses required) and Groovy DSL syntax.