If you work with Boomi, Groovy is the language of the Data Process shape’s custom scripting step. Everything in this track — closures, collection methods, null safety, JSON — comes together there. This lesson shows the shape of a typical Boomi script and how to run the same logic locally.
The shape of every Boomi script
for (int i = 0; i < dataContext.getDataCount(); i++) {
InputStream is = dataContext.getStream(i)
Properties props = dataContext.getProperties(i)
// ... read, change, split ...
dataContext.storeStream(is, props)
}
dataContextholds every document that reached the shape.- Each document is a stream of bytes plus a set of properties.
- Whatever you pass to
storeStreamcontinues down the process; documents you don’t store are dropped.
The details — and the most common mistakes — are covered in Get and set DPP and DDP in Boomi Groovy.
A realistic example: split and tag
Take a JSON document with many orders, keep only the active ones, emit one document per order, and tag each with its ID as a dynamic document property:
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
for (int i = 0; i < dataContext.getDataCount(); i++) {
Properties props = dataContext.getProperties(i)
def json = new JsonSlurper().parse(dataContext.getStream(i), 'UTF-8')
json.orders.findAll { it.status == 'active' }.each { order ->
Properties p = new Properties()
p.putAll(props)
p.setProperty('document.dynamic.userdefined.DDP_ORDER_ID', order.id.toString())
String out = JsonOutput.toJson(order)
dataContext.storeStream(new ByteArrayInputStream(out.getBytes('UTF-8')), p)
}
}
Notice the Groovy you’ve learned: findAll with a closure, each, safe string conversion with toString() — a GString or number won’t do as a property value.
Run it on your machine
The downloadable file below adds a tiny stand-in for dataContext at the top, so you can run exactly the same loop with groovy boomi_script.groovy and see the output instantly:
// boomi_script.groovy — the shape of a Boomi Data Process script, runnable outside Boomi.
// In Boomi, 'dataContext' is provided for you. Here a tiny stand-in lets you run the
// same loop locally: groovy boomi_script.groovy
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
// ---- local stand-in for Boomi's dataContext (not needed inside Boomi) ----
def dataContext = [
docs : ['{"orders":[{"id":1001,"status":"active"},{"id":1002,"status":"cancelled"}]}'],
out : [],
getDataCount: { -> 1 },
]
dataContext.getStream = { int i -> new ByteArrayInputStream(dataContext.docs[i].getBytes('UTF-8')) }
dataContext.getProperties = { int i -> new Properties() }
dataContext.storeStream = { InputStream is, Properties p -> dataContext.out << [text: is.getText('UTF-8'), props: p] }
// ---------------------------------------------------------------------------
// The script itself — paste this part into a Boomi Data Process shape
for (int i = 0; i < dataContext.getDataCount(); i++) {
Properties props = dataContext.getProperties(i)
def json = new JsonSlurper().parse(dataContext.getStream(i), 'UTF-8')
json.orders.findAll { it.status == 'active' }.each { order ->
Properties p = new Properties()
p.putAll(props)
p.setProperty('document.dynamic.userdefined.DDP_ORDER_ID', order.id.toString())
String out = JsonOutput.toJson(order)
dataContext.storeStream(new ByteArrayInputStream(out.getBytes('UTF-8')), p)
}
}
// Show what Boomi would receive
dataContext.out.each { println "${it.text} DDP_ORDER_ID=${it.props.getProperty('document.dynamic.userdefined.DDP_ORDER_ID')}" }
{"id":1001,"status":"active"} DDP_ORDER_ID=1001
For a full local workflow with VS Code, sample files and stubs for ExecutionUtil, see Set up VS Code to run and test Boomi Groovy scripts locally.
Habits for production scripts
- Match the Groovy version your Boomi runtime uses (the Language setting of the scripting step).
- Always use UTF-8 when reading and writing streams.
- Convert property values to String before
setProperty. - Log decisions, not payloads —
ExecutionUtil.getBaseLogger().info(...); payloads may contain personal data. - Prefer standard shapes when they can do the job, and keep scripts short and commented.
More real-world patterns live in the blog: JSON in Groovy for Boomi and the Boomi integration consulting page.
Try it yourself
Change the script so that, instead of one document per order, it outputs one document containing {"activeIds": [...]} and sets a dynamic process property DPP_ACTIVE_COUNT. (Inside Boomi, process properties are set with ExecutionUtil.setDynamicProcessProperty(name, value, false).)
Show a solution
import com.boomi.execution.ExecutionUtil
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
for (int i = 0; i < dataContext.getDataCount(); i++) {
Properties props = dataContext.getProperties(i)
def json = new JsonSlurper().parse(dataContext.getStream(i), 'UTF-8')
def ids = json.orders.findAll { it.status == 'active' }*.id
ExecutionUtil.setDynamicProcessProperty('DPP_ACTIVE_COUNT', ids.size().toString(), false)
String out = JsonOutput.toJson([activeIds: ids])
dataContext.storeStream(new ByteArrayInputStream(out.getBytes('UTF-8')), props)
}
This runs inside Boomi (where ExecutionUtil exists); locally, use the stubs from the VS Code guide.
Key takeaways
- A Boomi script loops over
dataContext, reads each stream and stores what should continue. - Dynamic document properties travel with each document; set them before storing.
- Groovy’s collection methods and JSON tools make splitting and reshaping short.
- Test locally with stand-ins, then run once in Boomi test mode.
🎉 You’ve finished the Groovy track. Continue with the Java track — especially lambdas and streams, the Java counterparts of everything you’ve learned here.