Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different types of Groovy execution in Java

I have 3 questions regarding using Groovy in java. They are all related together so I'm only creating one question here.

1) There are: GroovyClassLoader, GroovyShell, GroovyScriptEngine. But what is the difference between using them?

For example for this code:

static void runWithGroovyShell() throws Exception {
    new GroovyShell().parse(new File("test.groovy")).invokeMethod("hello_world", null);
}

static void runWithGroovyClassLoader() throws Exception {
    Class scriptClass = new GroovyClassLoader().parseClass(new File("test.groovy"));
    Object scriptInstance = scriptClass.newInstance();
    scriptClass.getDeclaredMethod("hello_world", new Class[]{}).invoke(scriptInstance, new Object[]{});
}

static void runWithGroovyScriptEngine() throws Exception {
    Class scriptClass = new GroovyScriptEngine(".").loadScriptByName("test.groovy");
    Object scriptInstance = scriptClass.newInstance();
    scriptClass.getDeclaredMethod("hello_world", new Class[]{}).invoke(scriptInstance, new Object[]{});
}

2) What is the best way to load groovy script so it remains in memory in compiled form, and then I can call a function in that script when I need to.

3) How do I expose my java methods/classes to groovy script so that it can call them when needed?

like image 768
NewProger Avatar asked Nov 03 '22 09:11

NewProger


1 Answers

Methods 2 and 3 both return the parsed class in return. So you can use a map to keep them in memory once they are parsed and successfully loaded.

Class scriptClass = new GroovyClassLoader().parseClass(new File("test.groovy"));
map.put("test.groovy",scriptClass);

UPDATE:

GroovyObject link to the groovy object docs.

Also this is possible to cast the object directly as GroovyObject and other java classes are indistinguishable.

Object aScript = clazz.newInstance();
MyInterface myObject = (MyInterface) aScript;
myObject.interfaceMethod();
 //now here you can also cache the object if you want to

Cannot comment on efficiency. But I guess if you keep the loaded classes in memory, one time parsing would not hurt much.

UPDATE For efficiency: You should use GroovyScriptEngine, it uses script caching internally.

Here is the link: Groovy Script Engine

Otherwise you can always test it using some performance benchmarks yourself and you would get rough idea. For example: Compiling groovy scripts with all three methods in three different loops and see which performs better. Try using same and different scripts, to see if caching kicks in, in some way.

UPDATE FOR PASSING PARAMS TO AND FROM SCRIPT Binding class will help you sending the params to and from the script.

Example Link

// setup binding
def binding = new Binding()
binding.a = 1
binding.setVariable('b', 2)
binding.c = 3
println binding.variables

// setup to capture standard out
def content = new StringWriter()
binding.out = new PrintWriter(content)

// evaluate the script
def ret = new GroovyShell(binding).evaluate('''
def c = 9
println 'a='+a
println 'b='+b
println 'c='+c 
retVal = a+b+c
a=3
b=2
c=1
''')

// validate the values
assert binding.a == 3
assert binding.getVariable('b') == 2
assert binding.c == 3 // binding does NOT apply to def'd variable
assert binding.retVal == 12 // local def of c applied NOT the binding!

println 'retVal='+binding.retVal
println binding.variables
println content.toString()
like image 52
Narendra Pathai Avatar answered Nov 09 '22 08:11

Narendra Pathai