November 20, 2013

Groovy Goodness: Set Delegating Class for Script

Since Groovy 2.2 we can assign the DelegatingScript class to a Script as a base script class. We use the CompilerConfiguration to set the base script class. After we have assigned the DelegatingScript class we can then set a delegate class for the Script. And this delegate class is then used to evaluate the script contents. This is a very easy setup for DSL scripts.

import org.codehaus.groovy.control.CompilerConfiguration
// Simple Car class to save state and distance.
class Car {
    String state
    Long distance = 0

// Custom Script with methods that change the Car's state.
// The Car object is passed via the constructor.
class CarScript {

    private final car
    CarScript(final car) {
        this.car = car

    def start() {
        car.state = 'started'

    def stop() {
        car.state = 'stopped'

    def drive(distance) {
        car.distance += distance

// Create CompilerConfiguration and assign
// the DelegatingScript class as the base script class.
def compilerConfiguration = new CompilerConfiguration()
compilerConfiguration.scriptBaseClass = DelegatingScript.class.name

// Configure the GroovyShell and pass the compiler configuration.
def shell = new GroovyShell(this.class.classLoader, new Binding(), compilerConfiguration)

// Simple DSL to start, drive and stop the car.
// The methods are defined in the CarScript class.
def carDsl = '''
drive 200

// Define Car object here, 
// so we can use it in assertions later on.
def car = new Car()

// Define CarScript instance so we can use it as delegate
// for the script.
def carScript = new CarScript(car)

// Set delegate carScript to script, so the DSL
// can be executed.
def script = shell.parse(carDsl)

// Run DSL script.

// Checks to see that Car object has changed.
assert car.distance == 200
assert car.state == 'stopped'

Code written with Groovy 2.2.