Skip to content

ortus-boxlang/boxlang-starter-aws-lambda

Repository files navigation

⚑ BoxLang AWS Lambda Template

|:------------------------------------------------------:|
| ⚑︎ B o x L a n g ⚑︎
| Dynamic : Modular : Productive
|:------------------------------------------------------:|
Copyright Since 2023 by Ortus Solutions, Corp
www.boxlang.io | www.ortussolutions.com

Β 

πŸš€ Production-ready template for building and deploying BoxLang applications to AWS Lambda. This template provides a complete Java-BoxLang hybrid runtime with Gradle build automation, comprehensive testing, and AWS SAM deployment scripts.

πŸ—οΈ Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   AWS Lambda    β”‚    β”‚  LambdaRunner    β”‚    β”‚  BoxLang App    β”‚
β”‚    Runtime      │───▢│  (Java Wrapper)  │───▢│  (Lambda.bx)    β”‚
β”‚   (Java 21)     β”‚    β”‚                  β”‚    β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                       β”‚                       β”‚
         β–Ό                       β–Ό                       β–Ό
  Handler Invocation    Event Processing        Business Logic
  Context Management    Response Formatting     Application Lifecycle

Key Components:

  • πŸ“¦ BoxLang AWS Lambda Runtime: Maven dependency io.boxlang:boxlang-aws-lambda:1.4.0
  • 🎯 Lambda Handler: ortus.boxlang.runtime.aws.LambdaRunner::handleRequest
  • πŸ“ BoxLang Code: Lives in src/main/bx/ (Lambda.bx, Application.bx)
  • βš™οΈ Java Wrapper: Gradle build system with shadow JAR packaging
  • πŸ—οΈ Deployment: ZIP artifact for AWS Lambda with SAM template

The main lambda code is located in src/main/bx/Lambda.bx and the test code is located in src/test/java/com/myproject.

πŸš€ Quick Start

Prerequisites

  • β˜• Java 21+ (required for runtime)
  • πŸ”§ AWS CLI (for deployment)
  • πŸ—οΈ SAM CLI (for local testing)

Get Started in 2 Steps

  1. πŸ§ͺ Run tests to verify setup:

    ./gradlew test
  2. πŸ“¦ Build deployment package:

    ./gradlew build

Your deployable ZIP will be created at build/distributions/boxlang-aws-project-<version>.zip

πŸ”₯ Deploy to AWS

1️⃣ Setup Configuration

Copy the config template and customize for your environment:

cp workbench/config.env workbench/config.local.env
# Edit config.local.env with your settings

Key settings:

# BoxLang Lambda Deployment Configuration
# Copy this file to config.local.env and customize for your environment

# S3 Bucket for Lambda artifacts (required)
# Must be globally unique, 3-63 characters, lowercase letters/numbers/hyphens only
AWS_LAMBDA_BUCKET=my-boxlang-lambda-artifacts

# AWS Region (optional - uses your default AWS region if not set)
AWS_REGION=us-east-1

# CloudFormation Stack Name (optional - defaults to 'boxlang-lambda-stack')
STACK_NAME=my-boxlang-lambda

# Lambda Function Name for direct invocation (optional)
# Use this to invoke by function name instead of looking up via stack
FUNCTION_NAME=my-boxlang-lambda

# Lambda Function Configuration (optional)
LAMBDA_MEMORY=128
LAMBDA_TIMEOUT=15

# Deployment Environment (optional)
ENVIRONMENT=dev

2️⃣ Create S3 Bucket

./workbench/1-create-bucket.sh

3️⃣ Deploy Lambda

./workbench/2-deploy.sh

This will:

  • Build your BoxLang project
  • Upload to S3
  • Deploy via CloudFormation with your configured parameters
  • Show function name and settings

4️⃣ Test Your Lambda

./workbench/3-invoke.sh

πŸ’‘ Pro Tip: The deployment scripts automatically use your configuration from config.local.env β†’ config.env β†’ environment variables and the workbench/sampleEvents/event-live.json

πŸ€– CI/CD Workflows

This template includes complete GitHub Actions workflows for automated testing, building, and deployment. All workflows are production-ready and can be used immediately.

