1.7.0

November 4, 2025

Introduction

BoxLang 1.7.0 brings significant performance improvements, powerful new features for modern web development, and enhanced database capabilities. This release introduces Server-Sent Events (SSE) support for building real-time applications and AI agents, a new JDBC Cache Store for distributed caching, and bytecode compatibility versioning for improved module management. Performance optimizations across scheduled tasks, class loading, and ASM generation deliver faster execution, while over 40 bug fixes improve stability in file operations, HTTP handling, database queries, and CFML compatibility.

🚀 Major Highlights

🎯 Server-Sent Events (SSE)

New SSE() BIF and Emitter for web runtimes enables real-time server-to-client event streaming, perfect for building AI agents, live dashboards, progressive loading experiences, and real-time notifications. The implementation includes automatic keep-alive, CORS support, async execution, and graceful timeout handling.

Basic Usage:

// Simple synchronous streaming
SSE( ( emitter ) => {
    emitter.send( "Hello from server!" );
    emitter.send( { status: "processing", progress: 25 }, "update" );
    emitter.close();
} );

AI Streaming with Async Execution:

// Non-blocking AI response streaming
SSE(
    callback: ( emitter ) => {
        var response = callAIService();
        while( !emitter.isClosed() && response.hasMoreTokens() ) {
            emitter.send( response.getNextToken(), "token" );
        }
        emitter.send( { complete: true }, "done" );
    },
    async: true,
    keepAliveInterval: 30000,  // Send keep-alive every 30s
    timeout: 300000            // Close after 5 minutes max
);

Cross-Origin Streaming:

// Enable CORS for cross-domain requests
SSE(
    callback: ( emitter ) => {
        emitter.send( { message: "Hello from API" }, "greeting", 1 );
    },
    cors: "*"  // or specific origin: "https://app.example.com"
);

Available Parameters:

  • callback (required) - Closure/lambda that receives the emitter object

  • async (default: false) - Run callback in background thread (non-blocking)

  • retry (default: 0) - Client reconnect interval in milliseconds

  • keepAliveInterval (default: 0) - Auto-send keep-alive comments interval

  • timeout (default: 0) - Maximum execution time for async mode

  • cors (default: "") - CORS origin (* for all, or specific domain)

Emitter Methods:

  • send( data, [event], [id] ) - Send SSE event (complex data auto-serialized to JSON)

  • comment( text ) - Send SSE comment for keep-alive

  • close() - Gracefully close the stream

  • isClosed() - Check if client disconnected

Implementation Features:

  • Automatic first-byte flush to establish connection quickly

  • Large data chunking (splits >32KB lines automatically)

  • Multi-line data support with proper SSE formatting

  • Client disconnect detection with graceful cleanup

  • Proxy/nginx buffering disabled for real-time delivery

🗄️ JDBC Cache Store

New distributed cache store backed by JDBC databases, enabling cache sharing across multiple BoxLang instances. Perfect for horizontal scaling scenarios where multiple application servers need to share cached data.

Basic Configuration:

// Configure JDBC cache store in boxlang.json
{
  "caches": {
    "distributedCache": {
      "provider": "BoxCache",
      "properties": {
        "objectStore": "JDBCStore",
        "datasource": "myDatasource",
        "table": "boxlang_cache",
        "autoCreate": true
      }
    }
  }
}

Advanced Configuration with Eviction:

{
  "caches": {
    "sharedCache": {
      "provider": "BoxCache",
      "properties": {
        "objectStore": "JDBCStore",
        "datasource": "prodDB",
        "table": "app_cache",
        "autoCreate": true,
        // Standard BoxCache properties
        "maxObjects": 1000,
        "evictionPolicy": "LRU",
        "evictCount": 100,
        "defaultTimeout": 3600,
        "defaultLastAccessTimeout": 1800,
        "reapFrequency": 300
      }
    }
  }
}

Configuration Options:

  • datasource (required) - Name of the datasource to use for storage

  • table (default: "boxlang_cache") - Database table name for cache storage

  • autoCreate (default: true) - Automatically create table and indexes if missing

  • Plus all standard BoxCache properties (maxObjects, evictionPolicy, evictCount, etc.)

