Java Programming: Getting your code spicy with Groovy 
Groovy isn't a new language, it has been around since 2003. Hence, some of the readers might already know it, although others probably never heard of it. And of course, there will be the ones - like me - who know the language but never explored it.
Well, a few weeks ago I had some time to read part of
Groovy's Documentation and started creating
some test code and exploring Groovy's potential.
For the ones who don't know, Groovy is a dynamic language influenced by languages such as Ruby - which currently has a huge hype around it -, perl and Java.
A huge attractive that Groovy has for Java developers is that it
can be compiled into byte code which runs directly on the JVM. But, there are various other ways to run Groovy:
- Running Groovy code as a script using a standalone interpreter
- Running Groovy within Java Code through a Groovy Java Shell
- Integrating Groovy into Java code using a Script engine
The possibilities of integration with Java with very low effort made me put Groovy in my "
should check" list.
For anyone with Java background - or probably any OO language - starting with Groovy isn't that hard, a few syntax modifications but that's it. Of course that there are some advanced issues that may take their time but, for what I've seen, I don't think they are so many. Also, since Groovy supports
closures the code style can change a bit, becoming possible to use functional style (some might like, some might dislike).
Since I'm talking about a new language, I'll follow tradition and present the Hello World source code:
public class Hello {
def hello(
String name) {
println
"Hello " + name;
}
}
Hello hello =
new Hello();
hello.hello(
"world");
Or in another way:
println "Hello world";
I think both ways are self explanatory and there's no need to comment any of the previous code.
Revisiting an exampleWhile exploring what could be done with Groovy I remembered what I've written a few months ago regarding Java Hot Deploy,
Java Programming: Hot Deploy.
The example presented in the Hot Deploy post was a simple command line application, where the commands - implemented via Command Pattern - could be added, removed or modified in runtime.
To achieve that solution, I had to write a custom class loader that would allow the JVM to load the modified classes into memory and, a file system watcher to know when a certain class was changed.
Even though the example presented in the post was a simple proof of concept, there was lots of code involved. More code means more work, the possibility of more bugs and a bigger effort to maintain.
Groovy can help in this problem by reducing the amount of code.
Since Groovy code can be dynamic, it's interesting to integrate new Groovy code with existing Java code through a script engine. In order to implement this solution it's important to understand what should be implemented has Java code and what should be implemented has Groovy.
Such problem is quite simple to solve since, what is intended to be dynamic are the commands, hence, the commands should be implemented as Groovy code.
The figure below represents the modifications in the application's design (top design explained in detail in the Hot deploy post), as it can be seen, the design becomes simpler.

Regarding the
GroovyScriptEngine there are a few things that deserve to be mentioned:
- The constructor receives an array of Strings that specifying the directory or directories where groovy scripts can be found (which I called groovy script repository).
- To execute a given script which is in the script repository the run(String name, Binding binding) method should be ran.
- The Binding object is the bridge between Java and Groovy that allows to pass variables into Groovy or retrieve values from Groovy scripts.
Show CoreEngine Source
package net.pabrantes.groovyTests;
import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;
import groovy.util.ResourceException;
import groovy.util.ScriptException;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class CoreEngine {
private GroovyScriptEngine scriptEngine;
public CoreEngine(
String[] roots)
throws IOException {
scriptEngine =
new GroovyScriptEngine(roots);
}
public void start()
throws ResourceException, IOException {
BufferedReader in =
new BufferedReader(
new InputStreamReader(
System.in));
String input =
"";
Boolean leave =
Boolean.FALSE;
Binding binding =
new Binding();
binding.setVariable(
"leave", leave);
while (!
Boolean.TRUE.equals(leave)) {
System.out.print(
"$ ");
input = in.readLine();
if (input !=
null) {
String[] commands = input.split(
" ");
String[] arguments = getArguments(commands);
binding.setVariable(
"args", arguments);
try {
long time1 =
System.currentTimeMillis();
scriptEngine.run(commands[0] +
".groovy", binding);
long time2 =
System.currentTimeMillis();
int time =
new Long(time2 - time1).intValue();
System.out.println(commands[0] +
" took " + time +
" ms");
}
catch (ScriptException e) {
if (e.getCause().getClass().equals(
FileNotFoundException.class)) {
System.out.println(commands[0] +
" command not found!");
}
else {
System.err.println(e.getMessage());
}
}
}
leave = (
Boolean) binding.getVariable(
"leave");
}
}
public static void main(
String[] args)
throws IOException,
ResourceException {
String[] roots =
new String[] {
"groovyCommands" };
CoreEngine commandLine =
new CoreEngine(roots);
commandLine.start();
}
private String[] getArguments(
String[] commands) {
String[] arguments = commands.length > 1 ?
new String[commands.length - 1]
:
new String[] {};
for (
int i = 0; i < commands.length - 1; i++) {
arguments[i] = commands[i + 1];
}
return arguments;
}
}
Show ListDir Groovy script
// This is a closure
//
"it" refers to the argument passed to the closure.
def getDir = { it.length == 0 ?
"/" : it[0] };
File dir =
new File(getDir(args));
File[] files = dir.listFiles();
files.length.times {
println files[it];
}
The amount of code reduced in the engine itself and in the commands. Although,
not everything is good, using Groovy scripts will have a negative impact in the applications' performance. To understand such impact, a simple benchmark was done using both implementations.
The benchmark consisted in running five times a given command and on the 4th time create a change on the command being run in order to create a reload action (which obviously will affect execution time). The benchmark was ran three times and the table below presents the time averages.
Time table For Java + Groovy Versus Java Only (average in 3 test runs)
Java + Groovy | ls / (in ms) | echo string (in ms) | Java Only | ls / (in ms) | echo string (in ms) |
|---|
| 1st time | 2665 | 426 | 1st time | 26 | 13 |
| 2nd time | 190 | 59 | 2nd time | 3 | 0 |
| 3rd time | 100 | 44 | 3rd time | 74 | 0 |
| 4th time (*) | 1042 | 641 | 4th time (*) | 8 | 2 |
| 5th time | 103 | 10 | 5th time | 2 | 1 |
(*) -
commands were modified, causing command reload.Anyone interested can also
download the full source code which includes Java and Groovy source code.
The code for the the Java only implementation can be found in the Hot Deploy post.
ConclusionsAs can be seen in the table above, the delay introduced by Groovy is quite big. In this particular case, user's output, the delay isn't very relevant since, most of the times, it's still under a second. But, in other cases this delay won't be acceptable.
As any other solution it contains trade-offs that should be well thought through. The example allowed to understand that the integration of Java with Groovy is quite simple and has great potential but it also has its share of problems.
Also, should be kept in mind that Groovy is not all about integration with Java, the language by itself contains really great features such as the
native support for markup languages and a
set of features that allow to create Domain Specific Languages very easily..
In my opinion, Groovy really has lots of potential which I'm definitely interested in exploring.