# Integrating Groovy in a Java application

version 6.0.0-RC-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. JavaShell

While `GroovyShell` and `GroovyClassLoader` compile Groovy source, `org.apache.groovy.util.JavaShell` compiles Java source in-memory using the platform `javax.tools.JavaCompiler`. It is useful when a Groovy or polyglot application needs to compile and load Java classes at runtime: code generation, plug-in loaders, scripting-style Java endpoints, or mixed-language testing setups.

| `JavaShell` requires a JDK at runtime, not just a JRE — `ToolProvider.getSystemJavaCompiler()` returns `null` on a JRE.

The simplest usage compiles a single source string and returns the loaded `Class`:

    import org.apache.groovy.util.JavaShell

    def js = new JavaShell()                                                    (1)
    def src = """
        package demo;
        public class Foo {
            public static String greet(String who) { return "hello, " + who; }
        }
    """
    Class<?> foo = js.compile('demo.Foo', src)                                  (2)
    assert foo.getDeclaredMethod('greet', String).invoke(null, 'world') == 'hello, world'  (3)

1 | create a new `JavaShell` (an optional `ClassLoader` argument sets the parent loader)
2 | compile the source; `className` is the fully-qualified binary name and must match the `package` declaration — see the `JavaShell` javadoc for the full naming rules
3 | invoke the compiled method reflectively

`compileAll` returns every class produced from the source unit — useful when the source declares auxiliary or nested classes:

    import org.apache.groovy.util.JavaShell

    def js = new JavaShell()
    def src = """
        package demo;
        public class Box { public static int hidden() { return Helper.value(); } }
        class Helper { static int value() { return 42; } }
    """
    Map<String, Class<?>> classes = js.compileAll('demo.Box', src)              (1)
    assert classes.keySet() == ['demo.Box', 'demo.Helper'] as Set               (2)
    assert classes['demo.Box'].getDeclaredMethod('hidden').invoke(null) == 42

1 | compile a primary public class together with its package-private helper
2 | the returned map is keyed by binary class name

To additionally persist the generated class files to disk (for tools that consume `.class` files or to seed a classpath outside the JVM), use `compileAllTo`. It accepts a `Path` output directory and writes each class to its conventional package subdirectory:

    import org.apache.groovy.util.JavaShell
    import java.nio.file.Files

    def out = Files.createTempDirectory('javashell-')
    try {
        def js = new JavaShell()
        def src = """
            package demo;
            public class Deep { public static String tag(String label) { return label; } }
        """
        def written = js.compileAllTo('demo.Deep', ['-parameters'], src, out)   (1)
        def classFile = out.resolve('demo/Deep.class')                          (2)
        assert written['demo.Deep'] == classFile && Files.exists(classFile)
        // classes also remain available through js.classLoader, same as compileAll
        assert js.classLoader.loadClass('demo.Deep').getDeclaredMethod('tag', String).invoke(null, 'x') == 'x'
    } finally {
        out.toFile().deleteDir()
    }

1 | compile and write to disk in one call; the second argument passes `javac` options (here `-parameters` to retain formal parameter names)
2 | packaged classes land under `<outputDir>/<package as path>/<ClassName>.class`; default-package classes land directly under `outputDir`

The compiled classes remain available through `js.getClassLoader()` after `compileAllTo` returns, so the same instance covers both "compile to memory" and "compile to memory and disk".

When the source fails to compile, `JavaShell` throws `JavaShellCompilationException` carrying the `javac` diagnostics. See the `JavaShell` javadoc for the full set of overloads (with/without an `Iterable<String>` options argument) and the expected `className`/`options` formats.

| `compileAllTo` and its no-options overload are marked `@Incubating` — their signatures may evolve in a subsequent 6.x release based on usage feedback.

### 1.6. 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. Class loader release in managed environments

Applications that load and discard Groovy repeatedly — a web container performing (parallel) redeployments with Groovy inside each web application, plugin systems, or any host that expects class loaders to be garbage collected — need one extra consideration.

Groovy associates runtime metadata (`ClassInfo`) with every class it dispatches on, including JDK classes such as `String`. By default those associations use `java.lang.ClassValue`, which gives the fastest possible lookup. A `ClassValue` association lives exactly as long as the key class does — by design (see JDK-8136353, resolved as working as intended) — so an association on a long-lived class such as `String` never releases its value, and with it holds the Groovy class loader the value belongs to. In a container this shows up as metaspace growth on every redeployment, even after the old application is undeployed.

Three supported measures release the class loader; any one suffices:

- Start the JVM with `-Dgroovy.use.classvalue=soft`. Groovy keeps the `ClassValue` per-class fast path but holds each association through a `SoftReference`, so immortal JDK classes no longer hold a strong chain to the Groovy class loader. Metadata carrying state that cannot be rebuilt — an installed or per-instance metaclass, registry-written extension methods — is strong-rooted while in use, and associations cleared under memory pressure are rebuilt on demand, with call-site guards remaining sound for `invokedynamic` and classic call sites alike. This preserves default-mode dispatch performance while letting the collector reclaim the loader.

- Start the JVM with `-Dgroovy.use.classvalue=false`. Groovy then stores the associations in a weak-key map instead of `ClassValue`. The trade-off is a hash lookup where `ClassValue` has a per-class fast path. Compilation speed is unaffected (within 1% in our measurements), and for applications that are not dispatch-heavy the difference is unlikely to be noticed; heavily dynamic code, however, can see a few percent overall, with hot dynamic idioms on JDK-class receivers (string coercions, ranges, safe navigation, map property access) up to roughly 1.4 times slower. Measure with your own workload if dispatch performance matters.

- Clean up explicitly when the application is discarded (for example from `ServletContextListener#contextDestroyed`):

      import org.codehaus.groovy.reflection.ClassInfo

      for (ClassInfo ci : ClassInfo.getAllClassInfo()) {
          Class<?> c = ci.theClass
          if (c != null) ClassInfo.remove(c)
      }

| Groovy itself starts no non-terminating background threads, so no thread of Groovy’s will pin the class loader. Threads started by user code (including via `Thread.start` from scripts, or executors created by scripts) capture the creating context and must be shut down by the application as usual.

## 3. 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.