JSR-223 scripting engine implementation for Apache Groovy that enables Java applications to execute Groovy scripts through the standard javax.script API
npx @tessl/cli install tessl/maven-org-codehaus-groovy--groovy-jsr223@3.0.0Groovy JSR-223 is a scripting engine implementation that provides JSR-223 (Scripting for the Java Platform) compliant support for executing Groovy scripts within Java applications. It enables seamless integration between Java and Groovy code through the standard javax.script API, supporting dynamic script execution, compiled script caching, and full integration with Groovy's language features.
<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-jsr223</artifactId><version>3.0.25</version></dependency> for Maven, or implementation 'org.codehaus.groovy:groovy-jsr223:3.0.25' for Gradleimport javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
// Direct factory usage
import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory;
import org.codehaus.groovy.jsr223.GroovyScriptEngineImpl;import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
// Standard JSR-223 discovery
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
// Execute simple script
try {
Object result = engine.eval("return 'Hello from Groovy!'");
System.out.println(result); // prints: Hello from Groovy!
// Set variables and execute
engine.put("name", "World");
engine.eval("greeting = 'Hello, ' + name");
System.out.println(engine.get("greeting")); // prints: Hello, World
} catch (ScriptException e) {
e.printStackTrace();
}Groovy JSR-223 is built around several key components:
Factory class for creating and discovering Groovy script engines through the JSR-223 API.
/**
* Factory class conforming to JSR-223 for instantiating Groovy ScriptEngines
*/
public class GroovyScriptEngineFactory implements ScriptEngineFactory {
/**
* Returns the full name of the ScriptEngine
* @return "Groovy Scripting Engine"
*/
public String getEngineName();
/**
* Returns the version of the ScriptEngine
* @return "2.0"
*/
public String getEngineVersion();
/**
* Returns the name of the scripting language supported by this ScriptEngine
* @return "Groovy"
*/
public String getLanguageName();
/**
* Returns the version of the scripting language supported by this ScriptEngine
* @return The current Groovy runtime version
*/
public String getLanguageVersion();
/**
* Returns file extensions supported by this engine
* @return List containing "groovy"
*/
public List<String> getExtensions();
/**
* Returns MIME types supported by this engine
* @return List containing "application/x-groovy"
*/
public List<String> getMimeTypes();
/**
* Returns short names for the ScriptEngine
* @return List containing "groovy" and "Groovy"
*/
public List<String> getNames();
/**
* Returns the value of an attribute whose meaning may be implementation-specific
* @param key The name of the parameter
* @return The value for the given parameter
*/
public Object getParameter(String key);
/**
* Returns a valid scripting language executable program with given method call syntax
* @param obj The name representing the object whose method is to be invoked
* @param method The name of the method to be invoked
* @param args Names of the arguments in the method call
* @return The String used to invoke the method in the syntax of the scripting language
*/
public String getMethodCallSyntax(String obj, String method, String... args);
/**
* Returns a valid scripting language executable program with a given statement
* @param toDisplay A String to be displayed
* @return The string used to display the string in the syntax of the scripting language
*/
public String getOutputStatement(String toDisplay);
/**
* Returns a valid scripting language executable program
* @param statements Individual statements in the scripting language
* @return The Program as a String
*/
public String getProgram(String... statements);
/**
* Returns an instance of the ScriptEngine associated with this ScriptEngineFactory
* @return A new ScriptEngine instance
*/
public ScriptEngine getScriptEngine();
}Usage Example:
import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory;
import javax.script.ScriptEngine;
// Direct factory usage
GroovyScriptEngineFactory factory = new GroovyScriptEngineFactory();
ScriptEngine engine = factory.getScriptEngine();
// Get factory information
System.out.println("Engine: " + factory.getEngineName());
System.out.println("Language: " + factory.getLanguageName());
System.out.println("Extensions: " + factory.getExtensions());Main script engine implementation providing compilation, execution, and invocation capabilities.
/**
* JSR-223 Engine implementation for Groovy scripts
*/
public class GroovyScriptEngineImpl extends AbstractScriptEngine
implements Compilable, Invocable {
/**
* Default constructor using default GroovyClassLoader
*/
public GroovyScriptEngineImpl();
/**
* Constructor with custom class loader
* @param classLoader Custom GroovyClassLoader instance
*/
public GroovyScriptEngineImpl(GroovyClassLoader classLoader);
/**
* Causes the immediate execution of the script whose source is the String passed as the first argument
* @param script The script to be executed by the script engine
* @param ctx A ScriptContext exposing sets of attributes in different scopes
* @return The value returned from the execution of the script
* @throws ScriptException if an error occurs in script
*/
public Object eval(String script, ScriptContext ctx) throws ScriptException;
/**
* Same as eval(String, ScriptContext) where the source of the script is read from a Reader
* @param reader The source of the script
* @param ctx The ScriptContext passed to the script engine
* @return The return value from the script execution
* @throws ScriptException if an error occurs in script
*/
public Object eval(Reader reader, ScriptContext ctx) throws ScriptException;
/**
* Returns an uninitialized Bindings
* @return A Bindings that can be used to replace the state of the engine
*/
public Bindings createBindings();
/**
* Returns the ScriptEngineFactory for the class to which this ScriptEngine belongs
* @return The ScriptEngineFactory
*/
public ScriptEngineFactory getFactory();
/**
* Sets the class loader for this script engine
* @param classLoader The GroovyClassLoader to use
*/
public void setClassLoader(GroovyClassLoader classLoader);
/**
* Gets the class loader for this script engine
* @return The current GroovyClassLoader
*/
public GroovyClassLoader getClassLoader();
}Support for pre-compiling scripts to improve performance with repeated execution.
/**
* Compilable interface methods for script pre-compilation
*/
public interface Compilable {
/**
* Compiles the script (source represented as a String) for later execution
* @param script The source of the script, represented as a String
* @return An instance of a subclass of CompiledScript to be executed later using eval methods
* @throws ScriptException if compilation fails
*/
public CompiledScript compile(String script) throws ScriptException;
/**
* Compiles the script (source read from Reader) for later execution
* @param script The reader from which the script source is obtained
* @return An instance of a subclass of CompiledScript to be executed later using eval methods
* @throws ScriptException if compilation fails
*/
public CompiledScript compile(Reader script) throws ScriptException;
}Usage Example:
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
if (engine instanceof Compilable) {
Compilable compilable = (Compilable) engine;
// Compile script once
CompiledScript compiled = compilable.compile("return Math.pow(x, 2)");
// Execute multiple times with different variables
engine.put("x", 5);
Object result1 = compiled.eval(); // returns 25.0
engine.put("x", 10);
Object result2 = compiled.eval(); // returns 100.0
}Support for invoking functions and methods within executed scripts.
/**
* Invocable interface methods for function and method invocation
*/
public interface Invocable {
/**
* Calls a method on a previously executed script
* @param name The name of the method to invoke
* @param args Arguments to pass to the method
* @return The return value from the method
* @throws ScriptException If the method does not exist or other error occurs
* @throws NoSuchMethodException If method with given name or matching arguments is not found
*/
public Object invokeFunction(String name, Object... args)
throws ScriptException, NoSuchMethodException;
/**
* Calls a method on an object that was set in the engine's context
* @param thiz Object on which the method is to be called
* @param name The name of the method to invoke
* @param args Arguments to pass to the method
* @return The return value from the method
* @throws ScriptException If the method does not exist or other error occurs
* @throws NoSuchMethodException If method with given name or matching arguments is not found
*/
public Object invokeMethod(Object thiz, String name, Object... args)
throws ScriptException, NoSuchMethodException;
/**
* Returns an implementation of an interface using functions compiled in the interpreter
* @param clazz The Class object of the interface to return
* @return An instance of requested interface - null if the requested interface is unavailable
*/
public <T> T getInterface(Class<T> clazz);
/**
* Returns an implementation of an interface using member functions of a scripting object
* @param thiz The scripting object whose member functions are used to implement the methods
* @param clazz The Class object of the interface to return
* @return An instance of requested interface - null if the requested interface is unavailable
*/
public <T> T getInterface(Object thiz, Class<T> clazz);
}Usage Example:
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
// Define functions in script
engine.eval("def greet(name) { return 'Hello, ' + name }");
engine.eval("def add(a, b) { return a + b }");
if (engine instanceof Invocable) {
Invocable invocable = (Invocable) engine;
// Invoke functions
Object greeting = invocable.invokeFunction("greet", "Alice");
Object sum = invocable.invokeFunction("add", 5, 3);
System.out.println(greeting); // prints: Hello, Alice
System.out.println(sum); // prints: 8
}Wrapper for compiled scripts enabling efficient repeated execution.
/**
* Represents compiled Groovy scripts for repeated execution without reparsing
*/
public class GroovyCompiledScript extends CompiledScript {
/**
* Constructor for compiled script
* @param engine The script engine that compiled this script
* @param clazz The compiled script class
*/
public GroovyCompiledScript(GroovyScriptEngineImpl engine, Class<?> clazz);
/**
* Executes the program stored in this CompiledScript object
* @param context A ScriptContext that is used in the same way as the ScriptContext parameter passed to eval methods
* @return The return value from the script execution
* @throws ScriptException if an error occurs during script execution
*/
public Object eval(ScriptContext context) throws ScriptException;
/**
* Returns the ScriptEngine whose compile method created this CompiledScript
* @return The ScriptEngine that created this CompiledScript
*/
public ScriptEngine getEngine();
}Extension methods that enhance ScriptEngine functionality with Groovy Binding integration.
/**
* Extension methods for enhanced ScriptEngine functionality with Groovy Binding support
*/
public class ScriptExtensions {
/**
* Executes script with Groovy Binding integration
* @param self The ScriptEngine instance
* @param script The script source to execute
* @param binding A Groovy Binding containing variables for the script
* @return The result of script execution
* @throws ScriptException if error occurs in script
*/
public static Object eval(ScriptEngine self, String script, Binding binding)
throws ScriptException;
/**
* Executes script from Reader with Groovy Binding integration
* @param self The ScriptEngine instance
* @param reader The source of the script
* @param binding A Groovy Binding containing variables for the script
* @return The result of script execution
* @throws ScriptException if error occurs in script
*/
public static Object eval(ScriptEngine self, Reader reader, Binding binding)
throws ScriptException;
}Usage Example:
import org.codehaus.groovy.jsr223.ScriptExtensions;
import groovy.lang.Binding;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
// Create Groovy binding with variables
Binding binding = new Binding();
binding.setVariable("name", "Alice");
binding.setVariable("age", 30);
// Execute script with binding
Object result = ScriptExtensions.eval(engine,
"greeting = 'Hello, ' + name + '! You are ' + age + ' years old.'; return greeting",
binding);
System.out.println(result); // prints: Hello, Alice! You are 30 years old.
// Variables are available back in binding
System.out.println(binding.getVariable("greeting"));Static extension methods for ScriptEngineManager providing convenient shorthand access.
/**
* Static extension methods for ScriptEngineManager
*/
public class ScriptStaticExtensions {
/**
* Provides convenient shorthand for accessing a scripting engine by language name
* @param self Placeholder for Groovy extension method (unused)
* @param languageShortName The short name of the scripting engine
* @return The ScriptEngine corresponding to the supplied short name or null if not found
*/
public static ScriptEngine $static_propertyMissing(ScriptEngineManager self,
String languageShortName);
}The Groovy JSR-223 engine follows standard JSR-223 error handling patterns:
/**
* Common exceptions thrown by the Groovy script engine
*/
public class ScriptException extends Exception {
// Thrown when script compilation or execution fails
}
public class NoSuchMethodException extends Exception {
// Thrown when invokeFunction or invokeMethod cannot find the specified method
}Error Handling Example:
import javax.script.ScriptException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
try {
// This will cause a compilation error
engine.eval("invalid groovy syntax {{{");
} catch (ScriptException e) {
System.err.println("Script error: " + e.getMessage());
System.err.println("Line number: " + e.getLineNumber());
System.err.println("Column number: " + e.getColumnNumber());
}For repeated script execution, use compiled scripts:
import javax.script.*;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
Compilable compilable = (Compilable) engine;
// Compile once
CompiledScript compiled = compilable.compile("return x * x + y * y");
// Execute many times with different variables
for (int i = 0; i < 1000; i++) {
engine.put("x", i);
engine.put("y", i + 1);
Object result = compiled.eval();
}// Core JSR-223 types used by Groovy engine
interface ScriptEngine {
// Standard JSR-223 interface
}
interface ScriptEngineFactory {
// Standard JSR-223 interface
}
interface Compilable {
// Standard JSR-223 interface for script compilation
}
interface Invocable {
// Standard JSR-223 interface for method invocation
}
abstract class CompiledScript {
// Standard JSR-223 abstract class for compiled scripts
}
interface Bindings extends Map<String, Object> {
// Standard JSR-223 interface for variable bindings
}
class ScriptContext {
// Standard JSR-223 class for script execution context
public static final int ENGINE_SCOPE = 100;
public static final int GLOBAL_SCOPE = 200;
}
// Groovy-specific types
class Binding {
// Groovy's variable binding class
public Object getVariable(String name);
public void setVariable(String name, Object value);
public Map<String, Object> getVariables();
}
class GroovyClassLoader extends ClassLoader {
// Groovy's specialized class loader
}