or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdexception-handling.mdindex.mdjava-integration.mdjsr223-scripting.mdpython-execution.mdpython-objects.md

jsr223-scripting.mddocs/

0

# JSR-223 Scripting

1

2

Jython provides full support for the Java Scripting API (JSR-223), allowing seamless integration with existing Java applications that use the standard scripting framework.

3

4

## Script Engine Factory

5

6

The factory class for creating Jython script engines.

7

8

```java { .api }

9

public class PyScriptEngineFactory implements ScriptEngineFactory {

10

// Engine metadata

11

public String getEngineName(); // Returns "jython"

12

public String getEngineVersion(); // Returns Jython version

13

public String getLanguageName(); // Returns "python"

14

public String getLanguageVersion(); // Returns Python version "2.7"

15

public List<String> getExtensions(); // Returns ["py"]

16

public List<String> getMimeTypes(); // Returns Python MIME types

17

public List<String> getNames(); // Returns ["python", "jython"]

18

19

// Script engine creation

20

public ScriptEngine getScriptEngine();

21

22

// Utility methods

23

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

24

public String getOutputStatement(String toDisplay);

25

public String getProgram(String... statements);

26

public Object getParameter(String key);

27

}

28

```

29

30

## Script Engine

31

32

The main JSR-223 script engine implementation for Jython.

33

34

```java { .api }

35

public class PyScriptEngine extends AbstractScriptEngine

36

implements Compilable, Invocable, AutoCloseable {

37

38

// Script execution

39

public Object eval(String script) throws ScriptException;

40

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

41

public Object eval(Reader reader) throws ScriptException;

42

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

43

44

// Compilation support (Compilable interface)

45

public CompiledScript compile(String script) throws ScriptException;

46

public CompiledScript compile(Reader reader) throws ScriptException;

47

48

// Function invocation (Invocable interface)

49

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

50

throws ScriptException, NoSuchMethodException;

51

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

52

throws ScriptException, NoSuchMethodException;

53

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

54

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

55

56

// Engine management

57

public Bindings createBindings();

58

public ScriptEngineFactory getFactory();

59

public void close();

60

}

61

```

62

63

## Script Engine Scope

64

65

Provides variable scoping and bindings for the JSR-223 engine.

66

67

```java { .api }

68

public final class PyScriptEngineScope extends PyObject implements Bindings {

69

// Bindings interface implementation

70

public Object put(String key, Object value);

71

public Object get(Object key);

72

public Object remove(Object key);

73

public boolean containsKey(Object key);

74

public boolean containsValue(Object value);

75

public Set<String> keySet();

76

public Collection<Object> values();

77

public Set<Entry<String, Object>> entrySet();

78

public int size();

79

public boolean isEmpty();

80

public void clear();

81

public void putAll(Map<? extends String, ? extends Object> toMerge);

82

}

83

```

84

85

## Basic Usage Examples

86

87

### Simple Script Execution

88

89

```java

90

import javax.script.*;

91

92

public class JSR223Example {

93

public static void main(String[] args) throws ScriptException {

94

// Get script engine manager

95

ScriptEngineManager manager = new ScriptEngineManager();

96

97

// Get Jython engine by name

98

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

99

100

// Execute simple script

101

engine.eval("print('Hello from Jython!')");

102

103

// Set variables

104

engine.put("name", "World");

105

engine.put("number", 42);

106

107

// Use variables in script

108

Object result = engine.eval("greeting = f'Hello, {name}! The answer is {number}'");

109

Object greeting = engine.get("greeting");

110

111

System.out.println("Result: " + greeting);

112

}

113

}

114

```

115

116

### Using Script Context

117

118

```java

119

ScriptEngineManager manager = new ScriptEngineManager();

120

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

121

122

// Create custom context

123

ScriptContext context = new SimpleScriptContext();

124

Bindings bindings = engine.createBindings();

125

bindings.put("x", 10);

126

bindings.put("y", 20);

127

context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);

128

129

// Execute with custom context

130

Object result = engine.eval("result = x + y", context);

131

Object sum = context.getAttribute("result");

132

133

System.out.println("Sum: " + sum); // Sum: 30

134

```

135

136

## Compilation Support

137

138

Pre-compile scripts for better performance when executing multiple times.

139

140

### Compiling Scripts

141

142

```java

143

ScriptEngineManager manager = new ScriptEngineManager();

144

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

145

146

// Check if engine supports compilation

147

if (engine instanceof Compilable) {

148

Compilable compilable = (Compilable) engine;

149

150

// Compile script

151

CompiledScript compiled = compilable.compile("""

152

def calculate(x, y):

153

return x * y + (x - y)

154

155

result = calculate(a, b)

156

""");

157

158

// Execute compiled script multiple times

159

engine.put("a", 5);

160

engine.put("b", 3);

161

compiled.eval();

162

System.out.println("Result 1: " + engine.get("result")); // 17

163

164

engine.put("a", 10);

165

engine.put("b", 4);

166

compiled.eval();

167

System.out.println("Result 2: " + engine.get("result")); // 46

168

}

169

```

