Using GroovyShell as "expression evaluator/engine" (or: How to reuse GroovyShell)

wiradikusuma picture wiradikusuma · Mar 16, 2011 · Viewed 9.7k times · Source

I'm using GroovyShell as an "expression evaluator/engine" inside my program. It accepts two inputs: (a) one or more init scripts (b) user-defined script. Both are then concatenated at runtime as big chunk of script (text) and feed to the shell.

String initScripts = getFromDB()
String userScript = getFromUser()

def shell = new GroovyShell()
output = shell.evaluate(initScripts + userScript)

The above code will run in a loop, where the contents of userScript will vary.

So far, initScripts only contain variable definitions (e.g. def $yyyy = new Date().format('yyyy')) which might be referenced in userScript (e.g. print "$yyyy 001").

Is there any more efficient approach for this? (E.g. reusing the shell, how?) Because right now it's very slow.

Edit: Groovy is a must. Please don't recommend other scripting engine.

Edit: I'm thinking whether GroovyShell can do this (pseudo-code):

def shell = new GroovyShell()
shell.evaluate(initScripts)

for each userScript in DB {
    shell.put(userScript )
    def result = shell.evaluateThat()
    println "Result is $result"
}

Is this possible? (Last time I googled it's not possible, but I'm hoping I'm wrong)

Answer

Adam picture Adam · Mar 16, 2011

You can cache the GroovyShell, you don't need to create a new one always:

final static GroovyShell shell = new GroovyShell()

Also if you run one Script many times you may cache them too. You can create a Script with GroovyShell.parse(String scriptText), use Script.run() to run the script.

This section of the documentation might help too, instead of scripts you can also create groovy objects dynamically.