Monday, February 15, 2016

Run Groovy from Java

Why do we want to mix Groovy with Java:
One common requirement in java is to keep core logic in groovy and then evaluate it at runtime. This gives a flexibility as groovy can be referred from xml file, property file or database. That way customer can change groovy anytime and without deployment java code can start working with new groovy expression.

One common example could be calculating salary components. We definitely want to give customer a flexibility to write his own logic to determine salary components. We don't want to hard code that logic in java code. In such cases we can store groovy expression in database table and read it at runtime and evaluate it from java. End user can change groovy expressions anytime in database.

Basic requirement from groovy to java integration would be
a. Somehow we should be able to pass java variables to groovy code. These are called environment variables.
b. Somehow we should be able to parse and run groovy from java. We have Groovy apis for that.
c. Somehow values calculated by groovy should be passed back to java.

Below code show how we can do it.

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;

import java.util.HashMap;
import java.util.Map;


public class GroovyUtil {
    public GroovyUtil() {
        super();
    }
   
    public static Map evaluateGroovy(Map paramMap,String scriptText){
       
       System.out.println("Evaluating groovy: " + scriptText);     
        System.out.println("Input Map: " + paramMap);

       //Environment variables passed to groovy using Binding.
        Binding binding = new Binding(paramMap);
        GroovyShell shell = new GroovyShell();       
        Script script = shell.parse(scriptText);
        script.setBinding(binding);
        script.run();

        //bindings.getVariables() returns all variables of groovy including input and other local variables
        System.out.println("Output Map: " + binding.getVariables());      
        return binding.getVariables();
       
    }
   
    public static void main(String[] args){
        String scriptText = "println('Sctipt execution Started');\n" +
        "    sum = a + b;\n" +
        "    println('script finished');";
       
        Map inputMap = new HashMap();
        inputMap.put("a",10);
        inputMap.put("b",20);
        Map outputMap = evaluateGroovy(inputMap,scriptText);
        System.out.println(outputMap);
    }
}












Output looks like
Evaluating groovy: println('Sctipt execution Started');
    sum = a + b;
    println('script finished');
Input Map: {b=20, a=10}
Sctipt execution Started
script finished
Output Map: {b=20, a=10, sum=30}
{b=20, a=10, sum=30}








For such kind of code there must be an understanding between groovy and java code about input and output variable names.