1.4.0

August 2, 2025

We're excited to announce BoxLang v1.4.0, our biggest release yet! This major update brings powerful new features, performance improvements, and extensive bug fixes that make BoxLang more robust and developer-friendly than ever.

🚀 Major New Features

Revolutionary Asynchronous Programming Framework

BoxLang v1.4.0 introduces a game-changing asynchronous programming framework that sets a new standard for JVM languages. This isn't just another async implementation—it's a comprehensive, battle-tested framework that makes parallel programming accessible, intuitive, and powerful in ways that other languages and frameworks simply don't offer.

What makes this revolutionary:

  • Zero boilerplate - Write async code as naturally as synchronous code

  • Built-in parallel primitives - No need for complex thread management or executor services

  • Functional composition - Chain, compose, and transform async operations with ease

  • Exception safety - Automatic error propagation and handling across async boundaries

  • Performance optimized - Leverages modern JVM concurrency patterns under the hood

  • Dedicated logging - Separate async.log and scheduler.log files for complete observability of async operations

Core async primitives that change everything:

  • asyncRun() - Transform any operation into a non-blocking future (with runAsync() as an alias)

  • asyncAll() - Execute multiple operations in parallel and aggregate results—no more callback hell or complex coordination

  • asyncAllApply() - Map-reduce operations across collections in parallel with automatic work distribution

  • asyncAny() - Race multiple operations and get the fastest result—perfect for timeout patterns and redundant services

This is async programming reimagined. While other languages force you to deal with complex promises, callbacks, or verbose async/await patterns, BoxLang gives you declarative parallel programming that just works.

This powerful new framework is fully documented in our comprehensive Asynchronous Programming Guide, including detailed sections on Executors, BoxFutures, Async Pipelines, Parallel Computations, and Scheduled Tasks.

// Run multiple operations in parallel
results = asyncAll( [
    () => fetchUserData( userId ),
    () => fetchOrderHistory( userId ),
    () => fetchPreferences( userId )
] );

// Apply function to multiple inputs in parallel
processedData = asyncAllApply( 
    [ "file1.txt", "file2.txt", "file3.txt" ],
    ( file ) => processFile( file )
);

// Get the first completed result
fastestResult = asyncAny( [
    () => callService1(),
    () => callService2(),
    () => callService3()
] );

// Powerful async pipelines - chain operations naturally
userPipeline = asyncRun( () => fetchUser( userId ) )
    .then( user => validateUser( user ) )
    .then( user => enrichUserData( user ) )
    .then( user => cacheUser( user ) )
    .onSuccess( user => auditLog( "User processed: #user.id#" ) )
    .onError( error => logError( "Pipeline failed: #error.message#" ) );

// Advanced scheduling with natural syntax
schedule.task( "data-cleanup" )
    .call( () => cleanupExpiredData() )
    .everyDayAt( "02:00" )  // Every day at 2 AM
    .timezone( "America/New_York" )
    .onSuccess( result => writeLog( "Cleanup completed: #result.recordsDeleted# records" ) )
    .onError( error => sendAlert( "Cleanup failed: #error.message#" ) );

// Weekly reports on business days
schedule.task( "weekly-report" )
    .call( () => generateWeeklyReport() )
    .onFridays( "17:00" )
    .withNoOverlaps()
    .onSuccess( report => emailReport( report ) );

// One-time delayed execution
schedule.task( "send-reminder" )
    .call( () => sendReminderEmail( userEmail ) )
    .delay( 1, "hours" )  // Execute in 1 hour
    .onSuccess( () => writeLog( "Reminder sent successfully" ) );

// Complex parallel data processing pipeline
reportData = asyncRun( () => fetchRawData() )
    .then( data => asyncAllApply( data, row => processRow( row ) ) )
    .then( processedRows => aggregateResults( processedRows ) )
    .then( summary => generateReport( summary ) )
    .onSuccess( report => emailReport( report ) )
    .get();  // Block and get the final result

Enhanced BoxLang Mappings

Mappings now support an external flag (defaults to false) for better module organization and security. New zipparamsupport provides fine-grained control over ZIP operations:

zip( action="zip", file="myarchive.zip" ) {
    zipparam( source="folder1/", prefix="backup/" );
    zipparam( source="file.txt", entrypath="documents/readme.txt" );
}

Environment Variable Support (.env)

The BoxLang miniserver now supports .env files for configuration management:

# .env file
DATABASE_URL=jdbc:mysql://localhost:3306/mydb
API_KEY=your-secret-key
DEBUG_MODE=true

Enhanced ZIP Functionality

Enhanced support for complex nested grouping in queries and loops:

bx:loop( query="salesData", group="region,quarter" ) {
    writeOutput( "<h2>#region# - #quarter#</h2>" );
    
    bx:loop() {
        writeOutput( "<p>Sale: #amount# on #date#</p>" );
    }
}

Enhanced BoxLang Mappings

Mappings now support an external flag (defaults to false) for better module organization and security.

