0
# JSR-223 Integration
1
2
Complete JSR-223 (Java Scripting API) compatible implementation for seamless integration with existing Java scripting frameworks and applications.
3
4
## Capabilities
5
6
### KotlinJsr223InvocableScriptEngine
7
8
Interface extending JSR-223 Invocable for function and method invocation with backward compatibility support.
9
10
```kotlin { .api }
11
/**
12
* JSR-223 invocable script engine interface with Kotlin-specific extensions
13
*/
14
interface KotlinJsr223InvocableScriptEngine : Invocable {
15
16
/** Optional wrapper for function/method invocation */
17
val invokeWrapper: InvokeWrapper?
18
19
/** Sequence of previously evaluated script instances for backward compatibility */
20
val backwardInstancesHistory: Sequence<Any>
21
22
/** Base class loader for script execution context */
23
val baseClassLoader: ClassLoader
24
25
/**
26
* Invokes a top-level function from previously evaluated scripts
27
* @param name Function name to invoke
28
* @param args Function arguments
29
* @returns Function result or null
30
*/
31
override fun invokeFunction(name: String?, vararg args: Any?): Any?
32
33
/**
34
* Invokes a method on a specific object instance
35
* @param thiz Object instance to invoke method on
36
* @param name Method name to invoke
37
* @param args Method arguments
38
* @returns Method result or null
39
*/
40
override fun invokeMethod(thiz: Any?, name: String?, vararg args: Any?): Any?
41
42
/**
43
* Gets an interface implementation from script context
44
* @param clasz Interface class to implement
45
* @returns Interface implementation or null
46
*/
47
override fun <T : Any> getInterface(clasz: Class<T>?): T?
48
49
/**
50
* Gets an interface implementation from specific object instance
51
* @param thiz Object instance to use as interface implementation
52
* @param clasz Interface class to implement
53
* @returns Interface implementation or null
54
*/
55
override fun <T : Any> getInterface(thiz: Any?, clasz: Class<T>?): T?
56
}
57
```
58
59
### KotlinJsr223ScriptEngineImpl
60
61
Complete JSR-223 script engine implementation with REPL capabilities and context integration.
62
63
```kotlin { .api }
64
/**
65
* JSR-223 script engine implementation with REPL support
66
* @param factory Script engine factory instance
67
* @param baseCompilationConfiguration Base compilation configuration
68
* @param baseEvaluationConfiguration Base evaluation configuration
69
* @param getScriptArgs Function to extract script arguments from JSR-223 context
70
*/
71
class KotlinJsr223ScriptEngineImpl(
72
factory: ScriptEngineFactory,
73
baseCompilationConfiguration: ScriptCompilationConfiguration,
74
baseEvaluationConfiguration: ScriptEvaluationConfiguration,
75
val getScriptArgs: (context: ScriptContext) -> ScriptArgsWithTypes?
76
) : KotlinJsr223JvmScriptEngineBase(factory), KotlinJsr223InvocableScriptEngine {
77
78
/** JSR-223 host configuration with context integration */
79
val jsr223HostConfiguration: ScriptingHostConfiguration
80
81
/** Final compilation configuration with JSR-223 refinements */
82
val compilationConfiguration: ScriptCompilationConfiguration
83
84
/** Final evaluation configuration with JSR-223 refinements */
85
val evaluationConfiguration: ScriptEvaluationConfiguration
86
87
/** REPL compiler for incremental compilation */
88
val replCompiler: ReplCompilerWithoutCheck
89
90
/** REPL evaluator for script execution */
91
val replEvaluator: ReplFullEvaluator
92
93
/** Current REPL state */
94
val state: IReplStageState<*>
95
96
/**
97
* Creates new REPL state with thread synchronization
98
* @param lock Read-write lock for thread safety
99
* @returns New REPL stage state
100
*/
101
fun createState(lock: ReentrantReadWriteLock): IReplStageState<*>
102
103
/**
104
* Overrides script arguments from JSR-223 context
105
* @param context JSR-223 script context
106
* @returns Script arguments with types or null
107
*/
108
fun overrideScriptArgs(context: ScriptContext): ScriptArgsWithTypes?
109
110
/**
111
* Compiles and evaluates script code with context integration
112
* @param script Script code to execute
113
* @param context JSR-223 script context
114
* @returns Evaluation result
115
*/
116
fun compileAndEval(script: String, context: ScriptContext): Any?
117
}
118
```
119
120
**Usage Examples:**
121
122
```kotlin
123
import kotlin.script.experimental.jvmhost.jsr223.*
124
import javax.script.*
125
126
// Create JSR-223 script manager
127
val manager = ScriptEngineManager()
128
129
// Register Kotlin script engine (typically done by service loader)
130
val factory = KotlinJsr223DefaultScriptEngineFactory()
131
manager.registerEngineExtension("kts", factory)
132
133
// Get Kotlin script engine
134
val engine = manager.getEngineByExtension("kts") as KotlinJsr223InvocableScriptEngine
135
136
// Basic script execution
137
val result = engine.eval("""
138
fun greet(name: String) = "Hello, ${'$'}name!"
139
val message = greet("World")
140
println(message)
141
message
142
""")
143
144
println("Script result: $result")
145
146
// Function invocation
147
val greeting = engine.invokeFunction("greet", "JSR-223")
148
println("Function result: $greeting")
149
150
// Context integration
151
val context = engine.context
152
context.setAttribute("userName", "Alice", ScriptContext.ENGINE_SCOPE)
153
context.setAttribute("userAge", 30, ScriptContext.ENGINE_SCOPE)
154
155
val contextResult = engine.eval("""
156
val user = mapOf("name" to userName, "age" to userAge)
157
println("User: ${'$'}user")
158
user
159
""")
160
161
// Interface implementation
162
interface Calculator {
163
fun add(a: Int, b: Int): Int
164
fun multiply(a: Int, b: Int): Int
165
}
166
167
engine.eval("""
168
fun add(a: Int, b: Int) = a + b
169
fun multiply(a: Int, b: Int) = a * b
170
""")
171
172
val calculator = engine.getInterface(Calculator::class.java)
173
println("5 + 3 = ${calculator.add(5, 3)}")
174
println("5 * 3 = ${calculator.multiply(5, 3)}")
175
```
176
177
## Configuration System
178
179
JSR-223 specific configuration keys and builders for customizing script engine behavior.
180
181
### Configuration Builders
182
183
```kotlin { .api }
184
/** JSR-223 host configuration keys */
185
interface Jsr223HostConfigurationKeys
186
187
/** Builder for JSR-223 host configuration */
188
open class Jsr223HostConfigurationBuilder
189
190
/** JSR-223 compilation configuration keys */
191
interface Jsr223CompilationConfigurationKeys
192
193
/** Builder for JSR-223 compilation configuration */
194
open class Jsr223CompilationConfigurationBuilder
195
196
/** JSR-223 evaluation configuration keys */
197
interface Jsr223EvaluationConfigurationKeys
198
199
/** Builder for JSR-223 evaluation configuration */
200
open class Jsr223EvaluationConfigurationBuilder
201
```
202
203
### Configuration Extension Properties
204
205
Extension properties for integrating JSR-223 configuration with standard Kotlin scripting configuration.
206
207
```kotlin { .api }
208
/** JSR-223 host configuration extension */
209
val ScriptingHostConfigurationKeys.jsr223: Jsr223HostConfigurationBuilder
210
211
/** JSR-223 compilation configuration extension */
212
val ScriptCompilationConfigurationKeys.jsr223: Jsr223CompilationConfigurationBuilder
213
214
/** JSR-223 evaluation configuration extension */
215
val ScriptEvaluationConfigurationKeys.jsr223: Jsr223EvaluationConfigurationBuilder
216
```
217
218
### Configuration Keys
219
220
```kotlin { .api }
221
/** Function to get JSR-223 script context from host configuration */
222
val Jsr223HostConfigurationKeys.getScriptContext: () -> ScriptContext?
223
224
/** Function to get JSR-223 script context from compilation configuration */
225
val Jsr223CompilationConfigurationKeys.getScriptContext: () -> ScriptContext?
226
227
/** Whether to import all JSR-223 context bindings as script properties */
228
val Jsr223CompilationConfigurationKeys.importAllBindings: Boolean
229
230
/** Function to get JSR-223 script context from evaluation configuration */
231
val Jsr223EvaluationConfigurationKeys.getScriptContext: () -> ScriptContext?
232
```
233
234
**Configuration Examples:**
235
236
```kotlin
237
import kotlin.script.experimental.jvmhost.jsr223.*
238
import javax.script.ScriptContext
239
240
// Host configuration with JSR-223 integration
241
val hostConfig = ScriptingHostConfiguration {
242
jsr223 {
243
getScriptContext = {
244
// Provide access to current script context
245
getCurrentScriptContext()
246
}
247
}
248
}
249
250
// Compilation configuration with automatic binding import
251
val compilationConfig = ScriptCompilationConfiguration {
252
jsr223 {
253
getScriptContext = { getCurrentScriptContext() }
254
importAllBindings = true // Import all context bindings as script properties
255
}
256
257
// Standard Kotlin scripting configuration
258
dependencies(JvmDependency(kotlinStdlib))
259
}
260
261
// Evaluation configuration with context access
262
val evaluationConfig = ScriptEvaluationConfiguration {
263
jsr223 {
264
getScriptContext = { getCurrentScriptContext() }
265
}
266
267
// Provide additional context variables
268
providedProperties(
269
"scriptContext" to ScriptContext::class
270
)
271
}
272
273
// Create engine with custom configuration
274
val customEngine = KotlinJsr223ScriptEngineImpl(
275
factory = KotlinJsr223DefaultScriptEngineFactory(),
276
baseCompilationConfiguration = compilationConfig,
277
baseEvaluationConfiguration = evaluationConfig
278
) { context ->
279
// Extract script arguments from context
280
val args = context.getBindings(ScriptContext.ENGINE_SCOPE)["args"] as? Array<String>
281
args?.let { ScriptArgsWithTypes(it, arrayOf(Array<String>::class)) }
282
}
283
```
284
285
## Context Property Integration
286
287
Functions for integrating JSR-223 context properties with Kotlin script compilation and evaluation.
288
289
### Context Configuration Functions
290
291
```kotlin { .api }
292
/**
293
* Configures provided properties from JSR-223 context for compilation
294
* @param context Script configuration refinement context
295
* @returns Updated compilation configuration or failure
296
*/
297
fun configureProvidedPropertiesFromJsr223Context(
298
context: ScriptConfigurationRefinementContext
299
): ResultWithDiagnostics<ScriptCompilationConfiguration>
300
301
/**
302
* Configures provided properties from JSR-223 context for evaluation
303
* @param context Script evaluation configuration refinement context
304
* @returns Updated evaluation configuration or failure
305
*/
306
fun configureProvidedPropertiesFromJsr223Context(
307
context: ScriptEvaluationConfigurationRefinementContext
308
): ResultWithDiagnostics<ScriptEvaluationConfiguration>
309
```
310
311
**Context Integration Example:**
312
313
```kotlin
314
import kotlin.script.experimental.jvmhost.jsr223.*
315
import javax.script.*
316
317
// Setup context with properties
318
val context = SimpleScriptContext()
319
val bindings = context.getBindings(ScriptContext.ENGINE_SCOPE)
320
bindings["database"] = DatabaseConnection("localhost:5432")
321
bindings["logger"] = LoggerFactory.getLogger("script")
322
bindings["config"] = mapOf("debug" to true, "maxRetries" to 3)
323
324
// Custom engine with automatic context property configuration
325
val contextEngine = KotlinJsr223ScriptEngineImpl(
326
factory = KotlinJsr223DefaultScriptEngineFactory(),
327
baseCompilationConfiguration = ScriptCompilationConfiguration {
328
refineConfiguration {
329
onAnnotations { context ->
330
// Automatically configure properties from JSR-223 context
331
configureProvidedPropertiesFromJsr223Context(context)
332
}
333
}
334
},
335
baseEvaluationConfiguration = ScriptEvaluationConfiguration {
336
refineConfiguration {
337
beforeEvaluation { context ->
338
// Configure evaluation properties from JSR-223 context
339
configureProvidedPropertiesFromJsr223Context(context)
340
}
341
}
342
}
343
) { scriptContext ->
344
// No special argument processing needed
345
null
346
}
347
348
contextEngine.context = context
349
350
// Script can now access context properties directly
351
val result = contextEngine.eval("""
352
// Properties from JSR-223 context are automatically available
353
logger.info("Starting script execution")
354
355
val users = database.query("SELECT * FROM users")
356
logger.info("Found ${'$'}{users.size} users")
357
358
if (config["debug"] as Boolean) {
359
println("Debug mode enabled")
360
println("Max retries: ${'$'}{config["maxRetries"]}")
361
}
362
363
users.size
364
""")
365
366
println("Script found ${result} users")
367
```
368
369
## Error Handling
370
371
JSR-223 integration provides comprehensive error handling that bridges Kotlin diagnostics with JSR-223 exceptions.
372
373
### Exception Translation
374
375
```kotlin
376
// JSR-223 exceptions are automatically translated from Kotlin diagnostics
377
try {
378
val result = engine.eval("invalid kotlin syntax !!!")
379
} catch (e: ScriptException) {
380
println("Script compilation error: ${e.message}")
381
println("Line number: ${e.lineNumber}")
382
println("Column number: ${e.columnNumber}")
383
384
// Access original Kotlin diagnostics if available
385
val kotlinDiagnostics = e.cause as? ScriptDiagnosticException
386
kotlinDiagnostics?.diagnostics?.forEach { diagnostic ->
387
println("Kotlin diagnostic: ${diagnostic.severity} - ${diagnostic.message}")
388
}
389
}
390
391
// Function invocation errors
392
try {
393
val result = engine.invokeFunction("nonExistentFunction", "arg")
394
} catch (e: NoSuchMethodException) {
395
println("Function not found: ${e.message}")
396
}
397
398
// Interface implementation errors
399
try {
400
val impl = engine.getInterface(Calculator::class.java)
401
if (impl == null) {
402
println("Cannot create interface implementation - required functions not defined")
403
}
404
} catch (e: ClassCastException) {
405
println("Interface implementation error: ${e.message}")
406
}
407
```
408
409
## Advanced Features
410
411
### Thread Safety
412
413
JSR-223 implementation provides thread-safe execution through proper synchronization and isolated state management.
414
415
```kotlin
416
import java.util.concurrent.*
417
418
val engine = manager.getEngineByExtension("kts") as KotlinJsr223InvocableScriptEngine
419
420
// Thread-safe concurrent execution
421
val executor = ForkJoinPool.commonPool()
422
val futures = (1..10).map { i ->
423
executor.submit(Callable {
424
val localContext = SimpleScriptContext()
425
localContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE)
426
localContext.setAttribute("threadId", i, ScriptContext.ENGINE_SCOPE)
427
428
engine.eval("""
429
println("Executing on thread ${'$'}threadId")
430
Thread.currentThread().name + " - " + threadId
431
""", localContext)
432
})
433
}
434
435
val results = futures.map { it.get() }
436
results.forEach { println("Result: $it") }
437
```
438
439
### Performance Optimization
440
441
```kotlin
442
// Reuse compiled scripts for better performance
443
val precompiledEngine = KotlinJsr223ScriptEngineImpl(
444
// Configuration optimized for repeated execution
445
baseCompilationConfiguration = ScriptCompilationConfiguration {
446
// Enable compilation caching
447
hostConfiguration(ScriptingHostConfiguration {
448
jvm {
449
compilationCache(FileBasedScriptCache(File("jsr223-cache")))
450
}
451
})
452
}
453
)
454
455
// Execute the same script multiple times efficiently
456
val scriptCode = """
457
fun factorial(n: Int): Long = if (n <= 1) 1 else n * factorial(n - 1)
458
factorial(args[0].toInt())
459
"""
460
461
val results = (1..10).map { n ->
462
val context = SimpleScriptContext()
463
context.setAttribute("args", arrayOf(n.toString()), ScriptContext.ENGINE_SCOPE)
464
precompiledEngine.eval(scriptCode, context)
465
}
466
467
println("Factorials: $results")
468
```