Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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)

like image 410
wiradikusuma Avatar asked Mar 16 '11 09:03

wiradikusuma


2 Answers

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.

like image 179
Adam Avatar answered Oct 21 '22 11:10

Adam


I guess you could avoid the weight of building a full groovy environment each time.

Since Java 6, there is a scripting API support in Java, which allows you to use lightweight scripting engines.

As an example, see this page in groovy website explaining how to start a groovy script in a Java application using GroovyScriptEngineImpl.

notice you may loose some groovy goodnesses, like maybe Groovy grape, but you'll be able to

  • reuse your script engine
  • ensure your script evals in application context (eventually benefitting from Java objects usage)

EDIT one important thing to notice is that neither GroovyScriptEngineImpl nor GroovyShell can guarantee you any kind of thread safety, as any groovy script is free to spawn any number of thread. In fact, the only way you could guarantte thread safety would be by installing a SecurityManager forbidding thread operations. In fact, even that wouldn't guarantee thread safety (as this thread safety could only be achieved by ensuring all your Java code base is thread safe).

like image 23
Riduidel Avatar answered Oct 21 '22 11:10

Riduidel