or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# Groovy JSR-223 Script Engine

1

2

A JSR-223 (Java Specification Request 223 - Scripting for the Java Platform) compliant script engine implementation for Apache Groovy. This package enables Java applications to execute Groovy scripts through the standard javax.script API, providing seamless integration between Java and Groovy code.

3

4

## Package Information

5

6

- **Package Name**: org.apache.groovy:groovy-jsr223

7

- **Package Type**: Maven

8

- **Language**: Java

9

- **Installation**:

10

- **Maven**:

11

```xml

12

<dependency>

13

<groupId>org.apache.groovy</groupId>

14

<artifactId>groovy-jsr223</artifactId>

15

<version>5.0.0</version>

16

</dependency>

17

```

18

- **Gradle**:

19

```groovy

20

implementation 'org.apache.groovy:groovy-jsr223:5.0.0'

21

```

22

23

## Core Imports

24

25

```java

26

import javax.script.ScriptEngineManager;

27

import javax.script.ScriptEngine;

28

import javax.script.ScriptException;

29

import javax.script.Compilable;

30

import javax.script.CompiledScript;

31

import javax.script.Invocable;

32

import org.codehaus.groovy.jsr223.GroovyScriptEngineFactory;

33

import org.codehaus.groovy.jsr223.GroovyScriptEngineImpl;

34

import org.codehaus.groovy.control.CompilationFailedException;

35

```

36

37

For extension methods:

38

39

```java

40

import org.codehaus.groovy.jsr223.ScriptExtensions;

41

import org.codehaus.groovy.jsr223.ScriptStaticExtensions;

42

import groovy.lang.Binding;

43

```

44

45

## Basic Usage

46

47

```java

48

import javax.script.*;

49

50

// Get Groovy script engine through ScriptEngineManager

51

ScriptEngineManager manager = new ScriptEngineManager();

52

ScriptEngine engine = manager.getEngineByName("groovy");

53

54

// Execute simple script

55

Object result = engine.eval("2 + 3");

56

System.out.println(result); // Outputs: 5

57

58

// Execute script with variables

59

engine.put("x", 10);

60

engine.put("y", 20);

61

Object sum = engine.eval("x + y");

62

System.out.println(sum); // Outputs: 30

63

64

// Execute script with more complex logic

65

String script = """

66

def greet(name) {

67

return "Hello, ${name}!"

68

}

69

greet('World')

70

""";

71

Object greeting = engine.eval(script);

72

System.out.println(greeting); // Outputs: Hello, World!

73

74

// Compile and reuse scripts

75

Compilable compilable = (Compilable) engine;

76

CompiledScript compiled = compilable.compile("Math.sqrt(x)");

77

78

engine.put("x", 16);

79

Object result1 = compiled.eval(); // 4.0

80

81

engine.put("x", 25);

82

Object result2 = compiled.eval(); // 5.0

83

```

84

85

## Architecture

86

87

The Groovy JSR-223 implementation consists of several key components:

88

89

- **GroovyScriptEngineFactory**: JSR-223 factory class that creates script engine instances and provides metadata about the Groovy scripting engine

90

- **GroovyScriptEngineImpl**: Main script engine implementation providing script evaluation, compilation, and invocation capabilities

91

- **GroovyCompiledScript**: Represents pre-compiled Groovy scripts for efficient repeated execution

92

- **Extension Classes**: Provide enhanced integration between Groovy Binding objects and JSR-223 script contexts

93

- **Service Registration**: Automatic discovery through META-INF/services mechanism

94

95

This design provides full JSR-223 compliance while leveraging Groovy's dynamic capabilities and maintaining compatibility with existing Java scripting infrastructure.

96

97

## Capabilities

98

99

### Script Engine Factory

100

101

Factory class for creating Groovy script engines and providing engine metadata.

102

103

```java { .api }

104

public class GroovyScriptEngineFactory implements ScriptEngineFactory {

105

public String getEngineName();

106

public String getEngineVersion();

107

public String getLanguageName();

108

public String getLanguageVersion();

109

public List<String> getExtensions();

110

public List<String> getMimeTypes();

111

public List<String> getNames();

112

public Object getParameter(String key);

113

public ScriptEngine getScriptEngine();

114

public String getMethodCallSyntax(String obj, String method, String... args);

115

public String getOutputStatement(String toDisplay);

116

public String getProgram(String... statements);

117

}

118

```