πŸ“‹ Available Workflows

πŸ§ͺ Test Workflow (.github/workflows/tests.yml)

Purpose: Reusable testing workflow with comprehensive validation

Features:

  • β˜• Java 21 setup with caching
  • πŸ” Full test suite execution via Gradle
  • πŸ“Š Test reports as workflow artifacts
  • πŸ”„ Reusable across multiple workflows

Usage: Automatically called by other workflows or can be triggered manually

πŸš€ Release Workflow (.github/workflows/release.yml)

Purpose: Complete build, test, and optional AWS deployment pipeline

Features:

  • πŸ—οΈ Full build with shadow JAR and Lambda ZIP creation
  • πŸ§ͺ Test execution via reusable test workflow
  • πŸ“¦ Build artifacts uploaded (ZIP, JAR, test reports)
  • πŸ”§ AWS Lambda deployment (commented out, ready to enable)
  • πŸ“€ S3 distribution upload (commented out, ready to enable)
  • 🏷️ GitHub release creation (commented out, ready to enable)

Triggers:

  • Push to main branch
  • Manual workflow dispatch

πŸ’‘ AWS Deployment: Ready-to-use Lambda function updates:

# Uncomment these lines in .github/workflows/release.yml for AWS deployment:

- name: Update AWS Lambda Function
  uses: kazimanzurrashid/aws-lambda-update-action@v2.0.3
  with:
    zip-file: "./build/distributions/${{ env.PROJECT_NAME }}-${{ env.VERSION }}.zip"
    lambda-name: ${{ env.PROJECT_NAME }}-${{ env.DEPLOY_TIER }}
  env:
    AWS_REGION: ${{ secrets.AWS_REGION }}
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_PUBLISHER_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_PUBLISHER_KEY }}

⚠️ Important: You must create the Lambda function FIRST (using the workbench scripts), then uncomment the AWS deployment workflow to enable automatic function updates on releases.

πŸ“Έ Snapshot Workflow (.github/workflows/snapshot.yml)

Purpose: Development builds and testing for non-release branches

Features:

  • πŸ”§ Development builds with snapshot versioning
  • πŸ§ͺ Test execution for validation
  • πŸ“¦ Snapshot artifacts for testing
  • 🌿 Branch-based development workflow

Triggers:

  • Push to any branch except main
  • Pull requests

πŸ› οΈ Setting Up CI/CD

1. GitHub Secrets (for AWS deployment)

Add these secrets to your GitHub repository (Settings β†’ Secrets and variables β†’ Actions):

AWS_REGION                    # e.g., us-east-1
AWS_PUBLISHER_KEY_ID         # AWS Access Key ID
AWS_SECRET_PUBLISHER_KEY     # AWS Secret Access Key

2. Enable AWS Deployment

  1. Deploy function first using workbench scripts:

    ./workbench/1-create-bucket.sh
    ./workbench/2-deploy.sh
  2. Uncomment AWS deployment in .github/workflows/release.yml

  3. Push to main or trigger workflow manually

3. Workflow Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Push to main   β”‚    β”‚  Release Flow   β”‚    β”‚  AWS Lambda     β”‚
β”‚  (or manual)    │───▢│   β€’ Build       │───▢│   β€’ Update      β”‚
β”‚                 β”‚    β”‚   β€’ Test        β”‚    β”‚   β€’ Deploy      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚   β€’ Package     β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                               β”‚
                               β–Ό
                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                       β”‚   Artifacts     β”‚
                       β”‚   β€’ Lambda ZIP  β”‚
                       β”‚   β€’ Shadow JAR  β”‚
                       β”‚   β€’ Test Reportsβ”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Pro Tip: The workflows are designed for zero-configuration operation. Just create your GitHub repository, add AWS secrets if needed, and push code. The CI/CD pipeline handles the rest!

πŸ“ Directory Structure

Here is a comprehensive overview of the project structure:

πŸ—‚οΈ Root Files & Folders

