skip to content

Show how to declare the same MavenPublication in both Kotlin DSL and Groovy DSL, and explain the syntactic differences.

level: middleimportance: should knowfreq 50%

answer

  1. Kotlin: create<MavenPublication>("maven")
  2. Groovy: maven(MavenPublication) { }
  3. Kotlin components["java"] vs Groovy components.java
  4. method-name = publication name in Groovy
  5. reified generic type in Kotlin

basics

~10 s

In Kotlin you call create<MavenPublication>("maven") { from(components["java"]) }; in Groovy you write maven(MavenPublication) { from components.java }. Both apply maven-publish and configure the same publishing block.

solid answer

~40 s

Both DSLs configure the same `publishing { publications { } }` extension. The difference is how you name the publication and reference the component. **Kotlin DSL** is statically typed: you create a publication with `create<MavenPublication>("maven")` (the type is a reified generic) and access the component as `components["java"]` (a `NamedDomainObjectCollection` lookup). **Groovy DSL** uses dynamic method-on-container syntax: `maven(MavenPublication) { ... }` where the method name *becomes* the publication name and the `Class` is passed as an argument; the component is reached as `components.java`. In Groovy you can omit quotes and rely on dynamic property access; in Kotlin everything is type-checked and string- or reified-typed. The published result is identical — only the DSL surface differs.

code

groovy · 8 lines
groovy
// Groovy DSL — build.gradle
publishing {
    publications {
        maven(MavenPublication) {
            from components.java
        }
    }
}

go deeper

for a junior

Recognize both forms and that they configure the same publishing block.

for a middle

Explain the container semantics: name+type in Kotlin via create/register, name-as-method in Groovy.

for a senior

Note Kotlin's register for lazy configuration and the static-typing implications when porting scripts.

for a principal

Discuss standardizing on Kotlin DSL across a large multi-module repo and the migration cost/benefit.

## Same model, two DSLs Gradle build scripts come in two flavors: Kotlin DSL (`build.gradle.kts`) and Groovy DSL (`build.gradle`). The publishing *model* is the same Java API underneath; the DSLs are just two front-ends. ## Naming a publication The `publications` container is a `PolymorphicDomainObjectContainer`. To add a typed element you must say both the **name** and the **type**: - **Kotlin**: the name is a string argument, the type is a reified generic — `create<MavenPublication>("maven") { }` (or `register<MavenPublication>("maven") { }` for laziness). - **Groovy**: Groovy's dynamic dispatch lets `maven(MavenPublication) { }` mean "create an element *named* `maven` of type `MavenPublication`." The method name is the publication name; the `Class` literal is the type. ## Referencing the java component - **Kotlin**: `components["java"]` — indexed access on the `components` `NamedDomainObjectCollection`. - **Groovy**: `components.java` — dynamic property access for the same lookup. ## Why it matters in interviews Mixing the two syntaxes is the classic mistake when porting a script. Kotlin DSL will not accept `maven(MavenPublication) { }` because that is Groovy dynamic dispatch; Groovy will accept `create(...)` but the idiomatic form is the dynamic one. ```kotlin // build.gradle.kts publishing { publications { create<MavenPublication>("maven") { from(components["java"]) } } } ``` ```groovy // build.gradle publishing { publications { maven(MavenPublication) { from components.java } } } ``` Both produce a publication named `maven` that publishes the `java` component.

  • In the Groovy form maven(MavenPublication) { }, where does the publication name come from?
    From the method name itself — `maven` — which Groovy's dynamic container dispatch turns into the element name; the `MavenPublication` class is the requested type.
  • Why does Kotlin DSL need create<MavenPublication>(...) instead of a dynamic call?
    Kotlin DSL is statically typed and has no dynamic dispatch, so you supply the name as a string and the type as a reified generic on `create`/`register`.

saying these in an interview costs you the question

  • Using Groovy's `maven(MavenPublication) { }` syntax inside a `.kts` script — it won't compile.
  • Claiming the two DSLs produce different artifacts — they configure the identical model.

context