# Integrating Groovy in a Java application

version 6.0.0-alpha-1

## 1. Groovy integration mechanisms

The Groovy language proposes several ways to integrate itself into applications (Java or even Groovy) at runtime, from the most basic, simple code execution to the most complete, integrating caching and compiler customization.

| All the examples written in this section are using Groovy, but the same integration mechanisms can be used from Java.

### 1.1. Eval

The `groovy.util.Eval` class is the simplest way to execute Groovy dynamically at runtime. This can be done by calling the `me` method:

    import groovy.util.Eval

    assert Eval.me('33*3') == 99
    assert Eval.me('"foo".toUpperCase()') == 'FOO'

`Eval` supports multiple variants that accept parameters for simple evaluation:

    assert Eval.x(4, '2*x') == 8                (1)
    assert Eval.me('k', 4, '2*k') == 8          (2)
    assert Eval.xy(4, 5, 'x*y') == 20           (3)
    assert Eval.xyz(4, 5, 6, 'x*y+z') == 26     (4)

1 | Simple evaluation with one bound parameter named `x`
2 | Same evaluation, with a custom bound parameter named `k`
3 | Simple evaluation with two bound parameters named `x` and `y`
4 | Simple evaluation with three bound parameters named `x`, `y` and `z`

The `Eval` class makes it very easy to evaluate simple scripts, but doesn’t scale: there is no caching of the script, and it isn’t meant to evaluate more than one-liners.

### 1.2. GroovyShell

#### 1.2.1. Multiple sources

The `groovy.lang.GroovyShell` class is the preferred way to evaluate scripts with the ability to cache the resulting script instance. Although the `Eval` class returns the result of the execution of the compiled script, the `GroovyShell` class offers more options.

    def shell = new GroovyShell()                           (1)
    def result = shell.evaluate '3*5'                       (2)
    def result2 = shell.evaluate(new StringReader('3*5'))   (3)
    assert result == result2
    def script = shell.parse '3*5'                          (4)
    assert script instanceof groovy.lang.Script
    assert script.run() == 15                               (5)

1 | create a new `GroovyShell` instance
2 | can be used as `Eval` with direct execution of the code
3 | can read from multiple sources (`String`, `Reader`, `File`, `InputStream`)
4 | can defer execution of the script. `parse` returns a `Script` instance
5 | `Script` defines a `run` method

#### 1.2.2. Sharing data between a script and the application

It is possible to share data between the application and the script using a `groovy.lang.Binding`:

    def sharedData = new Binding()                          (1)
    def shell = new GroovyShell(sharedData)                 (2)
    def now = new Date()
    sharedData.setProperty('text', 'I am shared data!')     (3)
    sharedData.setProperty('date', now)                     (4)

    String result = shell.evaluate('"At $date, $text"')     (5)

    assert result == "At $now, I am shared data!"

1 | create a new `Binding` that will contain shared data
2 | create a `GroovyShell` using this shared data
3 | add a string to the binding
4 | add a date to the binding (you are not limited to simple types)
5 | evaluate the script

Note that it is also possible to write from the script into the binding:

    def sharedData = new Binding()                          (1)
    def shell = new GroovyShell(sharedData)                 (2)

    shell.evaluate('foo=123')                               (3)

    assert sharedData.getProperty('foo') == 123             (4)

1 | create a new `Binding` instance
2 | create a new `GroovyShell` using that shared data
3 | use an undeclared variable to store the result into the binding
4 | read the result from the caller

It is important to understand that you need to use an undeclared variable if you want to write into the binding. Using `def` or an `explicit` type like in the example below would fail because you would then create a local variable:

    def sharedData = new Binding()
    def shell = new GroovyShell(sharedData)

    shell.evaluate('int foo=123')

    try {
        assert sharedData.getProperty('foo')
    } catch (MissingPropertyException e) {
        println "foo is defined as a local variable"
    }

| You must be very careful when using shared data in a multithreaded environment. The `Binding` instance that you pass to `GroovyShell` is not thread safe, and shared by all scripts.

It is possible to work around the shared instance of `Binding` by leveraging the `Script` instance which is returned by `parse`:

    def shell = new GroovyShell()

    def b1 = new Binding(x:3)                       (1)
    def b2 = new Binding(x:4)                       (2)
    def script = shell.parse('x = 2*x')
    script.binding = b1
    script.run()
    script.binding = b2
    script.run()
    assert b1.getProperty('x') == 6
    assert b2.getProperty('x') == 8
    assert b1 != b2

1 | will store the `x` variable inside `b1`
2 | will store the `x` variable inside `b2`