Miniserver Health Checks

Added simple health check endpoints for container-based deployments, making BoxLang more cloud-native.

Hidden File Protection

Basic protection against serving hidden files (dot files) in the miniserver for improved security.

🔧 Performance & Optimization Improvements

String Performance Enhancements

  • Significant performance improvements for toScript() BIF

  • Optimized string operations throughout the runtime

  • Better memory management for large string operations

Custom Component Lookup Optimization

  • Refactored custom component and class lookup for improved performance

  • Better caching mechanisms for frequently accessed components

  • Reduced overhead in component resolution

Module Class Visibility

  • Module classes are now properly visible to the context classloader

  • Improved module loading and initialization performance

JSON Processing Improvements

  • Removed JSON serialization limits

  • Enhanced JSON serialization of throwable objects

  • Better handling of complex object graphs in JSON serialization

🛠️ Language & Runtime Improvements

Enhanced Date/Time Handling

  • Support for more natural date parsing masks (case-insensitive)

  • Better timezone handling in DateTimeCaster

  • Improved CFML compatibility for partial years

  • Fixed issues with GregorianCalendar.getTime() return types

Improved Type Coercion

  • Skip type coercion for === operator (strict equality)

  • Better handling of Java arrays in modifiable contexts

  • Enhanced casting between BoxLang DateTime and Java Date types

Better Error Handling

  • Improved error messages in expression interpreter

  • Enhanced attempt.orThrow() handling

  • Better parsing errors for unclosed brackets

Array & Collection Enhancements

  • ArrayResize now accepts long values

  • Added missing max and min member functions

  • Fixed WriteDump errors on null array values

Query Improvements

  • Fixed query context issues in nested loops

  • Resolved queryDeleteColumn data integrity issues

  • Better handling of query serialization/deserialization

  • Support for queryObject.columnnames property

Regular Expression Enhancements

  • Fixed back reference handling (including references > 9)

  • Improved upper/lower case escapes in replacement text

  • Better support for complex regex patterns

🐛 Major Bug Fixes

JDBC & Database

  • Fixed race conditions in threaded query execution

  • Resolved nested transaction issues

  • Fixed savepoint name length limitations

  • Improved query caching with Redis integration

File Operations

  • Fixed cfcontent file corruption issues

  • Better handling of relative file paths in fileRead

  • Improved MIME type detection with strict mode

  • Enhanced multipart form handling

Session Management

  • Fixed SessionRotate and SessionInvalidate JSessionId handling

  • Better SameSite cookie attribute handling

  • Improved session shutdown cache interceptor

Component & Scope Handling

  • Fixed private static struct function access

  • Resolved scope access issues in custom tags

  • Better handling of thisComponent scope (renamed from thisTag)

Serialization & Casting

  • Fixed DeSerializeJSON strictMapping parameter

  • Better handling of Java primitive arrays

  • Improved object serialization in various contexts

🏗️ Architectural Changes

Dependency Updates

  • Updated Jackson-jr to latest patch version

  • Bumped semver4j from 5.8.0 to 6.0.0

  • Updated Apache Commons FileUpload to jakarta-servlet5

  • Updated Commons Text from 1.13.1 to 1.14.0

  • Updated Commons IO from 2.19.0 to 2.20.0

Code Organization

  • Refactored customTagsDirectory to customComponentsDirectory (with backward compatibility)

  • Renamed thisTag scope to thisComponent scope for consistency

  • Removed external JavaParser dependencies unless explicitly checked

Base64 & Encoding

  • Improved base64 string handling with padding tolerance

  • Better UTF-8 encoding support for multipart form data

  • Enhanced encoding handling across the platform

📚 New Documentation

We've significantly expanded our documentation with comprehensive new guides:

Comprehensive Asynchronous Programming Documentation

🎯 CFML Compatibility Improvements

This release includes numerous CFML compatibility enhancements:

  • Better parseDateTime compatibility with ACF

  • Improved handling of date masks and formatting

  • Enhanced numeric operations and casting

  • Better list BIF consistency across multi-character delimiters

🙏 Community & Contributors

This release represents months of hard work from our development team and valuable feedback from the BoxLang community. Thank you to everyone who reported issues, suggested improvements, and contributed to making BoxLang better.

Happy coding with BoxLang! 🚀


Release Notes

Improvement

BL-1517 Update the feature audit tool with the correct modules

BL-1518 Remove all JavaParser dependencies externally unless you check if it exists

BL-1565 improve error message on expression interpreter

BL-1566 Handle attempt.orThrow() better

BL-1571 Support some more natural date parsing masks which aren't case sensitive

BL-1577 lookup of custom componets and classes refactoring for performance

BL-1579 String performance and optimizations improvements for toScript() bif

BL-1581 Bump org.semver4j:semver4j from 5.8.0 to 6.0.0

BL-1601 avoid calling unputStream.available() due to FusionReactor bug

BL-1604 make module classes visible to context classloader

