Subsystem · groovy

Groovy & Spock

Drop .groovy files into your sources — Curie auto-detects them, resolves Apache Groovy from Maven Central, and compiles everything together. Add [spock] for Spock 2.x BDD specs backed by JUnit Platform.

Configuration

Add a [groovy] table to pin the Groovy version. If the table is absent, Curie uses the bundled default (currently 5.0.6):

Curie.toml
[groovy]
version = "5.0.6"   # optional; defaults to DEFAULT_GROOVY_VERSION

[spock]
version = "2.4-groovy-5.0"   # optional; defaults to DEFAULT_SPOCK_VERSION

The version strings are inherited from a workspace root and can be overridden per member, exactly like [kotlin] version.

Source layouts

Curie discovers Groovy sources from three layouts:

Test sources follow the same convention under src/test/groovy/ or in flat-package test directories. Files ending in *Spec.groovy, *Test.groovy, or *Tests.groovy are treated as test sources.

Compilation

Curie resolves org.apache.groovy:groovy from Maven Central and invokes org.codehaus.groovy.tools.FileSystemCompiler via java -cp:

Because the Java phase uses Curie's javac wrapper, annotation processors declared under [annotation-processors] work normally in Groovy + Java modules — generated sources appear under target/generated-sources/annotations/ and stale Java .class files are pruned automatically on the next build.

$ curie build
Building groovy-greeter v0.1.0
  Resolve Groovy  1 JAR(s)
  Compile         1 source file(s)  [no class files]
  Tests           no test sources found
  Package         groovy-greeter-0.1.0.jar
  Done            target/groovy-greeter-0.1.0.jar

Spock test framework

Add [spock] to activate Spock 2.x. Curie resolves spock-core and spock-spring (for Spring Boot tests), wires them onto the test compilation and runtime classpaths, and auto-selects a compatible JUnit Platform standalone launcher (Spock 2.x targets Platform 1.x).

src/test/groovy/com/example/CalculatorSpec.groovy
package com.example

import spock.lang.Specification
import spock.lang.Unroll

class CalculatorSpec extends Specification {

    def calc = new Calculator()

    @Unroll
    def "multiply #a * #b == #result"() {
        expect:
        calc.multiply(a, b) == result

        where:
        a | b | result
        2 | 3 |  6
        0 | 5 |  0
        4 | 4 | 16
    }
}
$ curie build
  Resolve Groovy  1 JAR(s)
  Compile         1 source file(s)
  Resolve Spock   9 JAR(s)
  Compile tests   1 source file(s)
  Tests           ✔ 3 tests successful
  Package         calculator-0.1.0.jar
  Done            target/calculator-0.1.0.jar

Spring Boot integration

For Spring Boot projects, Spock specs annotated with @SpringBootTest work out of the box because spock-spring is automatically included when [spock] is configured. @ServiceConnection (Spring Boot 3.1+) auto-wires Testcontainers datasources:

src/test/groovy/com/example/TaskSpec.groovy
@SpringBootTest(webEnvironment = WebEnvironment.NONE)
@Testcontainers
class TaskSpec extends Specification {

    @Container @ServiceConnection
    static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:16-alpine")

    @Autowired TaskRepository repository

    def "saves and retrieves a task"() {
        when:  def saved = repository.save(new Task(null, "hello", [:]))
        then:  saved.id() != null
    }
}

Groovy runtime classpath

Unlike Kotlin (where the stdlib is optional for simple programs), Groovy classes always reference groovy.lang.GroovyObject at runtime. Curie merges the Groovy runtime JAR into the application's target/libs/ directory and the JAR manifest's Class-Path entry automatically, so curie run and the Docker image just work.