File/Folder Required In Git Description
πŸ“ build/ ❌ ❌ Temporary build assets (generated by Gradle)
πŸ“ gradle/ βœ… βœ… Gradle wrapper and configuration
πŸ“ src/ βœ… βœ… Your module source code
πŸ“ workbench/ βœ… βœ… AWS deployment scripts and SAM template
πŸ“„ .cfformat.json ❌ βœ… CFFormat configuration (Ortus Standards)
πŸ“„ .editorconfig ❌ βœ… Editor consistency settings
πŸ“„ .gitattributes ❌ βœ… Git attributes
πŸ“„ .gitignore βœ… βœ… Git ignore patterns
πŸ“„ .markdownlint.json ❌ βœ… Markdown linting rules
πŸ“„ .ortus-java-style.xml ❌ βœ… Java style guide (IntelliJ/VSCode/Eclipse)
πŸ“„ box.json βœ… βœ… BoxLang dependencies and automations
πŸ“„ build.gradle βœ… βœ… Gradle build configuration
πŸ“„ changelog.md ❌ βœ… Version history tracking
πŸ“„ gradlew βœ… βœ… Gradle wrapper (Linux/macOS)
πŸ“„ gradlew.bat βœ… βœ… Gradle wrapper (Windows)
πŸ“„ settings.gradle βœ… βœ… Gradle project settings

πŸ“ Legend: βœ… = Required/Included, ❌ = Optional/Excluded

πŸ“‚ Source Directory (src/)

  • πŸ§‘β€πŸ’» main/ - Production source code
    • bx/ - BoxLang source files
      • Application.bx - Application lifecycle hooks and configuration
      • Lambda.bx - Your Lambda entry point (implements run(event, context, response))
      • (Add your BoxLang classes here)
  • πŸ§ͺ test/ - Test source code
    • java/com/myproject/ - JUnit test classes
      • LambdaIntegrationTest.java - Comprehensive Lambda integration tests
      • mocks/TestContext.java - Mock AWS Lambda Context
      • mocks/TestLogger.java - Test logging utilities
      • runner/LocalLambdaRunner.java - Local Lambda test runner
  • πŸ—‚οΈ resources/ - Runtime resources
    • βš™οΈ boxlang.json - BoxLang runtime configuration
    • πŸ“¦ boxlang_modules/ - Local BoxLang modules (auto-packaged)
    • πŸ”§ libs/ - Any non-maven managed Jars that you want to include in your project

πŸ”¬ Workbench Directory (workbench/)

The workbench provides a complete AWS deployment and testing workflow:

πŸ“‹ Core Scripts

  • πŸ› οΈ 0-check-aws.sh - AWS credentials troubleshooter (diagnoses configuration issues)
  • πŸͺ£ 1-create-bucket.sh - Creates S3 bucket for deployment artifacts
  • πŸš€ 2-deploy.sh - Builds and deploys Lambda via SAM/CloudFormation
  • πŸ“ž 3-invoke.sh - Invokes deployed Lambda with test payloads
  • 🧹 4-cleanup.sh - Cleanup deployment resources and stack

βš™οΈ Configuration

  • πŸ“ config.env - Default configuration template (copy to config.local.env)
  • πŸ” config.local.env - Your local settings (gitignored)

🎯 Templates & Events

  • πŸ“‹ template.yml - SAM template for AWS deployment (parameterized)
  • πŸ§ͺ template-local.yml - SAM template for local development with HTTP endpoints
  • πŸ“„ event-live.json - Production test payload for Lambda invocation
  • πŸ“ sampleEvents/ - Sample events (API Gateway, S3, etc.)

πŸ’» Lambda Development Guide

🎯 Writing Your Lambda Function

Your main Lambda logic goes in src/main/bx/Lambda.bx. The entry point must be named run:

/**
 * Lambda Entry Point
 * Convention: run(event, context, response)
 */
class {
    function run( event, context, response ) {
        response.body = {
            "error": false,
            "messages": [],
            "data": "Hello from BoxLang Lambda! Event: " & event.toString()
        }
        response.statusCode = 200
    }

    // Alternative function (call with x-bx-function header)
    function anotherFunction( event, context, response ) {
        return "Alternative lambda function!"
    }
}