119

120

**Usage Example:**

121

122

```java

123

GroovyScriptEngineFactory factory = new GroovyScriptEngineFactory();

124

125

// Get engine metadata

126

System.out.println(factory.getEngineName()); // "Groovy Scripting Engine"

127

System.out.println(factory.getLanguageName()); // "Groovy"

128

System.out.println(factory.getExtensions()); // ["groovy"]

129

System.out.println(factory.getMimeTypes()); // ["application/x-groovy"]

130

131

// Generate syntax examples

132

String methodCall = factory.getMethodCallSyntax("obj", "doSomething", "arg1", "arg2");

133

System.out.println(methodCall); // "obj.doSomething(arg1,arg2)"

134

135

String output = factory.getOutputStatement("Hello World");

136

System.out.println(output); // "println(\"Hello World\")"

137

138

// Create script engine

139

ScriptEngine engine = factory.getScriptEngine();

140

```

141

142

### Script Engine Implementation

143

144

Main JSR-223 script engine providing evaluation, compilation, and invocation capabilities.

145

146

```java { .api }

147

public class GroovyScriptEngineImpl extends AbstractScriptEngine

148

implements Compilable, Invocable {

149

150

// Constructors

151

public GroovyScriptEngineImpl();

152

public GroovyScriptEngineImpl(GroovyClassLoader classLoader);

153

154

// ScriptEngine methods

155

public Object eval(Reader reader, ScriptContext ctx) throws ScriptException;

156

public Object eval(String script, ScriptContext ctx) throws ScriptException;

157

public Bindings createBindings();

158

public ScriptEngineFactory getFactory();

159

160

// Compilable methods

161

public CompiledScript compile(String scriptSource) throws ScriptException;

162

public CompiledScript compile(Reader reader) throws ScriptException;

163

164

// Invocable methods

165

public Object invokeFunction(String name, Object... args)

166

throws ScriptException, NoSuchMethodException;

167

public Object invokeMethod(Object thiz, String name, Object... args)

168

throws ScriptException, NoSuchMethodException;

169

public <T> T getInterface(Class<T> clazz);

170

public <T> T getInterface(Object thiz, Class<T> clazz);

171

172

// Script class management methods

173

public Class<?> getScriptClass(String script) throws CompilationFailedException;

174

public Class<?> getScriptClass(String script, ScriptContext context)

175

throws CompilationFailedException;

176

177

// Utility methods

178

public void setClassLoader(GroovyClassLoader classLoader);

179

public GroovyClassLoader getClassLoader();

180

}

181

```

182

183

**Usage Example:**

184

185

```java

186

// Direct instantiation

187

GroovyScriptEngineImpl engine = new GroovyScriptEngineImpl();

188

189

// Function invocation

190

engine.eval("def multiply(a, b) { return a * b }");

191

Invocable invocable = (Invocable) engine;

192

Object result = invocable.invokeFunction("multiply", 5, 3); // 15

193

194

// Method invocation on objects

195

engine.eval("""

196

class Calculator {

197

def add(a, b) { return a + b }

198

def subtract(a, b) { return a - b }

199

}

200

calc = new Calculator()

201

""");

202

Object calculator = engine.get("calc");

203

Object sum = invocable.invokeMethod(calculator, "add", 10, 5); // 15

204

205

// Interface proxy

206

engine.eval("""

207

def hello(name) { return "Hello, ${name}!" }

208

def goodbye(name) { return "Goodbye, ${name}!" }

209

""");

210

211

interface Greeter {

212

String hello(String name);

213

String goodbye(String name);

214

}

215

216

Greeter greeter = invocable.getInterface(Greeter.class);

217

System.out.println(greeter.hello("Alice")); // "Hello, Alice!"

218

219

// Access to script class compilation

220

GroovyScriptEngineImpl groovyEngine = (GroovyScriptEngineImpl) engine;

221

Class<?> scriptClass = groovyEngine.getScriptClass("def hello() { 'Hello World' }");

222

System.out.println(scriptClass.getName()); // Generated class name

223

224

// Script class compilation with context

225

ScriptContext context = engine.getContext();

226

context.setAttribute(ScriptEngine.FILENAME, "MyScript.groovy", ScriptContext.ENGINE_SCOPE);

227

Class<?> namedClass = groovyEngine.getScriptClass("def greet() { 'Greetings!' }", context);

228

```

229

230

