August 26, 2010

Groovy Goodness: Store Closures in Script Binding

We have several ways to run (external) Groovy scripts from our code. For example we can use GroovyShell and the evaluate() method. If we want to pass variables to the script to be run we must create a Binding object and assign values to the variables and in our script we can use the variables. But if we assign closures to the variables we have methods available in our scripts. We can use it for example to define a DSL externally from the script that uses the DSL.

First we create a script with a simple DSL for sending text to the console or to a file:

// File: Output.groovy
console 'Groovy is great'

file('result.txt') { out ->
    out << 'Yes it is!'

Now we define the Groovy script that reads the script file and executes it:

// File: RunOutput.groovy
// Define DSL methods as closure variables in the binding.
def binding = new Binding()
binding.console = { String message ->
    println message
binding.file = { String fileName, Closure outputCode ->
    def outputFile = new File(fileName)
    outputFile.withWriter { writer ->
        outputCode.call writer

// Create shell with the new binding.
def shell = new GroovyShell(binding)
def script = new File('Output.groovy')

// And execute
shell.evaluate script

We get the following output when we run the script:

$ groovy RunOutput
Groovy is great

And in the current directory we have a new file result.txt with the following contents: Yes it is!.