However, you must be aware that you are still sharing the same instance of a script. So this technique cannot be used if you have two threads working on the same script. In that case, you must make sure of creating two distinct script instances:

    def shell = new GroovyShell()

    def b1 = new Binding(x:3)
    def b2 = new Binding(x:4)
    def script1 = shell.parse('x = 2*x')            (1)
    def script2 = shell.parse('x = 2*x')            (2)
    assert script1 != script2
    script1.binding = b1                            (3)
    script2.binding = b2                            (4)
    def t1 = Thread.start { script1.run() }         (5)
    def t2 = Thread.start { script2.run() }         (6)
    [t1,t2]*.join()                                 (7)
    assert b1.getProperty('x') == 6
    assert b2.getProperty('x') == 8
    assert b1 != b2

1 | create an instance of script for thread 1
2 | create an instance of script for thread 2
3 | assign first binding to script 1
4 | assign second binding to script 2
5 | start first script in a separate thread
6 | start second script in a separate thread
7 | wait for completion

In case you need thread safety like here, it is more advisable to use the GroovyClassLoader directly instead.

#### 1.2.3. Custom script class

We have seen that the `parse` method returns an instance of `groovy.lang.Script`, but it is possible to use a custom class, given that it extends `Script` itself. It can be used to provide additional behavior to the script like in the example below:

    abstract class MyScript extends Script {
        String name

        String greet() {
            "Hello, $name!"
        }
    }

The custom class defines a property called `name` and a new method called `greet`. This class can be used as the script base class by using a custom configuration:

    import org.codehaus.groovy.control.CompilerConfiguration

    def config = new CompilerConfiguration()                                    (1)
    config.scriptBaseClass = 'MyScript'                                         (2)

    def shell = new GroovyShell(this.class.classLoader, new Binding(), config)  (3)
    def script = shell.parse('greet()')                                         (4)
    assert script instanceof MyScript
    script.setName('Michel')
    assert script.run() == 'Hello, Michel!'

1 | create a `CompilerConfiguration` instance
2 | instruct it to use `MyScript` as the base class for scripts
3 | then use the compiler configuration when you create the shell
4 | the script now has access to the new method `greet`

| You are not limited to the sole scriptBaseClass configuration. You can use any of the compiler configuration tweaks, including the compilation customizers.

### 1.3. GroovyClassLoader

In the previous section, we have shown that `GroovyShell` was an easy tool to execute scripts, but it makes it complicated to compile anything but scripts. Internally, it makes use of the `groovy.lang.GroovyClassLoader`, which is at the heart of the compilation and loading of classes at runtime.

By leveraging the `GroovyClassLoader` instead of `GroovyShell`, you will be able to load classes, instead of instances of scripts:

    import groovy.lang.GroovyClassLoader

    def gcl = new GroovyClassLoader()                                           (1)
    def clazz = gcl.parseClass('class Foo { void doIt() { println "ok" } }')    (2)
    assert clazz.name == 'Foo'                                                  (3)
    def o = clazz.newInstance()                                                 (4)
    o.doIt()                                                                    (5)

1 | create a new `GroovyClassLoader`
2 | `parseClass` will return an instance of `Class`
3 | you can check that the class which is returns is really the one defined in the script
4 | and you can create a new instance of the class, which is not a script
5 | then call any method on it

| A GroovyClassLoader keeps a reference of all the classes it created, so it is easy to create a memory leak. In particular, if you execute the same script twice, if it is a String, then you obtain two distinct classes!

    import groovy.lang.GroovyClassLoader
    import org.junit.jupiter.api.Test
    import static groovy.test.GroovyAssert.*

    def gcl = new GroovyClassLoader()
    def clazz1 = gcl.parseClass('class Foo { }')                                (1)
    def clazz2 = gcl.parseClass('class Foo { }')                                (2)
    assert clazz1.name == 'Foo'                                                 (3)
    assert clazz2.name == 'Foo'
    assert clazz1 != clazz2                                                     (4)

1 | dynamically create a class named "Foo"
2 | create an identical looking class, using a separate `parseClass` call
3 | make sure both classes have the same name
4 | but they are actually different!

The reason is that a `GroovyClassLoader` doesn’t keep track of the source text. If you want to have the same instance, then the source must be a file, like in this example:

    def gcl = new GroovyClassLoader()
    def clazz1 = gcl.parseClass(file)                                           (1)
    def clazz2 = gcl.parseClass(new File(file.absolutePath))                    (2)
    assert clazz1.name == 'Foo'                                                 (3)
    assert clazz2.name == 'Foo'
    assert clazz1 == clazz2                                                     (4)

1 | parse a class from a `File`
2 | parse a class from a distinct file instance, but pointing to the same physical file
3 | make sure our classes have the same name
4 | but now, they are the same instance