### Compiled Scripts

231

232

Pre-compiled Groovy scripts for efficient repeated execution.

233

234

```java { .api }

235

public class GroovyCompiledScript extends CompiledScript {

236

public GroovyCompiledScript(GroovyScriptEngineImpl engine, Class<?> clazz);

237

public Object eval(ScriptContext context) throws ScriptException;

238

public ScriptEngine getEngine();

239

}

240

```

241

242

**Usage Example:**

243

244

```java

245

ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");

246

Compilable compilable = (Compilable) engine;

247

248

// Compile script once

249

CompiledScript compiled = compilable.compile("""

250

def processData(data) {

251

return data.collect { it * 2 }.findAll { it > 10 }

252

}

253

processData(input)

254

""");

255

256

// Execute multiple times with different inputs

257

engine.put("input", Arrays.asList(1, 2, 5, 8, 10));

258

Object result1 = compiled.eval(); // [16, 20]

259

260

engine.put("input", Arrays.asList(3, 6, 9, 12));

261

Object result2 = compiled.eval(); // [12, 18, 24]

262

```

263

264

### Script Extensions

265

266

Extension methods providing enhanced integration between ScriptEngine and Groovy Binding.

267

268

```java { .api }

269

public class ScriptExtensions {

270

public static Object eval(ScriptEngine self, String script, Binding binding)

271

throws ScriptException;

272

public static Object eval(ScriptEngine self, Reader reader, Binding binding)

273

throws ScriptException;

274

}

275

```

276

277

**Usage Example:**

278

279

```java

280

import static org.codehaus.groovy.jsr223.ScriptExtensions.eval;

281

282

ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");

283

Binding binding = new Binding();

284

285

// Set variables in Groovy binding

286

binding.setVariable("name", "Alice");

287

binding.setVariable("age", 25);

288

289

// Execute script with binding integration

290

Object result = eval(engine, "\"${name} is ${age} years old\"", binding);

291

System.out.println(result); // "Alice is 25 years old"

292

293

// Variables modified in script are reflected back in binding

294

eval(engine, "name = name.toUpperCase(); newVar = 'created'", binding);

295

System.out.println(binding.getVariable("name")); // "ALICE"

296

System.out.println(binding.getVariable("newVar")); // "created"

297

```

298

299

### Static Extensions

300

301

Static extension methods for ScriptEngineManager providing dynamic engine access.

302

303

```java { .api }

304

public class ScriptStaticExtensions {

305

public static ScriptEngine $static_propertyMissing(

306

ScriptEngineManager self, String languageShortName);

307

}

308

```

309

310

**Usage Example:**

311

312

```java

313

// This enables dynamic property access syntax in Groovy code:

314

// manager.groovy instead of manager.getEngineByName("groovy")

315

316

// Standard JSR-223 approach

317

ScriptEngineManager manager = new ScriptEngineManager();

318

ScriptEngine groovyEngine = manager.getEngineByName("groovy");

319

ScriptEngine jsEngine = manager.getEngineByName("javascript");

320

321

// With static extensions (in Groovy code):

322

// ScriptEngine groovyEngine = manager.groovy

323

// ScriptEngine jsEngine = manager.javascript

324

```

325

326

## Error Handling

327

328

The implementation provides comprehensive error handling for various scenarios:

329

330

```java

331

ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");

332

333

try {

334

// Script compilation errors

335

engine.eval("def invalid syntax here");

336

} catch (ScriptException e) {

337

System.err.println("Script compilation failed: " + e.getMessage());

338

}

339

340

try {

341

// Function invocation errors

342

Invocable invocable = (Invocable) engine;

343

invocable.invokeFunction("nonExistentFunction");

344

} catch (NoSuchMethodException e) {

345

System.err.println("Function not found: " + e.getMessage());

346

} catch (ScriptException e) {

347

System.err.println("Script execution failed: " + e.getMessage());

348

}

349

350

try {

351

// Invalid parameters

352

GroovyScriptEngineFactory factory = new GroovyScriptEngineFactory();

353

factory.getParameter("INVALID_KEY");

354

} catch (IllegalArgumentException e) {

355

System.err.println("Invalid parameter key: " + e.getMessage());

356

}

357

```

358

359

**Common Exceptions:**

360

361

- `ScriptException`: Script compilation or execution errors

362

- `NoSuchMethodException`: Missing function/method invocations

363