Supported Databases:

  • Oracle

  • MySQL / MariaDB

  • PostgreSQL

  • Microsoft SQL Server

  • Apache Derby

  • HSQLDB

  • SQLite

The implementation automatically detects the database vendor and generates optimized SQL for each platform, including proper handling of:

  • Database-specific data types (CLOB, TEXT, LONGTEXT, etc.)

  • Vendor-specific eviction queries (LIMIT, TOP, FETCH FIRST)

  • Index creation strategies

  • Transaction handling

Features:

  • Distributed: Mark as distributed store - cache data persists across instances

  • Automatic Schema Management: Creates table and indexes on first use

  • Serialization: Uses Base64-encoded object marshalling for complex types

  • Performance: Pre-compiled SQL statements for all operations

  • Eviction Support: Full support for LRU, LFU, and other eviction policies

  • Metadata Tracking: Stores hits, timeouts, and access timestamps

All cache stores now expose isDistributed() method for ecosystem tools to detect distribution capabilities.

🌳 BoxAST() - AST Generation

New BoxAST() BIF enables programmatic access to BoxLang's Abstract Syntax Tree (AST), perfect for building code analysis tools, linters, formatters, and code generation utilities. It supports parsing BoxLang script/template syntax as well as CFML/ColdFusion syntax for migration and compatibility tools.

// Parse BoxLang source code using BIF
ast = BoxAST( source: "x = 1 + 2; y = x * 3;" );

// Or use the convenient string member method
code = "function hello() { return 'world'; }";
ast = code.toAST();

// Parse from a file
ast = BoxAST( filepath: "myScript.bx" );

// Return as JSON for external tools
astJson = BoxAST(
  source: "function hello() { return 'world'; }",
  returnType: "json"
);

// Or with member method
astJson = "x = 1 + 2;".toAST( returnType: "json" );

// Return as text representation
astText = BoxAST(
  filepath: "complex.bx",
  returnType: "text"
);

// Parse BoxLang template syntax
templateAst = BoxAST(
  source: "<bx:output>#now()#</bx:output>",
  sourceType: "template"
);

// Parse CFML/ColdFusion script (for migration tools)
cfScriptAst = BoxAST(
  source: "cfset x = 1; cfloop from='1' to='10' index='i' { writeOutput(i); }",
  sourceType: "cfscript"
);

// Parse CFML/ColdFusion template (for migration tools)
cfTemplateAst = BoxAST(
  source: "<cfset x = 1><cfoutput>#x#</cfoutput>",
  sourceType: "cftemplate"
);

Parameters:

  • source - BoxLang/CFML source code to parse

  • filepath - Path to file to parse (alternative to source)

  • returnType - Output format: "struct" (default), "json", or "text"

  • sourceType - Syntax type: "script" (default), "template", "cfscript", or "cftemplate"

Use Cases:

  • Code Analysis: Build custom linters and static analysis tools

  • Code Generation: Generate BoxLang code from templates or DSLs

  • Formatters: Create custom code formatting utilities

  • Documentation Generators: Extract function signatures and comments

  • Refactoring Tools: Analyze and transform code structures

  • IDE Tooling: Power syntax highlighting and code intelligence features

  • Migration Tools: Parse and analyze CFML code for BoxLang migration

🔧 Bytecode Compatibility Versioning

BoxLang now implements bytecode compatibility versioning, ensuring compiled classes remain compatible across runtime versions and improving module stability.

🤖 Core Runtime Updates

Performance Improvements

  • Scheduled Tasks: Significant performance boost by introducing non-concurrent maps for logging and closure suppliers

  • Static Initializers: Optimized execution of static class initializers

  • ASM Generation: Streamlined bytecode generation by eliminating disk-based class file operations

  • Cache Stores: Performance tuning across all cache store implementations

Enhanced Dumping

  • Renamed all dump() member methods to .bxDump() to prevent conflicts with user-defined methods

  • Improved class dumping with better error handling for restricted Java fields

  • Fixed Java time type dumping (java.sql.Time)

  • Better handling of recursive class references in JSON serialization

Module System Enhancements

  • Added missing properties to getModuleInfo() struct snapshot

  • Fixed module publicMapping registration

  • Improved IService lifecycle by ensuring onConfigurationLoad() is called correctly

  • Better validation of template URIs

