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

Into the Box Sessions Round 2 is now Out!

Into the Box Sessions Round 2 is now Out!

Into the Box 2026 is shaping up to be our most dynamic event yet! Building on the momentum of our first release, we are thrilled to announce the second round of sessions for this year's conference.

As the ecosystem continues to evolve, teams are balancing the realities of maintaining critical legacy applications while adopting modern tools, architectures, and practices. Into the Box has always been about meeting developers where they are and giving them practical paths to whatโ€™s next.

Victor Campos
Victor Campos
February 24, 2026
Why UK Financial Institutions are reassessing ColdFusion Licensing

Why UK Financial Institutions are reassessing ColdFusion Licensing

Rising ColdFusion Licensing Costs, Oracle JVM Risk and Financial Exposure in the United Kingdom

Across the United Kingdom, many financial institutions continue to rely on legacy Adobe ColdFusion (ACF) platforms to power internal banking systems, insurance portals, reporting tools, and regulatory workflows.

For years, these systems were stable and cost-effective.

Today, however, Adobe ColdFusion licensing costs

Cristobal Escobar
Cristobal Escobar
February 24, 2026