BL-1618 Update jackson-jr to latest patch

BL-1625 skip type coercion for === operator

BL-1636 default non-existent request bodies to an empty string

BL-1642 Ignore extra padding on base64 encoded strings

BL-1647 remove JSON serialization limit

BL-1648 Improve JSON serialization of throwable

BL-1651 org.apache.commons:commons-fileupload2-jakarta-servlet5

BL-1653 Re-organize and add validation to loaded miniserver config options

BL-1656 Bump org.apache.commons:commons-text from 1.13.1 to 1.14.0 (#288)

BL-1657 Bump commons-io:commons-io from 2.19.0 to 2.20.0

BL-1659 Re-instate parsing errors for unclosed brackets

Bug

BL-1214 Documentation of Image module

BL-1367 BX Compiler Issues

BL-1415 Cast error on BoxFuture.all()

BL-1496 Can't cast a Java Array to a modifiable Array.

BL-1539 DateFormat vs TimeFormat vs DateTimeFormat BIF Separations

BL-1548 Private static struct function not found

BL-1555 round does not accept second argument for number of places, despite being documented

BL-1562 Issue with clone when using zonedatetimes

BL-1564 dump template for Java class not handling static field

BL-1567 java boxpiler not always compiling array literal

BL-1568 JDBC - Unable to execute query in nested transaction unless outer transaction has a query that executes first

BL-1569 JDBC - Failed to set savepoint... is too long

BL-1570 date mask when parsing string dates

BL-1573 Fix for this scope access from function in custom tag

BL-1575 stack overflow in session shutdown cache interceptor

BL-1578 ToscriptTest not accounting for the timezone of the tests

BL-1580 ParseDateTimeTest using non timezone tests and would be unpredictable on certain conditions

BL-1582 bx:component is missing attributecollection argument

BL-1584 DateTimeCaster does not handle request timezones Zones correctly

BL-1585 CFML Compat with partial years

BL-1587 Different return type when calling `getTime()` on `java.util.GregorianCalendar`

BL-1588 StructSort numeric not sorting on values

BL-1589 Regular expression back reference is being ignored

BL-1592 ASM not compiling self-closing custom components the same as Java boxpiler

BL-1593 outer loop loses query context after inner loop

BL-1594 Issue with JSON serialization of dates in a BL class

BL-1596 session cookie - samesite handling

BL-1597 ArrayResize does not accept long

BL-1598 WriteDump Error on Null Array Values

BL-1606 Compat: DeSerializeJSON strictMapping ignored

BL-1607 SessionRotate and SessionInvalidate null out JSessionId

BL-1610 ACF parseDateTime compat

BL-1611 Casting ortus.boxlang.runtime.types.DateTime to java.util.Date

BL-1612 outer for loop loses query context with inner for loop

BL-1613 queryDeleteColumn deletes the column but not the data from the query object

BL-1615 fileRead should handle relative files

BL-1616 now isn't being cast to java.util.Date

BL-1620 Grouped looping is not showing expected output when not inner grouping

BL-1621 JDBC - Query caching into bx-redis throws 'failed to serialize object'

BL-1622 Httpparam formfield is adding a break line on values when multipart is true

BL-1623 FileGetMimeType with strict should be based on file content

BL-1624 Deserialized Query Columns are Invalid because they no longer contain query reference

BL-1626 DateTime does not properly deserialize because formatter is transient

BL-1627 val() with negative value returns 0

BL-1628 regex replacement backreferences greater than 9 don't wor

BL-1629 regex upper/lower case escapes should apply to all replacement text

BL-1630 JDBC race conditions present in threaded (or Future-ed) query execution

BL-1632 Zip includes target directory as first level parent.

BL-1633 queryObject.columnnames not supported

BL-1634 cfcontent is causing files to be corrupted

BL-1635 java double[] not handled by writeoutput / SerializeJSON

BL-1639 `max` and `min` member functions missing

BL-1641 list BIFs have inconsistent support for multiCharacterDelimiter

BL-1652 PlacehbolderReplacer was not using the String Caster when dealing with map bindings.

BL-1658 Servlet: Missing UTF-8 encoding for form fields with multipart/form-data

New Feature

BL-842 .env support for the BoxLang miniserver

BL-1464 implement nested grouped output/looping

BL-1515 Add zipparam support for ZIP functionality

BL-1525 BoxLang mappings need to have an extra definition: external which defaults to false

BL-1595 runAsync is the alias, the main method is asyncRun() so we can use the `asyncX` namespace

BL-1609 asyncAll, asyncAllApply, asyncAny bifs and constructs for parallel programming

BL-1654 Add simple health checks for miniserver, especially for container based loading

BL-1655 Basic hidden file protection in MiniServer

Task

BL-1576 Refactor customTagsDirectory to customComponentsDirectory and add shim to support it

BL-1637 Rename thisTag scope to thisComponent scope for consistency and transpile the old scope

Last updated

Was this helpful?