Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute Groovy Script in Java with specific "Root" object

Tags:

java

groovy

dsl

I am writing a small Groovy DSL for letting end-users define configuration files. The idea is that I load those files in a Java environment, set some values and execute them. Here a small example from the DSL so far (the Gradle-ish style is on purpose):

model {
   file "some/path/here"
   conformsTo "some/other/path/here" 
}

model {
   ...
}

If I save above code to a file (example.groovy), I can integrate it with Java through the GroovyShell:

Binding binding = new Binding();
GroovyShell shell = new GroovyShell(binding);

Object value = shell.evaluate(...);

The tricky part is setting the "root" object. I know I can use Bindings to set in and out variables. However, I want that the "model" blocks in the DSL are mapped to a method call, i.e. I want to specify a "this" equivalent for the whole script. Anything I write in the DSL should be in scope of this "root" object, e.g.

// model is a method of the root object
model {
   file "some/path/here"
   conformsTo someValue  // if someValue is not defined inside the script, I want it to be considered as a property of the root object
}

I found this excellent article about what I want to achieve, but since it is from 2008, I thought there may be better options in newer Groovy versions. I just don't know what to look for. Can anyone point me in the right direction?

like image 662
WeSt Avatar asked Dec 31 '25 04:12

WeSt


2 Answers

If this is plain Groovy (not Gradle), then groovy.util.DelegatingScript is what you are looking for. Check its Javadoc for details.

DelegatingScript is a convenient basis for loading a custom-defined DSL as a Script, then execute it. The following sample code illustrates how to do it:

 class MyDSL {
     public void foo(int x, int y, Closure z) { ... }
     public void setBar(String a) { ... }
 }

 CompilerConfiguration cc = new CompilerConfiguration();
 cc.setScriptBaseClass(DelegatingScript.class);
 GroovyShell sh = new GroovyShell(cl,new Binding(),cc);
 DelegatingScript script = (DelegatingScript)sh.parse(new File("my.dsl"))
 script.setDelegate(new MyDSL());
 script.run();

my.dsl can look like this:

 foo(1,2) {
     ....
 }
 bar = ...;
like image 75
Peter Niederwieser Avatar answered Jan 01 '26 16:01

Peter Niederwieser


There is simple solution in Groovy to keep the configuration in properties, it's a ConfigSlurper. Have a look into ConfigSlurper

sample {
  foo = "default_foo"
  bar = "default_bar"
}

environments {
  development {
    sample {
      foo = "dev_foo"
    }
  }
  test {
    sample {
      bar = "test_bar"
    }
  }
}

def config = new ConfigSlurper("development").parse(new File('Sample.groovy').toURL())

assert config.sample.foo == "dev_foo"
assert config.sample.bar == "default_bar"

config = new ConfigSlurper("test").parse(new File('Sample.groovy').toURL())

assert config.sample.foo == "default_foo"
assert config.sample.bar == "test_bar"

Hope this is what you are looking for.


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!