Using a `File` as input, the `GroovyClassLoader` is capable of caching the generated class file, which avoids creating multiple classes at runtime for the same source.

### 1.4. GroovyScriptEngine

The `groovy.util.GroovyScriptEngine` class provides a flexible foundation for applications which rely on script reloading and script dependencies. While `GroovyShell` focuses on standalone `Script`s and `GroovyClassLoader` handles dynamic compilation and loading of any Groovy class, the `GroovyScriptEngine` will add a layer on top of `GroovyClassLoader` to handle both script dependencies and reloading.

To illustrate this, we will create a script engine and execute code in an infinite loop. First of all, you need to create a directory with the following script inside:

ReloadingTest.groovy

    class Greeter {
        String sayHello() {
            def greet = "Hello, world!"
            greet
        }
    }

    new Greeter()

then you can execute this code using a `GroovyScriptEngine`:

    def binding = new Binding()
    def engine = new GroovyScriptEngine([tmpDir.toURI().toURL()] as URL[])          (1)

    while (true) {
        def greeter = engine.run('ReloadingTest.groovy', binding)                   (2)
        println greeter.sayHello()                                                  (3)
        Thread.sleep(1000)
    }

1 | create a script engine which will look for sources into our source directory
2 | execute the script, which will return an instance of `Greeter`
3 | print the greeting message

At this point, you should see a message printed every second:

    Hello, world!
    Hello, world!
    ...

Without interrupting the script execution, now replace the contents of the `ReloadingTest` file with:

ReloadingTest.groovy

    class Greeter {
        String sayHello() {
            def greet = "Hello, Groovy!"
            greet
        }
    }

    new Greeter()

And the message should change to:

    Hello, world!
    ...
    Hello, Groovy!
    Hello, Groovy!
    ...

But it is also possible to have a dependency on another script. To illustrate this, create the following file into the same directory, without interrupting the executing script:

Dependency.groovy

    class Dependency {
        String message = 'Hello, dependency 1'
    }

and update the `ReloadingTest` script like this:

ReloadingTest.groovy

    import Dependency

    class Greeter {
        String sayHello() {
            def greet = new Dependency().message
            greet
        }
    }

    new Greeter()

And this time, the message should change to:

    Hello, Groovy!
    ...
    Hello, dependency 1!
    Hello, dependency 1!
    ...

And as a last test, you can update the `Dependency.groovy` file without touching the `ReloadingTest` file:

Dependency.groovy

    class Dependency {
        String message = 'Hello, dependency 2'
    }

And you should observe that the dependent file was reloaded:

    Hello, dependency 1!
    ...
    Hello, dependency 2!
    Hello, dependency 2!

### 1.5. CompilationUnit

Ultimately, it is possible to perform more operations during compilation by relying directly on the `org.codehaus.groovy.control.CompilationUnit` class. This class is responsible for determining the various steps of compilation and would let you introduce new steps or even stop compilation at various phases. This is for example how stub generation is done, for the joint compiler.

However, overriding `CompilationUnit` is not recommended and should only be done if no other standard solution works.

## 2. JSR 223 javax.script API

| JSR-223 is a standard API for calling scripting frameworks in Java. It is available since Java 6 and aims at providing a common framework for calling multiple languages from Java. Groovy provides its own richer integration mechanisms, and if you don’t plan to use multiple languages in the same application, it is recommended that you use the Groovy integration mechanisms instead of the limited JSR-223 API.

Here is how you need to initialize the JSR-223 engine to talk to Groovy from Java:

    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    ...
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("groovy");

Then you can execute Groovy scripts easily:

    Integer sum = (Integer) engine.eval("(1..10).sum()");
    assertEquals(Integer.valueOf(55), sum);

It is also possible to share variables:

    engine.put("first", "HELLO");
    engine.put("second", "world");
    String result = (String) engine.eval("first.toLowerCase() + ' ' + second.toUpperCase()");
    assertEquals("hello WORLD", result);

This next example illustrates calling an invokable function:

    import javax.script.Invocable;
    ...
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("groovy");
    String fact = "def factorial(n) { n == 1 ? 1 : n * factorial(n - 1) }";
    engine.eval(fact);
    Invocable inv = (Invocable) engine;
    Object[] params = {5};
    Object result = inv.invokeFunction("factorial", params);
    assertEquals(Integer.valueOf(120), result);

The engine keeps per default hard references to the script functions. To change this you should set an engine level scoped attribute to the script context of the name `#jsr223.groovy.engine.keep.globals` with a String being `phantom` to use phantom references, `weak` to use weak references or `soft` to use soft references - casing is ignored. Any other string will cause the use of hard references.