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
andscheduler.log
files for complete observability of async operations
Core async primitives that change everything:
asyncRun()
- Transform any operation into a non-blocking future (withrunAsync()
as an alias)asyncAll()
- Execute multiple operations in parallel and aggregate results—no more callback hell or complex coordinationasyncAllApply()
- Map-reduce operations across collections in parallel with automatic work distributionasyncAny()
- 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 zipparam
support 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()
BIFOptimized 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()
handlingBetter parsing errors for unclosed brackets
Array & Collection Enhancements
ArrayResize
now acceptslong
valuesAdded missing
max
andmin
member functionsFixed
WriteDump
errors on null array values
Query Improvements
Fixed query context issues in nested loops
Resolved
queryDeleteColumn
data integrity issuesBetter 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 issuesBetter handling of relative file paths in
fileRead
Improved MIME type detection with strict mode
Enhanced multipart form handling
Session Management
Fixed
SessionRotate
andSessionInvalidate
JSessionId handlingBetter 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 fromthisTag
)
Serialization & Casting
Fixed
DeSerializeJSON
strictMapping parameterBetter 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
tocustomComponentsDirectory
(with backward compatibility)Renamed
thisTag
scope tothisComponent
scope for consistencyRemoved 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:
MiniServer Guide - Complete miniserver setup and configuration
Components Guide - In-depth component development
Transactions Guide - Database transaction management
XML Processing Guide - Working with XML in BoxLang
Property Files Guide - Configuration and property management
Testing Guide - Testing best practices and frameworks
Comprehensive Asynchronous Programming Documentation
Executors - Thread pool management
BoxFutures - Future-based programming
Async Pipelines - Chaining async operations
Parallel Computations - CPU-intensive parallel processing
Scheduled Tasks - Background task scheduling
🎯 CFML Compatibility Improvements
This release includes numerous CFML compatibility enhancements:
Better
parseDateTime
compatibility with ACFImproved 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?