HTTP Component Improvements

  • Added client certificate functionality support:

http url="https://secure-api.com" {
  httpparam type="certificate" file="client-cert.p12" password="secret";
}
  • Fixed double encoding of query parameters in HTTPParam

  • Better handling of getAsBinary=no for CFML compatibility

  • Proper Optional unwrapping in HTTP result responses

📡 MiniServer Runtime Updates

  • Fixed rewrite file extension handling - no longer rewrites requests unnecessarily

  • Improved request body handling for empty payloads

  • Better error messages for empty request bodies

🤖 Servlet Runtime Updates

  • Fixed relative path resolution for mappings

  • Enabled BOXLANG_DEBUG environment variable support

  • Improved session management - fixed jsessionid cookie handling to prevent AWS WAF issues

  • Better handling of in-progress onApplicationStart() for concurrent requests

🥊 Developer Experience

Dynamic Object Creation

Enhanced createDynamicProxy() and createObject() to accept custom class loaders:

// Use custom class loader for dynamic object creation
customLoader = createObject( "java", "java.net.URLClassLoader" )
  .init( [ url ] );

proxy = createDynamicProxy(
  listener,
  [ "com.example.Interface" ],
  customLoader
);

IStruct Convenience Method

New getAsChar() method on IStruct for convenient character extraction:

struct = { "code": "A" };
charValue = struct.getAsChar( "code" ); // Returns Character 'A'

Configuration Improvements

  • JSON placeholders now applied immediately upon reading for consistent key replacement

  • Better handling of hyphens in pre-annotations to match post-annotation behavior

  • Fixed ignore of wildcard * in valid template extensions when searching for Application descriptors

🐛 Notable Bug Fixes

Database & Stored Procedures

  • Fixed MSSQL connection issues when specifying username and password in cfquery

  • Resolved multiple result set returns in CFStoredProc

  • Fixed stored procedure parameter errors and type casting for timestamps

  • Improved dynamic SQL type handling in CF transpiler

File Operations

  • Fixed fileCopy() not respecting overwrite parameter

  • Corrected file upload handling:

    • Files smaller than 10KB now properly stored on disk

    • Proper directory creation for absolute destination paths

    • Fixed template-relative destination path handling

    • Empty allow argument now treated correctly

  • Fixed getFileInfo() returning incorrect type string for directories

  • Resolved expandPath() using wrong base path when Application.bx in different directory

List Operations

  • Fixed listDeleteAt() incorrect behavior in both modes

  • Resolved appending null to list failures

Component & Class Handling

  • Better error messages for import statements in class bodies

  • Fixed class dump output showing keys twice instead of values

  • Improved loose struct converter error handling

  • Fixed duplicate() failures when encountering Optional types

Mail & Dates

  • Fixed bx:mail component string attribute handling for useSSL/useTLS

  • Resolved dateConvert() errors

  • Added handling for string dates with common masks

Path & Mapping

  • Normalized mapping paths with ../ correctly

  • Fixed CGI scope mapping returning null values

  • Improved abort exception handling (no longer caught inappropriately)

Dump Operations

  • Fixed CFDUMP and WRITEDUMP file output functionality

Windows Compatibility

  • Resolved Windows BoxLang REPL regression

🔧 Configuration Updates

No configuration changes required for this release. New features like SSE and JDBC cache store are opt-in and require explicit configuration.

⚡ Migration Notes

Breaking Changes

Dump Method Rename: All built-in member methods named dump() have been renamed to .bxDump() to avoid conflicts with user-defined methods. If you were calling .dump() on built-in objects, update to .bxDump():

// Old
array.dump();

// New
array.bxDump();

Compatibility Improvements

  • Enhanced CFML compatibility for HTTP component behaviors

  • Better handling of empty file upload allow parameter

  • Improved stored procedure result set handling

  • More accurate CGI scope value mapping


🎶 Release Notes

Release notes - BoxLang - 1.7.0

Improvements

BL-1808 HTTP Component - Support Client Cert Functionality

BL-1818 allow hyphen in pre annotations to match post annotations

