Blog

Luis Majano

January 09, 2026

Spread the word


Share your thoughts

Happy New Year! The BoxLang team is excited to announce BoxLang 1.9.0, a significant stability and compatibility release focused on production-readiness thanks to our client migrations and new application deployments. This release also introduces array-based form field parsing conventions, enhanced datasource lifecycle management, improved context handling, and resolves over 50 critical bugs to ensure enterprise-grade reliability for mission-critical applications.

🚀 What's New in 1.9.0

You can find the full engineering what's new guide here: https://boxlang.ortusbooks.com/readme/release-history/1.9.0

📦 Array-Based Form Field Parsing - Modern Web Conventions

BoxLang now automatically parses query parameters and form fields as arrays using modern naming conventions—no more manual listToArray() conversions:

// HTML form with multiple selections
<form method="POST">
    <input type="checkbox" name="colors[]" value="red" />
    <input type="checkbox" name="colors[]" value="blue" />
    <input type="checkbox" name="colors[]" value="green" />
    <button type="submit">Submit</button>
</form>

// BoxLang automatically parses as array
selectedColors = form.colors;
// Result: ["red", "blue", "green"]

// Works with query parameters too
// URL: /page?tags[]=boxlang&tags[]=java&tags[]=modern
tags = url.tags;
// Result: ["boxlang", "java", "modern"]

// Traditional single values still work
name = form.name;  // Single string value

Benefits:

  • ✨ No manual conversions needed
  • 🎯 Consistent with modern web frameworks
  • 🔄 Fully backward compatible
  • 📡 Works with both POST and GET data

🔄 Enhanced Context Lifecycle Management - Proper Cleanup

Significant improvements to context management and shutdown handling ensure proper resource cleanup and prevent memory leaks in long-running applications:

Key Improvements:

  • Thread Counter Tracking - Contexts maintain active thread counts for proper cleanup
  • Exchange Detachment - Web contexts can detach during shutdown while still in use
  • ORM Cleanup - ORM context removal moved to shutdown listeners
  • Session Error Recovery - Errors in onSessionEnd no longer permanently break sessions
  • Startup Prevention - Sessions won't inadvertently start during app initialization

🗄️ Datasource Lifecycle Management - No More Connection Leaks

Critical fixes to datasource lifecycle prevent connection pool leaks and resource exhaustion:

class {
    this.name = "MyApp";
    
    this.datasources = {
        "mydb" : {
            driver : "mysql",
            host : "localhost",
            database : "appdb",
            username : "user",
            password : "pass"
        }
    };

    function onApplicationEnd() {
        // Datasources properly shutdown automatically
        // No more connection pool leaks across application restarts!
        writeLog( "Datasources cleaned up automatically" );
    }
}

Fixed Issues:

  • ✅ Application-level datasources shut down when application ends
  • ✅ Server-level datasources no longer create duplicate pools per application
  • ✅ Application caches properly removed on application end
  • ✅ Connection pool cleanup during entire application lifecycle

📊 Comprehensive Query and JDBC Enhancements

Major improvements to query handling and database operations across all drivers:

Oracle Database Improvements:

// Named parameters now work correctly
queryExecute(
    "SELECT * FROM users WHERE id = :userId AND status = :status",
    {
        userId : { value : 123, type : "integer" },
        status : { value : "active", type : "varchar" }
    },
    { datasource : "oracle_ds" }
);

// Ref cursor parameters work regardless of position
bx:storedproc procedure="getUserData" datasource="oracle_ds" {
    bx:procparam type="in" value=123 cfsqltype="cf_sql_integer";
    bx:procparam type="out" variable="result" cfsqltype="cf_sql_refcursor";
}

// Unused procresult tags properly ignored (no errors)
bx:storedproc procedure="processData" datasource="oracle_ds" {
    bx:procresult name="unused";  // Safe even if not returned
    bx:procparam type="in" value="data";
}

Parameter Handling:

// Empty lists in queryparam handled correctly (CFML compat)
bx:query name="filtered" {
    writeOutput( "
        SELECT * FROM products
        WHERE category IN (
            <bx:queryparam value='#categoryList#' list='true' />
        )
    " );
}

// Integer SQL type now properly validates instead of truncating
queryExecute(
    "INSERT INTO scores (value) VALUES (?)",
    [ { value : 95.5, type : "integer" } ]  // Now throws error (was silently truncating)
);

Query of Queries:

// NULL comparisons with LIKE now work correctly
query1 = queryNew( "name,description", "varchar,varchar", [
    [ "Product 1", null ],
    [ "Product 2", "A great product" ]
] );

result = queryExecute(
    "SELECT * FROM query1 WHERE description LIKE '%product%'",
    {},
    { dbtype : "query" }
);
// Properly handles NULL values without errors

🔢 Number Handling Improvements - Clean Serialization

Significant enhancements to numeric type handling prevent scientific notation in JSON:

// Doubles serialize without scientific notation
bigNumber = 1234567890.123456;
jsonStr = jsonSerialize( { value : bigNumber } );
// Output: {"value":1234567890.123456}
// NOT: {"value":1.234567890123456E9}

// BigDecimals also serialize cleanly
amount = preciseValue( "999999999.99" );
jsonStr = jsonSerialize( { amount : amount } );
// Output: {"amount":999999999.99}

// Scientific notation literals with leading zeros parse correctly
value = 0001.5e2;  // Now works: 150

// String-to-double conversion trims whitespace
value = toNumeric( "  42.5  " );  // Now works: 42.5

🎭 Enhanced Class Metadata - Static and Abstract Flags

Class metadata now includes static and abstract flags for functions:

abstract class {

    static function getVersion() {
        return "1.9.0";
    }

    abstract function process();
}

// Inspect metadata
meta = getMetadata( MyClass );
functionMeta = meta.functions[ "getVersion" ];

println( "Is static: #functionMeta.static#" );      // true
println( "Is abstract: #functionMeta.abstract#" );  // false

// Use in reflection scenarios
if( functionMeta.static ) {
    version = invoke( MyClass, "getVersion" );
}

Additional Metadata Improvements:

  • Component metadata returns struct for implements (not string)
  • Interface metadata properly structured
  • Doc comments preserve line breaks
  • Doc comments inside script blocks associate properly

🧹 SOAP Client Improvements

The SOAP client from 1.8.0 enhanced with proper class structure:

// SOAP client now has full class capabilities
ws = soap( "http://example.com/service.wsdl" );

// Access underlying HTTP methods
ws.setTimeout( 60 );
ws.setHeader( "Authorization", "Bearer token123" );

// Invoke SOAP methods with improved reliability
result = ws.invoke( "getUserInfo", 123 );
println( "User: #result.name#" );

📝 Mid() Function Enhancement

The mid() BIF now has optional count parameter for flexible string extraction:

// Extract from position to end of string
text = "Hello World";
result = mid( text, 5 );  // "o World"

// Extract with count (existing behavior)
result = mid( text, 5, 3 );  // "o W"

// More intuitive substring operations
greeting = "Good Morning Everyone";
timeOfDay = mid( greeting, 6, 7 );  // "Morning"
remainder = mid( greeting, 14 );     // "Everyone"

🐛 50+ Critical Bug Fixes

CFML Compatibility (15+ fixes)

  • ListDeleteAt - Retains leading delimiters (proper CFML behavior)
  • ListAppend - Behavior matches CFML exactly
  • Boolean Strings - Characters 'y' and 'n' recognized as booleans in compat mode
  • Session IDs - Properly prefixed with app identifier when J2EE sessions enabled
  • GetComponentMetaData - Returns struct for implements (not string)
  • Empty Query Params - Empty lists in cfqueryparam handled correctly
  • CreateUUID - Returns standard UUID format

File Operations (5+ fixes)

  • File Upload - result field properly populated after upload
  • Content Types - Upload contentType no longer includes contentSubType
  • File Append - action="append" correctly appends with line breaks

Date & Time (5+ fixes)

  • DateTime Parsing - Fixed casting with formats like "Dec/13/2025 08:00"
  • DateAdd - datepart parameter no longer case-sensitive
  • GetHTTPTimeString - Always returns GMT timezone
  • Session End Errors - Errors no longer leave session permanently expired
  • Session Prevention - Sessions don't start during app initialization
  • Cookie Serialization - Time serialized in GMT as expected

Core Runtime (10+ fixes)

  • Duplicate - Properly handles recursive references
  • ExpandPath - Works correctly outside request context (in onServerStart)
  • For Loops - Work properly with Java primitive arrays
  • Evaluate - Uses CF transpiler when called from CF source
  • Whitespace - Preserve whitespace no longer consumes excessive line breaks
  • Class Loading - Fixed race conditions with concurrent class loading

Database and ORM (5+ fixes)

  • Redis Query Caching - Fixed serialization with cached queries
  • ORM Datasources - ORM properly finds datasources without errors
  • Stored Procedure Return Codes - Use correct key names

Memory and Threading (5+ fixes)

  • Stream Handling - Fixed "Stream is closed" errors (UT010029)
  • Context Threading - Proper handling with multiple active threads
  • Comparison Sorting - Fixed "Comparison method violates its general contract"

String Operations (5+ fixes)

  • ReReplace - Fixed index out of bounds errors
  • String Comparison - Better error handling in comparisons
  • Class Inspection - Improved error handling for complex object dumps

🔧 Configuration Updates

HTTP Multipart Simplification

File uploads no longer require explicit multipart() call in many cases:

// Automatic multipart detection
http( "https://api.example.com/upload" )
    .post()
    .file( "document", "/path/to/file.pdf" )
    .send();
// multipart() automatically applied when files present

Transaction Component Cleanup

Removed unused nested attribute from transaction component:

// Simplified transaction syntax
transaction {
    queryExecute( "INSERT INTO users (name) VALUES (?)", [ "John" ] );
    queryExecute( "INSERT INTO logs (action) VALUES (?)", [ "user_created" ] );
}

// Nested transactions work automatically
transaction {
    queryExecute( "UPDATE accounts SET balance = balance - 100 WHERE id = 1" );
    
    transaction {
        queryExecute( "UPDATE accounts SET balance = balance + 100 WHERE id = 2" );
    }
}

📡 MiniServer JSON Configuration

MiniServer configuration via JSON files (introduced in 1.8.0) is now finalized:

# Automatically loads miniserver.json
boxlang-miniserver

# Or specify custom config
boxlang-miniserver /path/to/config.json

Example Configuration:

{
    "port" : 8080,
    "webRoot" : "./www",
    "debug" : true,
    "rewrites" : true,
    "rewriteFileName" : "index.bx",
    "healthCheck" : true
}

🎯 Why This Release Matters

BoxLang 1.9.0 represents our continued commitment to production-grade reliability. The focus on lifecycle management, datasource cleanup, and CFML compatibility makes this release essential for:

  • Enterprise Applications - Running mission-critical workloads with confidence
  • CFML Migrations - Smoother transitions with enhanced compatibility
  • Long-Running Services - Proper resource cleanup prevents memory leaks
  • High-Volume Applications - Optimized connection pooling and cache management

Download

Please visit our download page or our quick installation guides to upgrade your installation.

Professional Open Source

BoxLang is a professional open-source product, with three different licences:

  1. Open-Source Apache2
  2. BoxLang +
  3. BoxLang ++

BoxLang is free, open-source software under the Apache 2.0 license. We encourage and support community contributions. BoxLang+ and BoxLang ++ are commercial versions offering support and enterprise features. Our licensing model is based on fairness and the golden rule: Do to others as you want them to do to you. No hidden pricing or pricing on cores, RAM, SaaS, multi-domain or ridiculous ways to get your money. Transparent and fair.

BoxLang Subscription Plans

BoxLang is more than just a language; it's a movement.

Join us and redefine development on the JVM Ready to learn more? Explore BoxLang's Features, Documentation, and Community.

Add Your Comment

Recent Entries

DocBox v5 - Reborn: Modern API Docs for BoxLang & CFML

DocBox v5 - Reborn: Modern API Docs for BoxLang & CFML

Welcome to DocBox v5! We didn't just update DocBox. We rebuilt it from the ground up.

DocBox v5.0.0 represents a complete architectural rewrite—modern syntax, blazing performance, and a stunning new look that finally brings API documentation into 2025. Gone are the clunky HTML pages of yesteryear. Say hello to a gorgeous, theme-driven single-page application that makes browsing your API docs feel like using a premium developer tool. We have also released a dedicated module for BoxLang: BX-DOCBOX. A fully interactive CLI tool for generating your docs from the command line using pure BoxLang.

Luis Majano
Luis Majano
January 06, 2026