Hello I'm using Groovy
engine to eval a certain script. The problem is that the execution time is a little bit big, so I want to separate my script into two scripts. The first one is static and can be compiled inside @PostConstruct
method and the second is a variable and it depends on some parameters that the user chooses. This is what I want to do:
Bindings bindings;
CompiledScript scriptC;
String script1="Static Script";
String script2="Variable Script";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
scriptC = ((Compilable) engine).compile(script1);
//Execute some instruction to generate 'script2'
scriptC += ((Compilable) engine).compile(script2);//Please note the += operator
or
Bindings bindings;
CompiledScript scriptC;
String script1="Static Script";
String script2="Variable Script";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
scriptC = ((Compilable) engine).compile(script1);
//Execute some instruction to generate 'script2'
scriptC.append(((Compilable) engine).compile(script2));//Please note the append function
These two code does not work for sure, I used them just to illustrate what I'm attempting to do. Is it possible to combine two scripts into a single one?
You can't combine like that two CompiledScript
objects. If it comes to Groovy - when Groovy script gets compiled it creates a class that extends groovy.lang.Script
with a few methods inside. In this case adding two scripts to each other means merging two Java classes.
Consider evaluating both scripts in separation as an alternative. Take a look at following example:
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
public class ScriptTest {
public static void main(String[] args) throws ScriptException {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("Groovy");
final Bindings bindings = new SimpleBindings();
bindings.put("a", 3);
final String script1 = "println 'Running first script...'; def c = 2; def d = c + a; return d";
final CompiledScript compiledScript1 = ((Compilable) engine).compile(script1);
//Execute some instruction to generate 'script2'
final String script2 = "println 'Running second script...';";
final CompiledScript compiledScript2 = ((Compilable) engine).compile(script2);
Integer returnedValue = (Integer) compiledScript1.eval(bindings);
System.out.println("Returned value from the first script: " + returnedValue);
if (returnedValue > 1) {
compiledScript2.eval(bindings);
}
}
}
Creating CompiledScript
object is one thing. Second thing is evaluation of those scripts. If you always evaluate script1
and script2
right away, then you simply need:
compiledScript1.eval(bindings);
compiledScript2.eval(bindings);
However script1
may return some value and based on that value you can decide if script2
should be evaluated. Let's say script1
returns an Integer
and I will evaluate script2
only if returned value is greater than 1:
Integer returnedValue = (Integer) compiledScript1.eval(bindings);
if (returnedValue > 1) {
compiledScript2.eval(bindings);
}
Alternatively you can base on bindings values after running script1
. Let's say script1
modifies bindings a
and b
and set both to true
(assuming they hold boolean
type):
compiledScript1.eval(bindings);
if (bindings.get("a") && bindings.get("b")) {
compiledScript2.eval(bindings);
}
script1
from script2
Let's say script1
is defined as follows:
import groovy.json.JsonOutput
def json(Map map) {
return new JsonOutput().toJson(map)
}
println json([test: 1])
In case you have to call json(map)
function inside script2
- you can do it. Take a look at this example:
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
public class ScriptTest {
public static void main(String[] args) throws ScriptException {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("Groovy");
final Bindings bindings = new SimpleBindings();
bindings.put("a", 3);
final String script1 = "import groovy.json.JsonOutput\n" +
"\n" +
"def json(Map map) {\n" +
" return new JsonOutput().toJson(map)\n" +
"}\n" +
"\n" +
"println json([test: 1])";
final CompiledScript compiledScript1 = ((Compilable) engine).compile(script1);
//Execute some instruction to generate 'script2'
final String script2 = "println 'Running second script...'; println json([test: 2]);";
final CompiledScript compiledScript2 = ((Compilable) engine).compile(script2);
compiledScript1.eval(bindings);
compiledScript2.eval(bindings);
}
}
script2
is defined as:
println 'Running second script...';
println json([test: 2]);
When you run it you will see in the console:
{"test":1}
Running second script...
{"test":2}
The first two lines come from script1
while the last line is generated by script2
. Keep in mind that both CompiledScript
hold a reference to the same engine, so you can refer to functions defined in previously evaluated scripts.