Answering my own question in case it helps others. My ultimate goal is to be able to execute DSL scripts at run-time from the filesystem, supporting reloading, import customizers and a base script class.
First, `GroovyShell` does not do caching, so it always re-parse the scripts. `GroovyClassLoader` supports reloading, but with `loadClass` methods, not `parseClass` (found it by inspecting the source code). But `loadClass` is for classes, not for scripts (it is possible to use it with scripts, but much more complicated). `GroovyScriptEngine` is more suited to doing this with scripts. To support reloading, its `CompilerConfiguration` must have `recompileGroovySource` set to true. Since it has no constructor taking a compiler configuration but exposes the `config` through getters/setters, one can get reloading by setting the compiler configuration after instance creation of `GroovyScriptEngine`. However, when a script is actually executed, the compiler configuration in effect is not inherited from our instance of `GroovyScriptEngine`, thus customization of the `scriptBaseClass` or import customizers added to the `compilationCustomizers` are not available for the script. The solution, as found while looking at `groovy.util.GroovyScriptEngineReloadingTest#testCompilerConfigurationInheritance` in groovy sources, is to first create a `GroovyClassLoader` with our `CompileConfiguration` properly setup and use that as the parent class loader when instantiating `GroovyScriptEngine`. This way, the customized compiler configuration is used when checking if a script should be reloaded and when running scripts. Here is a script showing all of this. Note the `Thread.sleep(1000)` statements : on my system, file modification time has a granularity of a second, so each change to the script file needs to be at least one second after the last one or the previous compiled version of the script will be used. ---- import org.codehaus.groovy.control.CompilerConfiguration class MyGse { static abstract class MyBaseScript extends Script { String hello() { return 'Je suis Paris' } } public static void main(String[] args) { CompilerConfiguration config = new CompilerConfiguration() config.setRecompileGroovySource(true) config.scriptBaseClass = MyBaseScript.name GroovyScriptEngine gse = new GroovyScriptEngine(".", new GroovyClassLoader(getClassLoader(), config)) Binding binding = new Binding(alpha:'abc', num:'123') File fooFile = new File("foo.groovy") fooFile.text = 'alpha' def result = gse.run(fooFile.name, binding) assert 'abc' == result Thread.sleep(1000) fooFile.text = 'num' result = gse.run(fooFile.name, binding) assert '123' == result Thread.sleep(1000) fooFile.text = 'hello()' assert 'Je suis Paris' == gse.run(fooFile.name, binding) Thread.sleep(1000) } } ---- Drop this in a file named 'MyGse.groovy', cd to its parent directory and run it with `groovy MyGse.groovy`. Hope this helps someone, Marc > Le 2015-11-14 à 10:31, Marc Paquette <mar...@mac.com> a écrit : > > Hello all, > > I am using `GroovyClassLoader` to execute groovy scripts at runtime and I > want modifications to the script text (stored on the filesystem) to be picked > up on subsequent execution of the script but I don't want the script to be > re-compiled each time. From my understanding, creating a `GroovyClassLoader` > with a `CompilerConfiguration` where `recompileGroovySource` is set to true > should give this outcome, but it does not seems to work the way I am using it. > > I expect the following script to pass, but the second assert fails, anybody > can tell me what I am doing wrong (or why my assumptions on how this is > supposed to work are false) ? > > > ---- > import org.codehaus.groovy.control.CompilerConfiguration > import org.codehaus.groovy.runtime.InvokerHelper > class MyGcl { > > public static void main(String[] args) { > CompilerConfiguration config > config = new CompilerConfiguration() > config.setRecompileGroovySource(true) > GroovyClassLoader gcl = new GroovyClassLoader(getClassLoader(), config) > Binding binding = new Binding() > > File fooFile = new File("foo.groovy") > fooFile.text = ''' > alpha='abc' > num='123' > alpha > ''' > def result = InvokerHelper.createScript(gcl.parseClass(fooFile), > binding).run() > assert 'abc' == result > > fooFile.text = fooFile.text + ''' > num > ''' > result = InvokerHelper.createScript(gcl.parseClass(fooFile), > binding).run() > assert '123' == result > } > } > ---- > > Thanks in advance, > Marc >