|:------------------------------------------------------:|
| β‘οΈ B o x L a n g β‘οΈ
| Dynamic : Modular : Productive
|:------------------------------------------------------:|
Copyright Since 2023 by Ortus Solutions, Corp
www.boxlang.io | www.ortussolutions.com
Β
This repository contains the core AWS Lambda Runtime for the BoxLang language. This runtime acts as a bridge between AWS Lambda's Java 21 runtime and BoxLang's dynamic language features, enabling BoxLang code execution in serverless environments.
β¨ Key Features:
- π― Automatic URI Routing - Route requests to specific BoxLang classes based on URI paths
- β‘ Performance Optimized - Class compilation caching and connection pooling
- π Multiple Event Sources - API Gateway, Function URLs, ALB, and direct invocations
- π§ͺ Developer Friendly - Hot reloading, comprehensive debugging, and local testing
π‘ For creating Lambda projects: Use our BoxLang AWS Lambda Template to quickly bootstrap new serverless applications.
The runtime consists of:
ortus.boxlang.runtime.aws.LambdaRunner- Main AWS Lambda RequestHandler- Dynamic Class Compilation - Compiles
.bxfiles on-demand with intelligent caching - Convention-based Execution - Executes
Lambda.bxfiles via therun()method - Flexible Response Handling - Supports both direct returns and response struct population
- Static Initialization - BoxLang runtime loads once per Lambda container
- URI-based Class Resolution - Automatically routes requests to specific BoxLang classes based on URI path
- Class Compilation -
.bxfiles are compiled and cached for performance - Method Resolution - Discovers target method via convention or
x-bx-functionheader - Application Lifecycle - Full Application.bx lifecycle with onRequestStart/End
- Response Marshalling - Converts BoxLang responses to Lambda-compatible JSON
The runtime supports automatic class routing based on incoming URI paths, making it easy to build multi-resource APIs without configuration.
When a request comes in, the runtime:
- Extracts the URI path from various event types (API Gateway, Function URLs, ALB)
- Converts the first path segment to PascalCase using BoxLang's built-in StringUtil
- Looks for a matching
.bxclass in the Lambda deployment root - Falls back to
Lambda.bxif no specific class is found
| Incoming URI | BoxLang Class | Description |
|---|---|---|
/products |
Products.bx |
Product management endpoints |
/customers |
Customers.bx |
Customer management endpoints |
/user-profiles |
UserProfiles.bx |
Handles hyphenated URIs |
/api_endpoints |
ApiEndpoints.bx |
Handles underscored URIs |
/orders/123 |
Orders.bx |
Routes based on first segment only |
/unknown/path |
Lambda.bx |
Falls back to default when class not found |
Simply create a .bx file with the PascalCase name of your resource:
// Products.bx - Handles all /products/* requests
class {
function run( event, context, response ) {
var httpMethod = event.requestContext?.http?.method ?: event.httpMethod ?: "GET";
var pathParameters = event.pathParameters ?: {};
switch( httpMethod ) {
case "GET":
if( structKeyExists( pathParameters, "id" ) ) {
return getProduct( pathParameters.id );
} else {
return getAllProducts();
}
break;
case "POST":
return createProduct( event.body );
break;
// ... handle other HTTP methods
}
}
private function getAllProducts() {
return {
"message": "Fetching all products",
"data": [
{ "id": 1, "name": "Product 1", "price": 29.99 }
]
};
}
private function getProduct( id ) {
return {
"message": "Fetching product ##" & id,
"data": { "id": id, "name": "Product " & id }
};
}
}
You can still use the x-bx-function header to call specific methods within your route classes:
# Call the 'run' method (default)
curl -X GET /products
# Call a custom method
curl -X GET /products -H "x-bx-function: getActiveProducts"URI routing works with all AWS event sources:
- API Gateway v1.0 (REST API) - Uses
pathfield - API Gateway v2.0 (HTTP API) - Uses
requestContext.http.pathfield - Lambda Function URLs - Uses
rawPathfield - Application Load Balancer - Uses
pathfield withrequestContext.elb - Direct Invocations - Falls back to
Lambda.bx
- π Zero Configuration - Just create
.bxfiles, no routing setup required - π Clean Organization - Separate classes for different resources/domains
- π Backward Compatible - Existing
Lambda.bxfiles continue to work - β‘ Performance Optimized - Classes are compiled once and cached
- π§ͺ Easy Testing - Test individual resource classes in isolation
- Java 21+ - Required for BoxLang runtime
- AWS CLI - For deployment and testing
- AWS SAM CLI - For local development and testing
- Docker - Required by SAM for local Lambda emulation
# Clone the runtime repository
git clone https://github.com/ortus-boxlang/boxlang-aws-lambda.git
cd boxlang-aws-lambda
# Build the runtime
./gradlew build shadowJar
# Create deployment packages
./gradlew buildMainZip buildTestZip
# Run tests
./gradlew test
# Local testing with SAM
sam local invoke bxFunction --event=workbench/sampleEvents/api.jsonRun comprehensive performance benchmarks:
# Execute performance test suite
./workbench/performance-test.sh
# Quick validation test
./workbench/simple-test.shThe main entry point implementing AWS Lambda's RequestHandler<Map<String, Object>, Object>:
- Static Initialization - BoxLang runtime loads once per container
- Class Caching - Compiled BoxLang classes cached via
ConcurrentHashMap - Performance Metrics - Debug timing for compilation and execution
- Connection Pooling - Configurable connection pool sizes
Runtime behavior is controlled via environment variables:
BOXLANG_LAMBDA_CLASS- Override defaultLambda.bxclass pathBOXLANG_LAMBDA_DEBUGMODE- Enable debug logging and performance metricsBOXLANG_LAMBDA_CONFIG- Custom BoxLang configuration path (default:/var/task/boxlang.json)BOXLANG_LAMBDA_CONNECTION_POOL_SIZE- Connection pool size (default: 2)LAMBDA_TASK_ROOT- Lambda deployment root (default:/var/task)
Key build tasks:
build- Builds, tests and packagesshadowJar- Creates fat JAR with all dependenciesbuildMainZip- Packages deployable Lambda runtime + sample + all.bxroute classesbuildTestZip- Creates test package for validationspotlessApply- Code formatting and linting
Note: The build system automatically includes all .bx files from src/main/resources/ in the deployment package to support URI routing.
The workbench/sampleEvents/ directory contains test payloads:
Core Events:
api.json- API Gateway integration eventevent.json- Simple Lambda eventhealth.json- Health check eventlarge-payload.json- Large payload stress test
URI Routing Examples:
products-get-all.json- GET/productsβ Routes toProducts.bxproducts-get-one.json- GET/products/123β Routes toProducts.bxwith ID parametercustomers-get-all.json- GET/customersβ Routes toCustomers.bxuser-profiles-test.json- GET/user-profilesβ Routes toUserProfiles.bx(hyphenated example)
Tests are located in src/test/java/ortus/boxlang/runtime/aws/:
- LambdaRunnerTest - Core runtime functionality
- Performance Tests - Class caching and optimization validation
- Integration Tests - Full Lambda lifecycle testing
# Test traditional Lambda.bx (fallback behavior)
sam local invoke bxFunction --event=workbench/sampleEvents/api.json
# Test URI routing to Products.bx
sam local invoke bxFunction --event=workbench/sampleEvents/products-get-all.json
# Test URI routing to Customers.bx
sam local invoke bxFunction --event=workbench/sampleEvents/customers-get-all.json
# Test URI routing with path parameters
sam local invoke bxFunction --event=workbench/sampleEvents/products-get-one.json
# Test hyphenated URI routing (user-profiles β UserProfiles.bx)
sam local invoke bxFunction --event=workbench/sampleEvents/user-profiles-test.json
# Test with debug logging
sam local invoke bxFunction --event=workbench/sampleEvents/products-get-all.json --debugThe runtime implements intelligent caching to avoid recompilation:
private static final ConcurrentHashMap<String, Class<?>> classCache = new ConcurrentHashMap<>();
private Class<?> getOrCompileLambda(String lambdaClassPath) {
return classCache.computeIfAbsent(lambdaClassPath, path -> {
// Compilation logic here
});
}When BOXLANG_LAMBDA_DEBUGMODE=true, the runtime logs:
- Compilation time vs cache retrieval
- Method execution duration
- Memory usage patterns
- Connection pool statistics
- Minimize Cold Start Impact - Keep static initialization lightweight
- Cache Aggressively - Store expensive computations in static variables
- Profile Memory Usage - Monitor CloudWatch logs for memory patterns
- Early Validation - Fail fast on invalid inputs to reduce execution time
# Build all artifacts
./gradlew clean build shadowJar buildMainZip buildTestZip
# Artifacts created in build/distributions/:
# - boxlang-aws-lambda-{version}-all.jar (fat JAR)
# - boxlang-aws-lambda-{version}.zip (deployable package)
# - boxlang-aws-lambda-test-{version}.zip (test package)- Development Branch - Versions append
-snapshot - Release Branches - Clean semantic versions
- Checksums - SHA-256 and MD5 generated for all artifacts
The runtime automatically handles BoxLang dependencies:
- Local Development - Uses
../boxlang/build/libs/boxlang-*.jarif available - CI/CD - Downloads dependencies to
src/test/resources/libs/ - Web Support - Includes
boxlang-web-supportfor HTTP utilities
- Fork & Clone - Create your development environment
- Feature Branch - Create branch from
development - Build & Test - Ensure all tests pass locally
- Performance Test - Run performance benchmarks
- Code Quality - Run
./gradlew spotlessApplyfor formatting - Pull Request - Target the
developmentbranch
- Java 21 - Use modern Java features appropriately
- BoxLang Integration - Follow BoxLang runtime patterns
- Performance First - Consider Lambda cold start implications
- Documentation - Update relevant docs and comments
- Testing - Add tests for new functionality
When working on URI routing features:
- Use BoxLang Built-ins - Leverage
ortus.boxlang.runtime.types.util.StringUtilfor string operations - Test All Event Types - Ensure compatibility with API Gateway v1/v2, Function URLs, and ALB
- Handle Edge Cases - Test with various URI patterns (hyphens, underscores, nested paths)
- Maintain Fallback - Always ensure
Lambda.bxfallback behavior works - Add Sample Events - Create corresponding test events in
workbench/sampleEvents/
- Enable Debug Mode - Set
BOXLANG_LAMBDA_DEBUGMODE=true - Check CloudWatch Logs - Look for compilation/execution metrics
- Local SAM Testing - Use
sam local invoke --debug - Unit Test Isolation - Create focused tests for specific issues
- Main Documentation - boxlang.ortusbooks.com
- AWS Lambda Guide - BoxLang Lambda Documentation
- IDE Tooling - Development Tools
- Lambda Template - bx-aws-lambda-template
- BoxLang Core - boxlang
- Web Support - boxlang-web-support
BoxLang is a modern, dynamic JVM language that can be deployed on multiple runtimes: operating system (Windows/Mac/*nix/Embedded), web server, lambda, iOS, android, web assembly, etc.
BoxLang Features:
- Be a rapid application development (RAD) scripting language and middleware.
- Unstagnate the dynamic language ecosystem in Java.
- Be dynamic, modular, lightweight, and fast.
- Be 100% interoperable with Java.
- Be modern, functional, and fluent (Think mixing CFML, Node, Kotlin, Java, and Clojure)
- Be able to support multiple runtimes and deployment targets:
- Native OS Binaries (CLI Tooling, compilers, etc.)
- MiniServer
- Servlet Containers - CommandBox/Tomcat/Jetty/JBoss
- JSR223 Scripting Engines
- AWS Lambda
- Microsoft Azure Functions (Coming Soon)
- Android/iOS Devices (Coming Soon)
- Web assembly (Coming Soon)
- Compile down to Java ByteCode
- Allow backward compatibility with the existing ColdFusion/CFML language.
- Great IDE, Debugger and Tooling: https://boxlang.ortusbooks.com/getting-started/ide-tooling
- Scripting (Any OS and Shebang) and REPL capabilities
Get professional support, training, and custom development services for your BoxLang applications:
- Professional Support and Priority Queuing
- Remote Assistance and Troubleshooting
You can find our docs here: https://boxlang.ortusbooks.com/
Apache License, Version 2.0.
This project is a professional open source project and is available as FREE and open source to use. Ortus Solutions, Corp provides commercial support, training and commercial subscriptions which include the following:
- Professional Support and Priority Queuing
- Remote Assistance and Troubleshooting
- New Feature Requests and Custom Development
- Custom SLAs
- Application Modernization and Migration Services
- Performance Audits
- Enterprise Modules and Integrations
- Much More
Β
"We β€οΈ Open Source and BoxLang" - Luis Majano
Please star us if this runtime helps you build amazing serverless applications with BoxLang!
A huge thanks to our sponsors who help us continue developing BoxLang and its ecosystem:
Made with β€οΈ by the BoxLang Team
Copyright Since 2023 by Ortus Solutions, Corp
Visit us at BoxLang.io Plans for more information.
To use it, you need to create a Lambda function and specify Java 21 as the runtime. The class that executes your BoxLang code is ortus.boxlang.runtime.aws.LambdaRunner. By convention it will execute a Lambda.bx file in the root (/var/task/Lambda.bx) of the Lambda function, via the run() method. The method signature can look like this:
// Lambda.bx
class{
function run( event, context, response ){
// Your code here
}
}- The
eventparameter is the event data that is passed to the Lambda function as aStruct. - The
contextparameter is the context object that is passed to the Lambda function. This matches the AWS Lambda context object:com.amazonaws.services.lambda.runtime.Context. - The
responseparameter is the response object that is passed to the Lambda function.
The response object is a Struct that you can use to set the response data. The response object has the following keys:
statusCode: The HTTP status code for the response.headers: AStructof headers to send in the response.body: The body of the response, which can be anything.
The BoxLang lambda runner will return the response object as the response to the Lambda function as a JSON object.
gradle shadowJar
gradle buildMainZip
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html
sam local invoke bxFunction --event=workbench/sampleEvents/api.json
sam local invoke bxFunction --event=workbench/sampleEvents/event.json
sam local invoke bxFunction --event=workbench/sampleEvents/api.json --debug
sam local invoke bxFunction --event=workbench/sampleEvents/event.json --debug
If you don't want to use the convention of Lambda.bx then you can setup an environment variable called BOXLANG_LAMBDA_CLASS with the full path to the BoxLang class that will execute your code. The class must have a run() method that matches the signature above.
You can enable debug mode by setting the environment variable BOXLANG_LAMBDA_DEBUG to true. This will output debug information to the Lambda logs.
Here is an example of a simple Lambda function that returns a Hello World response:
// Lambda.bx
class{
function run( event, context, response ){
// response.statusCode = 200; set by default
response.headers = {
"Content-Type" : "text/plain"
};
response.body = "Hello World";
}
}However, if you don't even want to deal with the response struct, you can just use a return and whatever you return will be placed for you in the response.body.
// Lambda.bx
class{
function run( event, context ){
return "Hello World";
}
}BoxLang is a professional open-source project and it is completely funded by the community and Ortus Solutions, Corp. Ortus Patreons get many benefits like a cfcasts account, a FORGEBOX Pro account and so much more. If you are interested in becoming a sponsor, please visit our patronage page: https://patreon.com/ortussolutions
"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" Jn 14:1-12