- `IllegalArgumentException`: Invalid parameters or arguments

364

- `NullPointerException`: Null method names in invocations

365

366

## Configuration Options

367

368

### Reference Management

369

370

Control memory management for global closures:

371

372

```java

373

ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");

374

375

// Configure closure reference strength

376

engine.getContext().setAttribute(

377

"#jsr223.groovy.engine.keep.globals",

378

"weak", // Options: "hard", "soft", "weak", "phantom"

379

ScriptContext.ENGINE_SCOPE

380

);

381

```

382

383

### Custom ClassLoader

384

385

Use custom ClassLoader for script compilation:

386

387

```java

388

GroovyClassLoader customLoader = new GroovyClassLoader();

389

GroovyScriptEngineImpl engine = new GroovyScriptEngineImpl(customLoader);

390

391

// Or modify existing engine

392

engine.setClassLoader(customLoader);

393

```

394

395

## Thread Safety

396

397

The Groovy JSR-223 implementation provides:

398

399

- **MULTITHREADED** support as indicated by the THREADING parameter

400

- Thread-safe script class caching using concurrent maps

401

- Safe concurrent execution of compiled scripts

402

- Proper synchronization of ScriptContext access

403

404

```java

405

// Multiple threads can safely share a compiled script

406

CompiledScript compiled = ((Compilable) engine).compile("Math.random()");

407

408

// Each thread should use its own ScriptContext for variable isolation

409

ExecutorService executor = Executors.newFixedThreadPool(10);

410

for (int i = 0; i < 100; i++) {

411

executor.submit(() -> {

412

try {

413

ScriptContext context = new SimpleScriptContext();

414

Object result = compiled.eval(context);

415

System.out.println("Random: " + result);

416

} catch (ScriptException e) {

417

e.printStackTrace();

418

}

419

});

420

}

421

```

422

423

## Types

424

425

```java { .api }

426

// Core JSR-223 interfaces implemented

427

interface ScriptEngineFactory {

428

String getEngineName();

429

String getEngineVersion();

430

String getLanguageName();

431

String getLanguageVersion();

432

List<String> getExtensions();

433

List<String> getMimeTypes();

434

List<String> getNames();

435

Object getParameter(String key);

436

ScriptEngine getScriptEngine();

437

String getMethodCallSyntax(String obj, String method, String... args);

438

String getOutputStatement(String toDisplay);

439

String getProgram(String... statements);

440

}

441

442

interface ScriptEngine {

443

Object eval(String script) throws ScriptException;

444

Object eval(Reader reader) throws ScriptException;

445

Object eval(String script, ScriptContext context) throws ScriptException;

446

Object eval(Reader reader, ScriptContext context) throws ScriptException;

447

void put(String key, Object value);

448

Object get(String key);

449

Bindings getBindings(int scope);

450

void setBindings(Bindings bindings, int scope);

451

Bindings createBindings();

452

ScriptContext getContext();

453

void setContext(ScriptContext context);

454

ScriptEngineFactory getFactory();

455

}

456

457

interface Compilable {

458

CompiledScript compile(String script) throws ScriptException;

459

CompiledScript compile(Reader script) throws ScriptException;

460

}

461

462

interface Invocable {

463

Object invokeMethod(Object thiz, String name, Object... args)

464

throws ScriptException, NoSuchMethodException;

465

Object invokeFunction(String name, Object... args)

466

throws ScriptException, NoSuchMethodException;

467

<T> T getInterface(Class<T> clazz);

468

<T> T getInterface(Object thiz, Class<T> clazz);

469

}

470

471

abstract class CompiledScript {

472

public abstract Object eval(ScriptContext context) throws ScriptException;

473

public Object eval() throws ScriptException;

474

public abstract ScriptEngine getEngine();

475

}

476

477

// Groovy-specific types

478

class Binding {

479

public Binding();

480

public Binding(Map variables);

481

public Object getVariable(String name);

482

public void setVariable(String name, Object value);

483

public Map getVariables();

484

}

485

486

class GroovyClassLoader extends ClassLoader {

487

public GroovyClassLoader();

488

public GroovyClassLoader(ClassLoader parent);

489

public Class<?> parseClass(String text, String fileName);

490

}

491

492

// Exception types

493

class CompilationFailedException extends RuntimeException {

494

public CompilationFailedException(String message);

495

public CompilationFailedException(String message, Throwable cause);

496

}

497

```