| name | boxlang-runtime-jsr-223 |
| description | Use this skill when embedding BoxLang into Java applications via the JSR-223 scripting API, evaluating BoxLang code from Java, sharing data between Java and BoxLang via Bindings, building rules engines, template processors, or configurable logic using BoxLang as a scripting engine inside a JVM application. |
BoxLang JSR-223 Scripting
Overview
JSR-223 ("Scripting for the Java Platform") allows Java applications to embed
BoxLang as a scripting engine. This enables dynamic business logic, configurable
rules, template processing, and runtime extensibility without a full recompile.
Dependencies
Maven
<dependency>
<groupId>io.boxlang</groupId>
<artifactId>boxlang</artifactId>
<version>1.10.1</version>
</dependency>
Gradle
dependencies {
implementation 'io.boxlang:boxlang:1.10.1'
}
Requirement: Java 21+
Quick Start
import javax.script.*;
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "BoxLang" );
Object result = engine.eval( "return 'Hello from BoxLang!'" );
System.out.println( result );
Passing Data to BoxLang
Use Bindings to pass Java objects into the BoxLang execution context:
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "BoxLang" );
Bindings bindings = engine.createBindings();
bindings.put( "name", "Java Developer" );
bindings.put( "items", java.util.Arrays.asList( "Spring", "Maven", "BoxLang" ) );
Object result = engine.eval( """
message = "Hello " & name & "!"
itemCount = items.len()
return {
greeting: message,
totalItems: itemCount,
technologies: items.map( ( item ) => item.uCase() )
}
""", bindings );
System.out.println( result );
Retrieving Values from BoxLang
BoxLang can set values back into the Bindings scope for Java to read:
Bindings bindings = engine.createBindings();
bindings.put( "inputData", myData );
engine.eval( """
processed = inputData.map( ( item ) -> item * 2 )
errorCount = 0
successCount = processed.len()
""", bindings );
Object processed = bindings.get( "processed" );
int successCount = (int) bindings.get( "successCount" );
Rules Engine Pattern
Embed BoxLang for business rules that non-developers can modify:
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "BoxLang" );
String discountRules = Files.readString( Path.of( "rules/discount.bxs" ) );
Bindings ctx = engine.createBindings();
ctx.put( "customer", customerData );
ctx.put( "order", orderData );
Boolean eligible = (Boolean) engine.eval( discountRules, ctx );
rules/discount.bxs:
// Business rules — editable without recompiling Java
if ( order.total > 1000 && customer.tier == "GOLD" ) {
return true
}
if ( customer.loyaltyPoints > 5000 ) {
return true
}
return false
Template Processing Pattern
Use BoxLang string interpolation as a lightweight template engine:
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "BoxLang" );
String template = Files.readString( Path.of( "templates/email.bxs" ) );
Bindings data = engine.createBindings();
data.put( "firstName", "Alice" );
data.put( "orderNumber", "ORD-12345" );
data.put( "total", 99.99 );
String rendered = (String) engine.eval( template, data );
System.out.println( rendered );
templates/email.bxs:
return """
Dear #firstName#,
Your order #orderNumber# totaling $#numberFormat( total, "0.00" )# has been confirmed.
Thank you for your business!
"""
Performance: Reuse the Engine
ScriptEngineManager creates a new runtime per call. For production use,
create the engine once and reuse it:
private static final ScriptEngine BOXLANG_ENGINE =
new ScriptEngineManager().getEngineByName( "BoxLang" );
public Object evaluate( String script, Map<String, Object> vars ) throws ScriptException {
Bindings bindings = BOXLANG_ENGINE.createBindings();
bindings.putAll( vars );
return BOXLANG_ENGINE.eval( script, bindings );
}
BoxLang Home Configuration
Control where BoxLang stores its runtime files (classes, modules, config):
System.setProperty( "boxlang.home", "/opt/myapp/.boxlang" );
ScriptEngine engine = new ScriptEngineManager().getEngineByName( "BoxLang" );
Or via environment variable before JVM startup:
export BOXLANG_HOME=/opt/myapp/.boxlang
java -jar myapp.jar
Loading BoxLang Modules
Modules extend BoxLang with BIFs, components, and capabilities:
System.setProperty( "boxlang.home", "/opt/myapp/.boxlang" );
Or set in boxlang.json in the home directory:
{
"modules": {
"load": [ "bx-mail", "bx-pdf" ]
}
}
Exception Handling
BoxLang exceptions are wrapped in ScriptException. Unwrap to inspect:
try {
engine.eval( script, bindings );
} catch ( ScriptException e ) {
Throwable cause = e.getCause();
if ( cause != null ) {
System.err.println( "BoxLang error: " + cause.getMessage() );
} else {
System.err.println( "Script error: " + e.getMessage() );
}
}
Core JSR-223 Classes Reference
| Class | Purpose |
|---|
ScriptEngineManager | Discovers and creates script engines |
ScriptEngine | Executes scripts, manages state |
Bindings | Key-value map for passing data to/from scripts |
ScriptContext | Full context (global + engine-level Bindings) |
Compilable | Compile scripts for repeated execution (if supported) |
Invocable | Call specific functions defined in the engine |
Production Checklist