πŸ“‹ Function Parameters

  • event: AWS Lambda event object (API Gateway, S3, etc.)
  • context: AWS Lambda context (com.amazonaws.services.lambda.runtime.Context)
  • response: Response object with standard structure:
    • statusCode - HTTP status (default: 200)
    • headers - HTTP headers map/struct
    • body - Response payload (your data goes here)
    • cookies - Array of response cookies

πŸ”§ Application Lifecycle

Use src/main/bx/Application.bx for initialization and request processing:

class {
    this.name = "My-AWS-Lambda"

    function onApplicationStart() {
        // Initialize databases, caches, etc.
        return true;
    }

    function onRequestStart( targetPage ) {
        // Per-request initialization
        return true;
    }
}

βš™οΈ Configuration

πŸ”§ Project Properties

Project Name: Defined in settings.gradle

rootProject.name = 'boxlang-aws-project'

Versions: Configured in gradle.properties and build.gradle

# gradle.properties
version=1.0.0
jdkVersion=21
boxlangVersion=1.0.0

πŸŽ›οΈ BoxLang Runtime Configuration

Configure BoxLang behavior in src/resources/boxlang.json:

{
  "debugMode": false,          // Enable for development
  "trustedCache": true,        // Enable for production
  "requestTimeout": "0,0,15,0", // 15 minute timeout (matches AWS Lambda)
  "timezone": "${env:TZ:UTC}",  // Use TZ environment variable or UTC
  "logging": {
    "rootLevel": "WARN",       // ERROR, WARN, INFO, DEBUG, TRACE
    "loggers": {
      "runtime": { "level": "INFO", "appender": "console" }
    }
  }
}

Key Settings for AWS Lambda:

  • πŸ”’ trustedCache: true - Enables class caching (recommended for production)
  • πŸ• requestTimeout - Should match your Lambda timeout
  • 🌍 timezone - Use ${env:TZ:UTC} to respect Lambda environment
  • πŸ“ logging.*.appender: "console" - Required for CloudWatch logs

πŸ“¦ BoxLang Modules

πŸ”Œ Adding Modules

Method 1: CommandBox CLI

You can leverage the CommandBox CLI to install BoxLang modules easily.

# Install to src/resources/boxlang_modules/
box install {moduleName} --production --directory=src/resources/boxlang_modules

Method 2: Via box.json

CommandBox will read your box.json file for module dependencies. This is a durable way to manage your dependencies.

{
  "dependencies": {
    "bx-pdf": "^1.0.0",
	"bx-mysql": "^1.0.0"
  },
  "installPaths": {
    "bx-pdf": "src/resources/boxlang_modules/bx-pdf",
	"bx-mysql": "src/resources/boxlang_modules/bx-mysql"
  }
}

Then run:

box install --production

Remember that these dependencies should not be added to your source control (e.g., Git).

Method 3: BoxLang Module Installer

The BoxLang module installer is an OS level CLI tool that is used to install modules easily without CommandBox. Eventually, this tool and CommandBox will merge, but it is here for reference.

cd src/resources
install-bx-module <module-name> --local

πŸ“‚ Module Structure

Modules are automatically packaged into your deployment ZIP:

build/distributions/your-lambda.zip
β”œβ”€β”€ Lambda.bx
β”œβ”€β”€ boxlang.json
β”œβ”€β”€ lib/
β”‚   └── (jars)
└── boxlang_modules/          # ← Your modules go here
    β”œβ”€β”€ bx-pdf/
    └── bx-mysql/

πŸ”¨ Build System & Tasks

πŸš€ Essential Commands

Development Workflow:

# 1. Run tests
./gradlew test

# 2. Build deployment package
./gradlew build

# 3. Deploy to AWS
./workbench/2-deploy.sh

πŸ“‹ All Available Tasks

