Groovy
Concise scripting for the JVM.
Groovy is a dynamic language for the Java Virtual Machine with a concise, Python-like feel and full access to Java libraries. It powers Gradle build scripts and Jenkins pipelines, so many developers use it daily for builds and CI/CD, including pipelines that train and deploy AI models.
Why learn Groovy?
If you work with Jenkins or Gradle, you already write Groovy; learning it properly makes builds and pipelines far easier.
- Less boilerplate: optional semicolons, types and parentheses.
- Java compatible: use any Java library directly.
- DevOps: the language of Jenkinsfiles and Gradle builds.
Set up and run your first program
Install Java 17+ and Groovy (SDKMAN makes this easy).
curl -s "https://get.sdkman.io" | bash
sdk install groovy
groovy hello.groovydef name = "Ada"
println "Hello, AI! Welcome to Groovy, ${name}."${} interpolation (GStrings); single quotes do not.Variables and strings
Use def for dynamic variables or declare a type. GStrings interpolate values, and triple quotes allow multi-line strings.
def layers = 32
String model = "llama3.1"
double params = 8.03e9
println "$model: $layers layers"
println "FP16 size: ${String.format('%.1f', params * 2 / 1e9)} GB"
def prompt = """
You are a helpful assistant.
Explain tensor cores.
"""
println prompt.trim()Lists, maps and closures
Lists [] and maps [:] have literal syntax. Closures { } work with methods like each, collect, findAll and inject.
def gpus = ["H100", "H200", "B200"]
def vram = [H100: 80, H200: 141, "RTX 5090": 32]
gpus.each { println it }
println vram.findAll { k, v -> v >= 80 }.keySet()
println vram.values().sum()
println((1..5).collect { it * it })
println([1, 2, 3, 4].inject(0) { acc, x -> acc + x })Control flow
Groovy's switch matches values, ranges, lists and regexes. The safe-navigation ?. and Elvis ?: operators handle nulls neatly.
def precision(bits) {
switch (bits) {
case 32: return "FP32"
case 16: return "FP16"
case 1..8: return "low precision"
default: return "other"
}
}
println precision(8)
String user = null
println user?.toUpperCase() ?: "anonymous"
for (i in 1..3) println "epoch $i"Classes and traits
Classes get getters, setters and constructors automatically. Annotations like @ToString remove more boilerplate; traits share behaviour.
import groovy.transform.ToString
trait Describable {
String describe() { "${this.class.simpleName}: $name" }
}
@ToString
class Gpu implements Describable {
String name
int vram
boolean fits(int gb) { gb <= vram }
}
def g = new Gpu(name: "RTX 5090", vram: 32)
println g
println g.describe()
println g.fits(16)JSON, files and HTTP
Groovy includes JsonSlurper and JsonOutput, and adds handy methods to files and URLs.
import groovy.json.*
def data = new JsonSlurper().parseText('{"model":"llama3.1","sizes":[8,70,405]}')
println data.sizes.max()
new File("out.json").text = JsonOutput.prettyPrint(JsonOutput.toJson([ok: true]))
new File("notes.txt").eachLine { line -> if (line.contains("GPU")) println line }
def repo = new JsonSlurper().parse(new URL("https://api.github.com/repos/pytorch/pytorch"))
println "Stars: ${repo.stargazers_count}"AI with Groovy
Groovy's AI role is mostly in automation: Jenkins pipelines that train, evaluate and deploy models, Gradle builds for Java AI apps, and scripts that call LLM APIs. Because it runs on the JVM, it can also use Java AI libraries such as LangChain4j and Deep Java Library (DJL).
The essential libraries
A Jenkins pipeline for a model
A declarative Jenkinsfile that trains, evaluates and deploys a model on a GPU agent.
pipeline {
agent { label 'gpu' }
environment { RUN = "run-${env.BUILD_NUMBER}" }
stages {
stage('Setup') { steps { sh 'pip install -r requirements.txt' } }
stage('Train') { steps { sh 'python train.py --out runs/$RUN' } }
stage('Evaluate') {
steps {
script {
def acc = sh(script: "python eval.py runs/$RUN", returnStdout: true).trim() as double
if (acc < 0.90) error "Accuracy too low: $acc"
}
}
}
stage('Deploy') { when { branch 'main' } steps { sh './deploy.sh runs/$RUN' } }
}
post { always { archiveArtifacts artifacts: "runs/$RUN/**", allowEmptyArchive: true } }
}Build an AI agent in Groovy
Java's HttpClient plus Groovy's JSON tools make a compact tool-calling loop. Tools are closures in a map.
import groovy.json.*
import java.net.http.*
def client = HttpClient.newHttpClient()
def url = URI.create("http://localhost:11434/v1/chat/completions")
def tools = [[type: "function", function: [name: "get_weather", description: "Weather for a city",
parameters: [type: "object", properties: [city: [type: "string"]], required: ["city"]]]]]
def impls = [get_weather: { args -> "It is 24°C and sunny in ${args.city}." }]
def messages = [[role: "user", content: "Should I take an umbrella in Lahore today?"]]
for (round in 1..5) {
def req = HttpRequest.newBuilder(url).header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(JsonOutput.toJson([model: "llama3.1", messages: messages, tools: tools])))
.build()
def body = client.send(req, HttpResponse.BodyHandlers.ofString()).body()
def msg = new JsonSlurper().parseText(body).choices[0].message
messages << msg
if (!msg.tool_calls) { println msg.content; break }
msg.tool_calls.each { call ->
def args = new JsonSlurper().parseText(call.function.arguments)
messages << [role: "tool", tool_call_id: call.id, content: impls[call.function.name](args).toString()]
}
}Adding a tool means adding a schema to tools and a closure to impls.
ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.Groovy learning roadmap
Tick items off as you go. Your progress is saved in this browser.
Beginner
Intermediate
Advanced
Projects to build
Groovy cheat sheet
| Task | Syntax |
|---|---|
| Variable | def x = 5 |
| GString | "Hi ${name}" |
| List | [1, 2, 3] |
| Map | [a: 1, b: 2] |
| Closure | list.collect { it * 2 } |
| Safe nav | obj?.prop ?: "default" |
Common mistakes
- Single-quoted strings do not interpolate
${}. ==callsequals()in Groovy; use.is()for identity.- Dynamic typing hides typos until runtime; add
@CompileStaticfor critical code.
Where to go next
- Groovy docs — official
- Jenkins Pipeline — CI/CD guide
- Gradle docs — builds
On TensorCore.si: Java volume, Kotlin volume.
Keyboard: [ previous language · ] next language · / search the library