JSR-223 Scripting
Integrate BoxLang into Java applications using JSR-223 Scripting

🚀 Getting Started for Java Developers
JSR 223, also known as "Scripting for the Java Platform," enables seamless integration between Java applications and scripting languages like BoxLang. This guide shows Java developers how to embed BoxLang's dynamic capabilities directly into their applications.
📋 Table of Contents
📦 Adding BoxLang to Your Project
Maven Dependency
Add BoxLang to your Maven project's pom.xml:
Gradle Dependency
For Gradle projects, add to your build.gradle:
Direct JAR Download
Download the latest BoxLang JAR from:
Add the JAR to your project's classpath:
System Requirements
Java 21+ (BoxLang requires JDK 21 or later)
JSR-223 Support (included in standard Java installations)
🏗️ Quick Start Example
Here's a complete Java application demonstrating BoxLang integration:
🔧 Architecture Overview
BoxLang offers complete JSR-223 compliance for seamless integration with JVM applications. Understanding the core components helps Java developers leverage BoxLang effectively.
💡 Common Use Cases for Java Developers
Configuration & Rules Engine
Template Processing
Data Transformation
📚 Core Scripting Classes
The BoxLang scripting package can be found here: ortus.boxlang.runtime.scripting. The classes that will assist you are:
BoxCompiledScript- Implements the JSRCompiledScriptinterface (https://docs.oracle.com/en/java/javase/17/docs/api/java.scripting/javax/script/CompiledScript.html)BoxScopeBindings- Implements the JSRBindingsinterface (https://docs.oracle.com/en/java/javase/17/docs/api/java.scripting/javax/script/Bindings.html)BoxScriptingContext- Implements the JSRScriptContextinterface (https://docs.oracle.com/en/java/javase/17/docs/api/java.scripting/javax/script/ScriptContext.html)BoxScriptingEngine- Implements the JSRScriptEngineandCompilablehttps://docs.oracle.com/en/java/javase/17/docs/api/java.scripting/javax/script/ScriptEngine.html https://docs.oracle.com/en/java/javase/17/docs/api//java.scripting/javax/script/Compilable.htmlBoxScriptingFactory- implements the JSRScriptEngineFactoryhttps://docs.oracle.com/en/java/javase/17/docs/api/java.scripting/javax/script/ScriptEngineFactory.html
Definitions
Script Factory - creates scripting engines and gets metadata about scripting engines.
Script Engine - provides a way to create bindings, scripts, and run statements.
Invocable - Our BoxLang engine also implements the scripting
Invocableinterface so you can declare functions and classes (coming soon) and then execute them from the calling language.Bindings - these are like scopes to BoxLang. The bridge between Java and BoxLang
Scripting Context - Like the BoxLang context object, it provides scope lookups and access to bindings.
Bindings
Bindings are under the hood HashMaps. They are used to bind your Java code to the BoxLang code. By default, in BoxLang, we provide three scopes you can bind bindings to:
Engine Scope- The default scope which maps to the BoxLangvariablesscopeRequest Scope- The JSR request scope maps to the BoxLangrequestscopeGlobal Scope- The JSR global scope maps to the BoxLangserverscope
Discovering Engines
To find out what engines are available in your platform you can run the following:
BoxLang ScriptEngine
To get started, you need to get an instance of the BoxLang Scripting Engine. You can do so by using the Java ScriptEngineManager() class or importing our BoxScriptingEngine class.
You can also cast it to our class to get enhanced methods and functionality:
Debug Mode
If you ever need to send debugging information to the console from the BoxRuntime in the scripting engine, you can create a new script engine and pass the debug flag to it.
This will start up the BoxRuntime in debug mode.
🏠 BoxLang Home Configuration
Default BoxLang Home
When you create a BoxLang scripting engine, it initializes a BoxLang runtime instance that uses a home directory for configuration and modules. By default, BoxLang uses:
For example:
Linux/macOS:
/home/username/.boxlang/or/Users/username/.boxlang/Windows:
C:\Users\username\.boxlang\
Custom Home Directory
You can configure a custom BoxLang home directory using system properties or environment variables:
Runtime Configuration
The BoxLang home directory contains:
config/boxlang.json- Runtime configuration filelib/- Custom modules and librarieslogs/- Runtime log files (if file logging is enabled)
You can customize the runtime behavior by modifying the boxlang.json configuration file:
Multiple Runtime Instances
For applications requiring isolated BoxLang environments, you can create separate instances:
Configuration Override
You can also override specific configuration settings using system properties or environment variables by prefixing with boxlang. or BOXLANG_:
Eval() BoxLang Code
Once you access the script engine, you can use the plethora of eval() methods to execute the BoxLang source and bind with specific dynamic bindings. You can execute scripts from strings or reader objects. You can also compile a script/class into a CompiledScript and then execute it at a later point in time via the compile() methods.
You can use eval with the following signatures
Bindings - Passing Data to the Scripts
Data can be passed into the engine by defining a Bindings object and passing it as a second parameter to the eval function. You will do so by using the createBindings() method. If you casted the engine to our BoxScriptingEngine class, you will also get a createBindings( Map m ) so you can quickly create bindings from a map of data.
Once you bind the engine with bindings before execution, you must get the modified bindings via the engine.getBindings() method. If you don't do this, you will only have access to the simple hashmap to bind the engine.
Calling Functions From Java to BoxLang
You can also use the eval() method to define functions, closures, or lambdas in BoxLang and execute them in your host language. We do so by evaluating the script, casting the engine to Invocable, and using the invokeFunction() method.
Objects, Functions, Closures, Lambdas, Member Methods
You can also use the invokeMethod( object, name, args ) function, which allows you to target a specific object, such as a BoxLang class, member method, struct, lambda, closure or collection of functions.
This is indeed truly powerful as you can not only invoke functions on objects, but also member methods in any valid BoxLang type.
Compiling Scripts
Apart from executing strings, you can also compile BoxLang scripts and evaluate them using the compileScript( String ) or compileScript( Reader ) methods. You will get a Box CompiledScript class, which you can then use the eval() methods and binding methods at a later point in time.
Dynamic Interfaces
JSR223 also allows you to dynamically create interface proxies for any functions or classes you map in the dynamic language. Let's say you want to create a nice BoxLang function that maps to a Java Runnable. In our example, we will create the run function and then map that via JSR223 to the Runnable interface so we can execute it as a runnable object.
As you can see from the sample above, you can use the getInterface( class<?> ) method to map the evaluated code to any interface of your choosing. Here are the two methods you can use for interfaces:
getInterface( Class<T> )- Build a dynamic proxy from the evaluated function and the passed in classgetInterface( Object, Class<T> )- Build a dynamic proxy from the passed inObjectand the passed in class.
Let's finish this section with another example. Using a struct and anonymous functions, let's build a BoxLang virtual object and treat it as a Runnable interface.
Capturing Output
We have also added the capability for your host language to seed your own String Writers into the engine so you can capture output. BoxLang can produce two types of output
System output - Bifs and components that send output to the
System.outBuffer output - A BoxLang request has an output String buffer that can be used to produce output which can be sent to console, web, etc.
Runtime Source Code
The runtime source code can be found here: https://github.com/ortus-boxlang/BoxLang/tree/development/src/main/java/ortus/boxlang/runtime/scripting
We welcome any pull requests, testing, docs, etc.
🏭 Production Considerations
Performance Optimization
Thread Safety
Error Handling
🔗 Integration Patterns
Spring Framework Integration
Maven Build Integration
Gradle Build Integration
Last updated
Was this helpful?

