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

I use GroovyShell as an "evaluator / expression engine" inside my program. It accepts two inputs: (a) one or more initialization scripts (b) a user script. Both of them are then concatenated at runtime as a large piece of script (text) and passed 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 change.

So far, initScripts only contains variable definitions (for example, def $yyyy = new Date().format('yyyy') ) that can be referenced in userScript (for example, print "$yyyy 001" ).

Is there a more efficient approach for this? (For example, shell reuse, how?) Because now it is very slow.

Edit: Groovy is a must. Using a different scripting engine is not recommended.

Edit: I think GroovyShell can do this (pseudocode):

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

Is it possible? (The last time I googled it was not possible, but I hope I am wrong)

+7
source share
3 answers

You can cache GroovyShell, you do not need to create a new one:

 final static GroovyShell shell = new GroovyShell() 

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

This documentation section may also help; instead of scripts, you can also dynamically create groovy objects.

+7
source

I think you could avoid the weight of creating a complete groovy environment every time.

Starting with Java 6, Java supports scripting API support, which allows the use of lightweight scripts.

For an example, see this page on the groovy website , which explains how to run the groovy script in a Java application using GroovyScriptEngineImpl .

note that you may lose some groovy goods, for example, perhaps groovy grape, but you can

  • reuse script engine
  • make sure your script evals are in the application context (will ultimately benefit from using Java objects)

EDIT it is important to note that neither GroovyScriptEngineImpl nor GroovyShell can guarantee you any thread safety, since any groovy script can spawn any number of threads. In fact, the only way to guarantee thread safety is to install a SecurityManager that prohibits thread operations. In fact, even this would not guarantee thread safety (since this thread safety can only be achieved by securing your entire Java code base).

+1
source

I end up doing this:

 def shell = new GroovyShell() shell.evaluate(initScripts) for( i in 1..count ) { output = shell.evaluate(userScripts); } 

And to be safe, you can put a shell in ThreadLocal or a pool.

0
source

All Articles