BL-1825 Performance improvement of all scheduled task calls by introducing non concurrent maps for logging and closure suppliers

BL-1830 Don't rewrite miniserver requests with rewrite file extension

BL-1836 Apply placeholders to JSON as soon as it's read to ensure all keys are replaced

BL-1838 Improve performance of running static initializer on class

BL-1839 Added missing properties to getModuleInfo() struct snapshot

BL-1846 Validate request URIs

BL-1848 Optimize ASM generation by not relying on disk class files

BL-1849 dump class improvements

BL-1853 Component annotation for ignoring ignore outpout only setting

BL-1855 Component annotation for auto-evaluating interpolated expressions

BL-1863 Rename all dump() member methods to be .bxDump() to avoid conflicts with actual methods named dump()

BL-1864 Catch Java access errors when getting Fields dynamically in class dump

BL-1865 Allow createDynamicProxy(), createObject() to accept a class loader

BL-1866 Ignore valid template extension setting of * when searching for Application descriptors

BL-1867 can't dump java.sql.Time

BL-1877 Performance tuning on cache stores

New Features

BL-1791 Implement bytecode compat version

BL-1861 New getAsChar() on IStruct for convenience

BL-1875 New JDBCStore for the Box Cache

BL-1876 Cache stores now have a isDistributed() interface method which allows cache providers and eco system to tell if the store can distribute content or be local only

BL-1880 New SSE() BIF and Emitter for Web Runtimes to allow for server side event streaming. Especially great when building AI Agents

BL-1883 New BoxAST() bif to help you return the AST of source or a filepath

Bugs

BL-1376 specifying `username` and `password` throws 'unable to open connection' in cfquery - mssql

BL-1685 CFStoredProc does not return multiple result sets when using a statement like an insert as first query

BL-1809 Servlet resolution of relative paths can return incorrect mapping

BL-1810 Prevent Double Encoding of Query Params passed by HTTParam

BL-1811 loose struct converter can error on getting public fields

BL-1812 Don't catch abort exceptions

BL-1814 appending null to list fails

BL-1815 listDeleteAt() is not working correctly on cfml compat mode or not

BL-1816 Stored Procedure errors out on missing parameter

BL-1817 FileCopy bif using overwrite is not using it.

BL-1820 mapping paths with ../ not always normalized

BL-1821 recursive class references cause stack overflow on JSON serialization

BL-1822 Compat: HTTP getAsBinary=no not always honored in other engines

BL-1823 Duplicate Fails When Encountering Optional

BL-1824 HTTP Component Returns Raw Optional for Result response When No Timeout is Specified

BL-1829 Module publicMapping is not being registered

BL-1831 dateConvert is throwing an error

BL-1833 bx:mail not handling string useSSL or useTLS attributes

BL-1834 CFDUMP and WRITEDUMP do not dump to a file

BL-1837 Instances of IService in BL Modules never call onConfigurationLoad

BL-1840 CF transpiler doesn't catch dynamic sql type on proc param

BL-1841 BOXLANG_DEBUG env var not used in servlet

BL-1842 Class dump doesn't output this scope values, just keys twice

BL-1845 subsequent requests do not respect in-progress onApplicationStart()

BL-1847 I am getting an error after server forget and server start

BL-1851 Better error for Import Statements in Class bodies

BL-1854 Web Compat: Empty `allow` argument to FileUpload is treated as "All" by other Engines

BL-1856 MiniServer Exchange GetRequestBody Method Throws Error when RequestBody Is Empty

BL-1857 GetFileInfo Returns Incorrect `type` string for Directory

BL-1858 File Uploads smaller than 10KB not being stored on disk

BL-1860 expandPath() uses wrong base path when application.xx is in different dir

BL-1870 stored proc param not casting timestamp

BL-1871 Regression Windows Boxlang REPL

BL-1872 FileUpload - When Temp directory is passed in explicitly in absolute destination path, directories should be created

BL-1873 FileUpload - Ensure correct handling for template relative destination paths

BL-1874 jsessionid cookie value set to null - breaks AWS WAF

BL-1878 Mapping CGI scope returns null values

BL-1879 Add handling for string dates as a common mask

Last updated

Was this helpful?