Task Description Output
πŸ—οΈ build Full build lifecycle (clean, compile, test, package) build/distributions/*.zip
🧹 clean Delete build artifacts and temporary files -
β˜• compileJava Compile Java source files build/classes/java/main/
πŸ§ͺ compileTestJava Compile Java test files build/classes/java/test/
πŸ“Š dependencyUpdates Check for newer dependency versions Console report
πŸ”— shadowJar Create uber-JAR with all dependencies build/distributions/
🎁 buildLambdaZip Package Lambda deployment ZIP build/distributions/*.zip
πŸ“„ jar Create standard JAR (without dependencies) build/libs/
πŸ“š javadoc Generate Java API documentation build/docs/javadoc/
πŸ§ͺ test Run JUnit tests build/reports/tests/
🏠 runLocal Run Lambda locally with default event Console output
🌐 runLocalApi Run Lambda locally with API Gateway event Console output
πŸ”§ runLocalLegacy Run Lambda locally with legacy API event Console output
🌍 startSamServer Start SAM local API server (foreground) HTTP server at :3000
πŸ”„ startSamServerBackground Start SAM local API server (background) HTTP server at :3000
πŸ›‘ stopSamServer Stop background SAM server -
✨ spotlessApply Auto-format source code -
πŸ” spotlessCheck Check code formatting -
πŸ“‹ tasks List all available Gradle tasks -

🎯 Key Build Outputs

build/distributions/
β”œβ”€β”€ boxlang-aws-project-1.0.0.zip     # πŸš€ Deploy this to AWS Lambda
β”œβ”€β”€ boxlang-aws-project-1.0.0-all.jar # πŸ“¦ Shadow JAR (uber-JAR)
└── boxlang-aws-project-1.0.0/        # πŸ“ Unpacked contents
    β”œβ”€β”€ Lambda.bx                      # Your BoxLang entry point
    β”œβ”€β”€ boxlang.json                   # Runtime configuration
    β”œβ”€β”€ lib/                          # All Java dependencies
    └── boxlang_modules/              # BoxLang modules

πŸ§ͺ Testing

🎯 Test Structure

src/test/java/com/myproject/
β”œβ”€β”€ LambdaIntegrationTest.java    # Comprehensive integration tests
β”œβ”€β”€ mocks/
β”‚   β”œβ”€β”€ TestContext.java         # Mock AWS Lambda Context
β”‚   └── TestLogger.java          # Test logging utilities
└── runner/
    └── LocalLambdaRunner.java   # Local Lambda test runner

βœ… Running Tests

# Run all tests
./gradlew test

# Run specific test class
./gradlew test --tests "com.myproject.LambdaIntegrationTest"

# Run with detailed output
./gradlew test --info

πŸ“Š Test Reports

After running tests, view results at:

  • πŸ“„ HTML Report: build/reports/tests/test/index.html
  • πŸ“Š XML Results: build/test-results/test/

πŸ§ͺ Sample Test

@Test
@DisplayName("Test Lambda.bx execution")
public void testValidLambda() throws IOException {
    Path validPath = Path.of("src", "main", "bx", "Lambda.bx");
    LambdaRunner runner = new LambdaRunner(validPath, true);
    Context context = new TestContext();

    var event = new HashMap<String, Object>();
    event.put("name", "Ortus Solutions");
    event.put("when", Instant.now().toString());

    IStruct response = runner.handleRequest(event, context);

    assertThat(response.getAsInteger(Key.of("statusCode"))).isEqualTo(200);
}

🏠 Local Testing

Test your Lambda locally without deploying to AWS:

πŸš€ Quick Local Testing

# Test locally with default event
./gradlew runLocal

# Test with API Gateway event
./gradlew runLocalApi

# Test with custom event file
./gradlew runLocal -PeventFile=workbench/sampleEvents/s3-event.json

🌐 SAM Local Development Server

If you have SAM CLI installed:

# Start local API server (HTTP endpoint testing)
./workbench/5-test-local.sh

This creates a local HTTP endpoint at http://localhost:3000 where you can:

  • Send HTTP requests directly to your Lambda
  • Test API Gateway integration locally
  • Debug with hot reload capabilities

πŸ“ Available Sample Events

workbench/sampleEvents/
β”œβ”€β”€ api.json         # API Gateway HTTP v2.0 event
β”œβ”€β”€ api-post.json    # POST request with JSON body
β”œβ”€β”€ event.json       # Legacy API Gateway event
β”œβ”€β”€ event-live.json  # Production test payload (used by 3-invoke.sh)
β”œβ”€β”€ event-local.json # Local development test payload
└── s3-event.json    # S3 bucket notification event

πŸ”§ Local Test Runner Features

The built-in LocalLambdaRunner provides:

  • ⚑ Fast execution - No deployment required
  • πŸ“Š Performance metrics - Shows execution time
  • πŸ” JSON output formatting - Pretty-printed responses
  • πŸ“„ Multiple event support - Easy event switching
  • ❌ Error handling - Clear error messages with stack traces

πŸ§ͺ Enhanced Integration Tests

The LambdaIntegrationTest suite includes:

  • Basic Lambda execution - Validates core functionality
  • API Gateway simulation - Tests HTTP request/response handling
  • Complex nested data - Handles rich JSON payloads
  • Performance testing - Large payload stress testing (5-second timeout)
  • Error handling - Null value and edge case testing
  • Mock AWS Context - Realistic Lambda environment simulation

Test scenarios covered:

@Test void testBasicExecution()        // Core Lambda functionality
@Test void testApiGatewayEvent()       // HTTP API simulation
@Test void testComplexEvent()          // Nested JSON structures
@Test void testLargePayload()          // Performance validation
@Test void testNullHandling()          // Edge case testing

🌐 SAM Local HTTP Server

For HTTP endpoint testing, start a local API Gateway simulation:

Background Server (Recommended for Development):

# Start server in background
./gradlew startSamServerBackground

# Your Lambda is now available at http://localhost:3000
curl http://localhost:3000
curl -X POST http://localhost:3000 -d '{"test":"data"}' -H 'Content-Type: application/json'

# Stop when done
./gradlew stopSamServer

Foreground Server:

# Start server in foreground (blocks terminal)
./gradlew startSamServer
# Press Ctrl+C to stop

Test Endpoints:

# Manual testing examples with curl
curl http://localhost:3000
curl -X POST http://localhost:3000/api/users \
  -H 'Content-Type: application/json' \
  -d '{"name":"John","email":"john@example.com"}'

# Or use your favorite HTTP client:
# - Postman
# - Insomnia
# - HTTPie: http POST localhost:3000/api/users name=John email=john@example.com

Development Workflow:

  1. πŸš€ ./gradlew startSamServerBackground - Start server
  2. ✏️ Edit src/main/bx/Lambda.bx - Make changes
  3. πŸ”„ ./gradlew build - Rebuild (server auto-reloads)
  4. πŸ§ͺ curl http://localhost:3000 - Test changes
  5. πŸ” Repeat steps 2-4 for rapid development

Requirements:

  • SAM CLI installed: brew install aws-sam-cli
  • AWS credentials configured (can use dummy values for local testing)

πŸš€ AWS Deployment

πŸ› οΈ Deployment Scripts

The workbench/ directory provides complete deployment automation:

Script Purpose Requirements
πŸͺ£ 1-create-bucket.sh Create S3 bucket for artifacts, skip if defined already AWS CLI configured
πŸš€ 2-deploy.sh Build & Deploy via CloudFormation S3 bucket must exist & AWS CLI Configured
πŸ“ž 3-invoke.sh Test deployed Lambda Lambda deployed
🧹 4-cleanup.sh Remove AWS resources -

πŸ“‹ SAM Template

The deployment uses workbench/template.yml with configurable parameters:

Parameters:
  LambdaMemorySize:
    Type: Number
    Default: 128
    Description: Memory allocated to the Lambda function (MB)

  LambdaTimeout:
    Type: Number
    Default: 15
    Description: Lambda function timeout (seconds)

  Environment:
    Type: String
    Default: "dev"
    Description: Deployment environment (dev, staging, prod)

Resources:
  bxFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: build/distributions/boxlang-aws-project-1.0.0.zip
      Handler: ortus.boxlang.runtime.aws.LambdaRunner::handleRequest
      Runtime: java21
      Timeout: !Ref LambdaTimeout
      MemorySize: !Ref LambdaMemorySize
      Environment:
        Variables:
          ENVIRONMENT: !Ref Environment
          BOXLANG_DEBUG: "false"

Outputs:
  FunctionName:
    Description: "BoxLang Lambda Function Name"
    Value: !Ref bxFunction

πŸ’‘ Configuration: The deploy script passes your config.local.env values as CloudFormation parameters

🎯 Testing Your Deployed Lambda

Simple Invocation

# Test with production payload (uses event-live.json)
./workbench/3-invoke.sh

The 3-invoke.sh script:

  • Loads your configuration from config.local.env
  • Uses the FUNCTION_NAME setting (or derives it from STACK_NAME)
  • Invokes with event-live.json as test payload
  • Shows the response and execution details

Manual AWS CLI Invocation

# Test with custom payload
aws lambda invoke --function-name your-function \
  --payload '{"name":"test","data":"hello"}' \
  response.json && cat response.json

# List your functions
aws lambda list-functions --query 'Functions[?contains(FunctionName, `boxlang`)].FunctionName'

Configuration Variables in Action

Your config.local.env settings are used throughout the deployment:

# Example config.local.env
STACK_NAME=my-api-stack
AWS_LAMBDA_BUCKET=my-unique-bucket-name
LAMBDA_MEMORY=512          # Higher memory for performance
LAMBDA_TIMEOUT=30          # Longer timeout for complex operations
FUNCTION_NAME=my-api-stack-bxFunction-ABC123DEF456
ENVIRONMENT=production

When you deploy, you'll see:

βš™οΈ  Lambda Memory: 512MB, Timeout: 30s, Environment: production

βš™οΈ Configuration Reference

πŸ“‹ Complete Configuration Variables

The template uses a hierarchical configuration system: config.local.env β†’ config.env β†’ environment variables

Required Settings

Variable Description Example Used By
AWS_LAMBDA_BUCKET S3 bucket for artifacts (globally unique) my-company-lambda-artifacts All deployment scripts

Stack & Function Settings

Variable Default Description Used By
STACK_NAME boxlang-lambda-stack CloudFormation stack name 2-deploy.sh, 4-cleanup.sh
FUNCTION_NAME {STACK_NAME}-bxFunction-{SUFFIX} Direct function name for invocation 3-invoke.sh

Lambda Runtime Settings

Variable Default Description Constraints
LAMBDA_MEMORY 128 Memory allocation (MB) 128-10240 MB
LAMBDA_TIMEOUT 15 Timeout in seconds 1-900 seconds
ENVIRONMENT dev Deployment environment tag dev/staging/prod

AWS Settings

Variable Default Description Used By
AWS_REGION your default AWS region for deployment All AWS CLI operations

πŸ”§ Configuration Setup

1. Copy Template

cp workbench/config.env workbench/config.local.env

2. Edit Your Settings

# config.local.env (this file is gitignored)
AWS_LAMBDA_BUCKET=my-unique-bucket-2024
STACK_NAME=my-api-prod
LAMBDA_MEMORY=256
LAMBDA_TIMEOUT=30
ENVIRONMENT=production

3. Verify Configuration

# Check if AWS is configured
./workbench/0-check-aws.sh

# Deploy with your config
./workbench/2-deploy.sh

🎯 Configuration Best Practices

  • βœ… Use config.local.env - Keep your settings out of git
  • βœ… Unique bucket names - Include company/project prefix
  • βœ… Environment-specific stacks - my-app-dev, my-app-prod
  • βœ… Resource sizing - Start small, scale up based on needs
  • βœ… Timeout alignment - Match Lambda timeout with boxlang.json settings

πŸ’« Complete Development Workflow

πŸ“‹ From Zero to Deployed

1. Initial Setup

# Clone or download the template
git clone <your-repo>
cd boxlang-aws-lambda-template

# Configure your deployment settings
cp workbench/config.env workbench/config.local.env
# Edit config.local.env with your AWS settings

2. Development Cycle

# Test locally during development
./gradlew runLocal                    # Quick local test
./gradlew test                       # Run full test suite

# Test with HTTP endpoints (if SAM CLI installed)
./gradlew startSamServerBackground   # Start local API server
curl http://localhost:3000           # Test your endpoints
./gradlew stopSamServer             # Stop when done

3. Pre-Deployment Validation

# Verify AWS configuration
./workbench/0-check-aws.sh

# Full build and test
./gradlew clean build test

# Verify your config
cat workbench/config.local.env

4. AWS Deployment

# Create S3 bucket (one-time setup)
./workbench/1-create-bucket.sh

# Deploy to AWS Lambda
./workbench/2-deploy.sh

# Test deployed function
./workbench/3-invoke.sh

5. Iteration & Updates

# Make code changes in src/main/bx/Lambda.bx
# Run tests
./gradlew test

# Redeploy
./gradlew build && ./workbench/2-deploy.sh

# Test updated function
./workbench/3-invoke.sh

6. Cleanup (when done)

# Remove all AWS resources
./workbench/4-cleanup.sh

⚑ Quick Commands Reference

Daily Development

./gradlew runLocal                   # Test locally
./gradlew test                      # Run tests
./gradlew build                     # Build package

AWS Operations

./workbench/0-check-aws.sh          # Check AWS setup
./workbench/1-create-bucket.sh      # Create S3 bucket
./workbench/2-deploy.sh             # Deploy to AWS
./workbench/3-invoke.sh             # Test deployed function
./workbench/4-cleanup.sh            # Remove AWS resources

Local Testing Options

./gradlew runLocal                  # Default event
./gradlew runLocalApi              # API Gateway event
./gradlew runLocalLegacy           # Legacy API event
./gradlew startSamServerBackground # HTTP server
./gradlew stopSamServer           # Stop server

βœ… Development Tips

πŸ’‘ Best Practices

  • πŸ§ͺ Test locally before deploying - Use ./gradlew test to catch issues early
  • πŸš€ Use the wrapper - Always use ./gradlew (not gradle) for consistency
  • πŸ“¦ Check your ZIP - Verify build/distributions/*.zip contains expected files
  • πŸ”§ Configure for production - Set trustedCache: true in boxlang.json

🎨 Code Formatting Standards

Spacing around symbols: Always add spaces around parentheses ( ), brackets [ ], braces { }, and operators for readability

Examples:

  • βœ… function run( event, context, response )
  • ❌ function run(event,context,response)
  • βœ… var results = [ 1, 2, 3 ]
  • ❌ var results = [1,2,3]
  • βœ… if ( condition ) { doSomething(); }
  • ❌ if(condition){doSomething();}

Apply this spacing standard to all BoxLang, Java, and configuration code in the project.

πŸ› Troubleshooting

πŸ”§ Build & Test Issues

Problem Solution
❌ Tests fail with ClassNotFoundException Check dependency resolution, run ./gradlew clean build
❌ Gradle build fails Ensure Java 21+ installed, run ./gradlew --version
❌ BoxLang class not found Check module paths in src/resources/boxlang_modules/
❌ Large deployment package Review dependencies in build.gradle, exclude unnecessary JARs

☁️ AWS Deployment Issues

Problem Solution
❌ AWS credentials not configured Run ./workbench/0-check-aws.sh for diagnosis
❌ S3 bucket already exists Choose a globally unique bucket name in config.local.env
❌ CloudFormation deployment fails Check AWS permissions, review stack events in AWS Console
❌ Lambda function not found Verify FUNCTION_NAME in config matches deployed function

πŸš€ Lambda Runtime Issues

Problem Solution
❌ Lambda timeout in AWS Increase LAMBDA_TIMEOUT in config and redeploy
❌ Lambda memory errors Increase LAMBDA_MEMORY in config and redeploy
❌ BoxLang initialization errors Check boxlang.json configuration, enable debugMode: true
❌ Module loading failures Verify modules in src/resources/boxlang_modules/ directory

πŸ› οΈ Quick Diagnosis Commands

# Check AWS configuration
./workbench/0-check-aws.sh

# Verify project build
./gradlew clean build test

# Test locally before deployment
./gradlew runLocal

# Check deployed function
aws lambda list-functions --query 'Functions[?contains(FunctionName, `boxlang`)].FunctionName'

πŸ“š Additional Help: See workbench/DEPLOYMENT.md for detailed deployment troubleshooting

Ortus Sponsors

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

THE DAILY BREAD

"I am the way, and the truth, and the life; no one comes to the Father, but by me (JESUS)" Jn 14:1-12

About

A base template to work with our BoxLang AWS Runtime

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •