Image Blog Scripting Java Application with Groovy
April 16, 2013

Scripting With Groovy in Java Applications

Java Application Development
Developer Productivity

In this post I'd like to present you with the case for using an alternative JVM scripting language - Groovy - for extending your Java application. We'll start out with a few cases where scripting in Java apps with Groovy may be the right move, then give an example of how to embed a script with Groovy in Java.

A Case for Scripting With Groovy in Java Applications

So why would I want to move some pieces of logic into (Groovy) scripts instead of implementing the same in Java classes? One obvious reason for this is the customization of application business logic. Again, why? Because sometimes there's a need to deliver code faster than it is possible for the whole application.

An externalized script can be seen as a minimalistic business rule definition as opposed to full-blown BRMS implementations. This kind of approach could be viewed as a poor-man's plugin system, where it would be possible to implement plugins in a scripted manner.

Another case for scripting is when there's a need to interactively control the application. For this purpose, scripting has become widely adopted in Java middleware: Jython scripts in IBM WebSphere AS and Oracle WebLogic are the well-known examples.

Embedding Groovy in Java

Groovy is a great language for embedding into Java applications. The Groovy API provides us with GroovyShell class which is used as an entry point for Groovy scripts execution.


GroovyShell shell = new GroovyShell();
shell.evaluate("println 'Hello from Groovy script!'");


By executing the lines above obviously the program prints "Hello from Groovy script!" line.

What if we need it to be implemented as a deferred callback? In that, we don’t want to execute the Groovy code as it is evaluated, rather execute the pieces of the script based on decisions we make in the application later on. In that case we could move the code into a dedicated method and evaluate the script. The result of the script evaluation:


GroovyShell shell = new GroovyShell();
Object script = shell.evaluate("def sayHello() { " + 
    "println 'Hello from Groovy script!' }");


The problem now is that the script variable is null. We didn't return anything from the script! Obviously, an attempt to call the foo method via reflection would result in NullPointerException in this case.

Actually we should explicitly return the result of the script at the very last line:


Object script = shell.evaluate("def sayHello() { " + 
    "println 'hello from Groovy script!' }; this");


This variable represents an instance of class Script1 for the current example. Script1 is an automatically generated name for the piece of code that we have evaluated with GroovyShell. For every new evaluation GroovyShell with generate a new class name by incrementing the suffix - Script2, Script3, etc.

So now we could actually call the sayHello() method via reflection:


Object script = shell.evaluate("def sayHello() { " + 
    "println 'Hello from Groovy script!' }; this");
Method m = script.getClass().getMethod("sayHello");
m.invoke(script);


Next, we could make use of interfaces for the better design. The script evaluation result could then be hidden behind a dynamic proxy. Let's assume that we have an Engine interfaces and it is considered to be a pluggable component in our application:


public interface Engine {
   void start();
   void stop();
}


And the following is a Groovy script that implements the Engine interface by convention:


//engine.groovy
def start(){
   println "Start the engines!"
}
def stop(){
   println "Stop at once!"
}
this


At the very last line of the script, again, we can see this reference declared as a result for the script evaluation. So we will be able to call the methods implemented in the script via this reference. Then the following snippet maps the script to the Engine interface:


final Object e = shell.evaluate(new File("engine.groovy"));
Engine engine = (Engine) Proxy.newProxyInstance(app.getClass().getClassLoader(),
         new Class[]{Engine.class},
         new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) 
             throws Throwable {
             Method m = e.getClass().getMethod(method.getName());
             return m.invoke(e, args);
           }});

engine.start();  // Start the engines!
engine.stop();  // Stop at once!


This is a very simplified example as we assume that the methods do not take any parameters and the only thing we need to do is find it by name, and in real life we would definitely have to handle method invocation errors as well. But I guess you get the idea - the dynamic proxy serves as a gate into the script so that the rest of our application wouldn't have to deal with reflection and script evaluation.

Re-Evaluating the Groovy Script

As we can see, the script is evaluated dynamically and we definitely could evaluate it again when needed. This leads us to the idea of updating the certain pieces of our logic on-the-fly, without taking the application down.

Here's an example that demonstrates the script re-evaluation:


  new Thread(new Runnable() {
    @Override
    public void run() {
      try {
        execute();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    private void execute() throws Exception {
      final File file = new File("engine.groovy");
      long timestamp = file.lastModified();
      GroovyShell shell = new GroovyShell();
      Object app = shell.evaluate(file);
      Engine e = getEngine(app);
      while (true) {
        if (timestamp < file.lastModified()) {
          timestamp = file.lastModified();
          app = shell.evaluate(file);
          e = getEngine(app);
        }

        e.start();
        e.stop();

        Thread.sleep(5000);
      }
    }

    private Engine getEngine(final Object app) {
      return (Engine) Proxy.newProxyInstance(app.getClass().getClassLoader(),
        new Class[]{Engine.class},
        new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
            Method m = app.getClass().getMethod(method.getName());
            return m.invoke(app, args);
          }
        });
      }
    }).start();


The script is evaluated in the the loop we just call start() and stop() methods via the Engine interface. Whenever the script file is modified, we can detect that by timestamp and re-evaluate the script again via GroovyShell.

Final Thoughts

Scripting equips us with enormous flexibility in regards to implementing the business logic of the application and customizations that we can implement if required.

Combined with powerful DSL abilities of Groovy we could create very nice, readable, technically externalized business rules for our Java application. This approach results in a win-win situation from both the technical and business POV: it is technically simple and you can achieve the business goal by being able to update application logic quickly without bringing the application down even in live environments.

Additional Resources

Speaking of updating applications quickly, did you know that JRebel can help developers to skip the rebuild and redeploy steps entirely?

See for yourself with a free, 10-day JRebel trial.

Try JRebel for Free