Embedding Groovy

Groovy is an ‘agile dynamic language for the Java Platform.’ Groovy has many of the features available in Ruby such as closures and xml builders but draws much of its strength from Java’s extensive libraries.

Groovy can be embedded in your application to allow advance users or sales engineer compile and run Groovy scripts against a running system. Earlier I wrote about compiling Java code at runtime, but Groovy is a more natural solution for dynamically compiling and loading new classes. In this article I will demonstrate how to embed, compile, and load Groovy classes.

To get started you will need to use the groovy-all jar that is located under the embeddable directory of the groovy distribution. Add the groovy-all jar to your project.

You will need to create and set a CompilerConfiguration object accordingly, to indicate where to write out the class files and what additional classpath to use.

// Some variables…
String scriptLocation = “c:/src/com/juixe/MyClass.groovy”;
File scriptPath = new File(“c:/path/to/output/bin”);

// Configure
CompilerConfiguration conf = new CompilerConfiguration();
conf.setClasspath(new File[]{additonalPath});

Once you have initialized your CompilerConfiguration object you can proceed by setting a Groovy compilation unit that will do the actual compilation of Groovy script files. Here is an example of that…

// Compile…
GroovyClassLoader gcl = new GroovyClassLoader();
CompilationUnit cu = new CompilationUnit(gcl);
cu.addSource(new File(scriptLocation));
// Add more source files to the compilation unit if needed

Using the above code, the class files will be compiled to the output directory specified in the setTargetDirectory of the compiler configuration object.

Once a Groovy class has been compiled to the file system, you can load that class to be used in your system. Still using the variables from the above sample code, here is a code snippet that loads a Groovy class from the output directory.

// Load…
ClassLoader cl = Thread.currentThread().getContextClassLoader();
URL[] urls = new URL[]{scriptPath.toURL()};
URLClassLoader ucl = new URLClassLoader(urls, cl);
gcl = new GroovyClassLoader(ucl, conf);
Class clazz = gcl.loadClass(“com.juixe.MyClass”);

Once you have loaded the class file you can create a new instance. If your Groovy script extends or implements a type you can cast the new object to that type. If the Groovy class did not extend or implement any type explicitly in the script, you can cast the new object to GroovyObject as in the following example.

GroovyObject go = (GroovyObject)clazz.newInstance();

Any Groovy class extends GroovyObject implicitly. GroovyObject has a few convenience methods that can help invoke methods defined in the Groovy class via reflection.

go.invokeMethod(“myMethod”, new Object[]{param1, param2});

Technorati Tags: , , , , , , , ,

Leave a Reply