170

171

### CompiledScript Usage

172

173

```java

174

CompiledScript compiled = compilable.compile("x ** 2 + y ** 2");

175

176

// Execute with different contexts

177

ScriptContext ctx1 = new SimpleScriptContext();

178

ctx1.setAttribute("x", 3, ScriptContext.ENGINE_SCOPE);

179

ctx1.setAttribute("y", 4, ScriptContext.ENGINE_SCOPE);

180

Object result1 = compiled.eval(ctx1);

181

System.out.println("3² + 4² = " + result1); // 25

182

183

ScriptContext ctx2 = new SimpleScriptContext();

184

ctx2.setAttribute("x", 5, ScriptContext.ENGINE_SCOPE);

185

ctx2.setAttribute("y", 12, ScriptContext.ENGINE_SCOPE);

186

Object result2 = compiled.eval(ctx2);

187

System.out.println("5² + 12² = " + result2); // 169

188

```

189

190

## Function Invocation

191

192

Call Python functions directly from Java using the Invocable interface.

193

194

### Basic Function Invocation

195

196

```java

197

ScriptEngineManager manager = new ScriptEngineManager();

198

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

199

200

// Define Python functions

201

engine.eval("""

202

def add(x, y):

203

return x + y

204

205

def greet(name, title=""):

206

if title:

207

return f"Hello, {title} {name}!"

208

else:

209

return f"Hello, {name}!"

210

211

class Calculator:

212

def __init__(self, factor=1):

213

self.factor = factor

214

215

def multiply(self, x):

216

return x * self.factor

217

218

calc = Calculator(10)

219

""");

220

221

// Invoke functions

222

if (engine instanceof Invocable) {

223

Invocable invocable = (Invocable) engine;

224

225

// Call simple function

226

Object sum = invocable.invokeFunction("add", 5, 3);

227

System.out.println("Sum: " + sum); // 8

228

229

// Call function with keyword-like behavior (positional only in JSR-223)

230

Object greeting1 = invocable.invokeFunction("greet", "Alice");

231

Object greeting2 = invocable.invokeFunction("greet", "Bob", "Dr.");

232

System.out.println(greeting1); // Hello, Alice!

233

System.out.println(greeting2); // Hello, Dr. Bob!

234

235

// Call method on object

236

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

237

Object product = invocable.invokeMethod(calcInstance, "multiply", 7);

238

System.out.println("Product: " + product); // 70

239

}

240

```

241

242

### Interface Implementation

243

244

Create Java interfaces implemented by Python objects.

245

246

```java

247

// Define Java interface

248

interface MathOperations {

249

double calculate(double x, double y);

250

String getOperationName();

251

}

252

253

// Define Python implementation

254

engine.eval("""

255

class Adder:

256

def calculate(self, x, y):

257

return x + y

258

259

def getOperationName(self):

260

return "Addition"

261

262

adder = Adder()

263

""");

264

265

// Get interface implementation

266

MathOperations mathOps = invocable.getInterface(

267

engine.get("adder"),

268

MathOperations.class

269

);

270

271

// Use as Java interface

272

double result = mathOps.calculate(10.5, 5.3);

273

String opName = mathOps.getOperationName();

274

275

System.out.println(opName + ": " + result); // Addition: 15.8

276

```

277

278

## Advanced Usage Patterns

279

280

### Custom Bindings

281

282

```java

283

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

284

285

// Create custom bindings with initial values

286

Bindings customBindings = new SimpleBindings();

287

customBindings.put("PI", Math.PI);

288

customBindings.put("E", Math.E);

289

customBindings.put("logger", LoggerFactory.getLogger("jython"));

290

291

// Set as engine scope

292

engine.setBindings(customBindings, ScriptContext.ENGINE_SCOPE);

293

294

engine.eval("""

295

import math

296

297

# Use Java objects in Python

298

logger.info("Calculating circle area")

299

300

radius = 5

301

area = PI * radius * radius

302

303

logger.info(f"Area of circle with radius {radius} is {area}")

304

""");

305

```

306

307

### Multi-Engine Coordination

308

309

```java

310

ScriptEngineManager manager = new ScriptEngineManager();

311

312

// Create multiple engines

313

ScriptEngine engine1 = manager.getEngineByName("python");

314

ScriptEngine engine2 = manager.getEngineByName("python");

315

316

// Shared data object

317

Map<String, Object> sharedData = new ConcurrentHashMap<>();

318

319

// Setup engines with shared data

320

engine1.put("shared", sharedData);

321

engine2.put("shared", sharedData);

322

323

// Engine 1 sets data

324

engine1.eval("shared['message'] = 'Hello from Engine 1'");

325

326

// Engine 2 reads data

327

engine2.eval("print('Engine 2 received:', shared.get('message'))");

328

```

329

330

### Error Handling

331

332

