Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

Scripting Your Java Application With Groovy

There are plenty of scripting languages for the JVM (Jython and JRuby to name some well known ones) and JavaScript is even bundled with the JDK. But what’s in it for me? Embedding a scripting engine into a Java application isn’t very common thing to do. However, it is possible to achieve neat design solutions by leveraging scripting facilities in Java applications.

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.

A case for scripting 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

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");

The 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 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.

Summary

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.

How do you use scripting to “pimp” your apps? Let us know in the comments section below, and follow us at @Rebel_Labs for frequent updates and blatherings.

  • There are several ways to instantiate a GroovyShell. One particular constructor can handle “org.codehaus.groovy.control.CompilerConfiguration” as input. This class is used to setup configuration options to the underlying Groovy compiler used by the Shell. One of those options allow you to define a base class for the generated script. This class must extend “groovy.lang.Script” however you may define additional methods. The following link (https://gist.github.com/aalmiray/5395913) shows a modified version of the examples demonstrated by Anton; this example makes use of a custom script class, no need to muck around with Java proxies anymore ;-)

  • arhan

    Nice! The gist link is a bit broken. Here’s the correct one: https://gist.github.com/aalmiray/5395913

  • Peter Schuebl

    If you change the return value “this” to “this as Engine” the returned instance would already implement the interface

    See https://gist.github.com/schup/5397811 for an example.

  • arhan

    Nice tip! It actually creates a proxy automatically then. So there’s a difference in the way the proxy could be created and what you can do with that. Basically it would be a matter of taste, but there could be a good reason why one might want to construct the proxy on Java side.

  • It is easier to interact with web with Groovy, one of the great benefits of this language is how it can simplify a few of the common scenarios we face in Java.

  • rsaez