```java

333

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

334

335

try {

336

engine.eval("undefined_variable + 1");

337

} catch (ScriptException e) {

338

System.out.println("Script error: " + e.getMessage());

339

System.out.println("Line number: " + e.getLineNumber());

340

System.out.println("Column number: " + e.getColumnNumber());

341

System.out.println("File name: " + e.getFileName());

342

343

// Get the underlying Python exception

344

Throwable cause = e.getCause();

345

if (cause instanceof PyException) {

346

PyException pyEx = (PyException) cause;

347

System.out.println("Python exception type: " + pyEx.type);

348

System.out.println("Python exception value: " + pyEx.value);

349

}

350

}

351

```

352

353

## Configuration and Properties

354

355

### Engine Parameters

356

357

```java

358

ScriptEngineFactory factory = new PyScriptEngineFactory();

359

360

// Get engine information

361

System.out.println("Engine Name: " + factory.getEngineName());

362

System.out.println("Engine Version: " + factory.getEngineVersion());

363

System.out.println("Language Name: " + factory.getLanguageName());

364

System.out.println("Language Version: " + factory.getLanguageVersion());

365

System.out.println("Extensions: " + factory.getExtensions());

366

System.out.println("MIME Types: " + factory.getMimeTypes());

367

System.out.println("Names: " + factory.getNames());

368

369

// Check specific parameters

370

Object threadingType = factory.getParameter(ScriptEngine.THREADING);

371

System.out.println("Threading: " + threadingType);

372

```

373

374

### Script Context Management

375

376

```java

377

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

378

379

// Get default context

380

ScriptContext defaultContext = engine.getContext();

381

382

// Create isolated context for sensitive operations

383

ScriptContext isolatedContext = new SimpleScriptContext();

384

Bindings isolatedBindings = engine.createBindings();

385

isolatedBindings.put("secure_data", "sensitive information");

386

isolatedContext.setBindings(isolatedBindings, ScriptContext.ENGINE_SCOPE);

387

388

// Execute in isolated context

389

engine.eval("result = len(secure_data)", isolatedContext);

390

Object result = isolatedContext.getAttribute("result");

391

392

// Original context remains unaffected

393

Object originalData = defaultContext.getAttribute("secure_data");

394

System.out.println("Original context has secure_data: " + (originalData != null));

395

```

396

397

## Performance Optimization

398

399

### Script Compilation Best Practices

400

401

```java

402

// Cache compiled scripts for reuse

403

Map<String, CompiledScript> scriptCache = new ConcurrentHashMap<>();

404

405

public Object executeScript(String script, Map<String, Object> variables)

406

throws ScriptException {

407

408

// Get or compile script

409

CompiledScript compiled = scriptCache.computeIfAbsent(script, s -> {

410

try {

411

return ((Compilable) engine).compile(s);

412

} catch (ScriptException e) {

413

throw new RuntimeException(e);

414

}

415

});

416

417

// Create context with variables

418

ScriptContext context = new SimpleScriptContext();

419

Bindings bindings = engine.createBindings();

420

bindings.putAll(variables);

421

context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);

422

423

// Execute compiled script

424

return compiled.eval(context);

425

}

426

```

427

428

### Resource Management

429

430

```java

431

// Use try-with-resources for automatic cleanup

432

try (AutoCloseable engine = (AutoCloseable) manager.getEngineByName("python")) {

433

engine.eval("print('Script executed')");

434

// Engine automatically closed

435

}

436

437

// Manual resource management

438

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

439

try {

440

engine.eval("print('Script executed')");

441

} finally {

442

if (engine instanceof AutoCloseable) {

443

((AutoCloseable) engine).close();

444

}

445

}

446

```

447

448

## Integration with Java Frameworks

449

450

### Spring Framework Integration

451

452

```java

453

@Component

454

public class JythonScriptService {

455

private final ScriptEngine engine;

456

457

public JythonScriptService() {

458

ScriptEngineManager manager = new ScriptEngineManager();

459

this.engine = manager.getEngineByName("python");

460

}

461

462

@PostConstruct

463

public void initialize() throws ScriptException {

464

// Load common Python modules

465

engine.eval("""

466

import json

467

import datetime

468

import re

469

470

def format_data(data):

471

return json.dumps(data, indent=2)

472

""");

473

}

474

475

public String processData(Map<String, Object> data) throws ScriptException {

476

engine.put("input_data", data);

477

return (String) engine.eval("format_data(input_data)");

478

}

479

}

480

```

481

482

### Servlet Integration

483

484

```java

485

@WebServlet("/python-script")

486

public class PythonScriptServlet extends HttpServlet {

487

private ScriptEngine engine;

488

489

@Override

490

public void init() throws ServletException {

491

ScriptEngineManager manager = new ScriptEngineManager();

492

engine = manager.getEngineByName("python");

493

}

494

495

@Override

496

protected void doPost(HttpServletRequest request, HttpServletResponse response)

497

throws ServletException, IOException {

498

499

String script = request.getParameter("script");

500

501

try {

502

engine.put("request_params", request.getParameterMap());

503

Object result = engine.eval(script);

504

505

response.setContentType("application/json");

506

response.getWriter().write(result.toString());

507

} catch (ScriptException e) {

508

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

509

response.getWriter().write("Script error: " + e.getMessage());

510

}

511

}

512

}

513

```