> For the complete documentation index, see [llms.txt](https://boxlang.ortusbooks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://boxlang.ortusbooks.com/readme/release-history/1.4.0.md).

# 1.4.0

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.

## 🚀 Core Runtime Updates

### 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](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming), including detailed sections on [Executors](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/executors), [BoxFutures](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/box-futures), [Async Pipelines](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/async-pipelines), [Parallel Computations](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/parallel-computations), and [Scheduled Tasks](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/scheduled-tasks).

```js
// 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. All mappings in the global runtime config `boxlang.json` and those in the `Application.bx|cfc` are `external = true` by default, meaning they can be accessed via the URL.

All module mappings are `external = false` by default, meaning they are not accessible via the URL.

````js
// Default External Mapping
this.mappings[ "myInternalMapping" ] = "/abc/internal/path";
this.mappings[ "myExternalMapping" ] = {
    path: "/abc/external/path",
    external: true  // Indicates this mapping CANNOT be accessed via URL
};

### Enhanced ZIP Functionality

New `zipparam`support provides fine-grained control over ZIP operations:

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

### Loop Grouping Enhancements

BoxLang now supports complex nested grouping in queries and loops, allowing you to easily group data by multiple fields. This makes it simpler to generate reports and summaries directly in your templates.

```js
bx:loop( query="salesData", group="region,quarter" ) {
    writeOutput( "<h2>#region# - #quarter#</h2>" );

    bx:loop() {
        writeOutput( "<p>Sale: #amount# on #date#</p>" );
    }
}
```

## ⚡Miniserver Updates

Read all about the new miniserver features in our [MiniServer Guide](https://boxlang.ortusbooks.com/getting-started/running-boxlang/miniserver).

### Environment Variable Support (.env)

The BoxLang miniserver now supports `.env` files for configuration management. It will look for a `.env` file in the root of your project and load environment variables from it. This allows you to easily manage configuration settings without hardcoding them in your codebase.

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

### 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:

* [**MiniServer Guide**](https://boxlang.ortusbooks.com/getting-started/running-boxlang/miniserver) - Complete miniserver setup and configuration
* [**Components Guide**](https://boxlang.ortusbooks.com/boxlang-framework/components) - In-depth component development
* [**Transactions Guide**](https://boxlang.ortusbooks.com/boxlang-framework/transactions) - Database transaction management
* [**XML Processing Guide**](https://boxlang.ortusbooks.com/boxlang-language/syntax/xml) - Working with XML in BoxLang
* [**Property Files Guide**](https://boxlang.ortusbooks.com/boxlang-framework/property-files) - Configuration and property management
* [**Testing Guide**](https://boxlang.ortusbooks.com/extra-credit/testing) - Testing best practices and frameworks

### Comprehensive Asynchronous Programming Documentation

* [**Asynchronous Programming Overview**](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming)
* [**Executors**](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/executors) - Thread pool management
* [**BoxFutures**](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/box-futures) - Future-based programming
* [**Async Pipelines**](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/async-pipelines) - Chaining async operations
* [**Parallel Computations**](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/parallel-computations) - CPU-intensive parallel processing
* [**Scheduled Tasks**](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming/scheduled-tasks) - Background task scheduling

## 🎯 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

***

## Release Notes

### Improvement

[BL-1517](https://ortussolutions.atlassian.net/browse/BL-1517) Update the feature audit tool with the correct modules

[BL-1518](https://ortussolutions.atlassian.net/browse/BL-1518) Remove all JavaParser dependencies externally unless you check if it exists

[BL-1565](https://ortussolutions.atlassian.net/browse/BL-1565) improve error message on expression interpreter

[BL-1566](https://ortussolutions.atlassian.net/browse/BL-1566) Handle attempt.orThrow() better

[BL-1571](https://ortussolutions.atlassian.net/browse/BL-1571) Support some more natural date parsing masks which aren't case sensitive

[BL-1577](https://ortussolutions.atlassian.net/browse/BL-1577) lookup of custom componets and classes refactoring for performance

[BL-1579](https://ortussolutions.atlassian.net/browse/BL-1579) String performance and optimizations improvements for toScript() bif

[BL-1581](https://ortussolutions.atlassian.net/browse/BL-1581) Bump org.semver4j:semver4j from 5.8.0 to 6.0.0

[BL-1601](https://ortussolutions.atlassian.net/browse/BL-1601) avoid calling unputStream.available() due to FusionReactor bug

[BL-1604](https://ortussolutions.atlassian.net/browse/BL-1604) make module classes visible to context classloader

[BL-1618](https://ortussolutions.atlassian.net/browse/BL-1618) Update jackson-jr to latest patch

[BL-1625](https://ortussolutions.atlassian.net/browse/BL-1625) skip type coercion for === operator

[BL-1636](https://ortussolutions.atlassian.net/browse/BL-1636) default non-existent request bodies to an empty string

[BL-1642](https://ortussolutions.atlassian.net/browse/BL-1642) Ignore extra padding on base64 encoded strings

[BL-1647](https://ortussolutions.atlassian.net/browse/BL-1647) remove JSON serialization limit

[BL-1648](https://ortussolutions.atlassian.net/browse/BL-1648) Improve JSON serialization of throwable

[BL-1651](https://ortussolutions.atlassian.net/browse/BL-1651) org.apache.commons:commons-fileupload2-jakarta-servlet5

[BL-1653](https://ortussolutions.atlassian.net/browse/BL-1653) Re-organize and add validation to loaded miniserver config options

[BL-1656](https://ortussolutions.atlassian.net/browse/BL-1656) Bump org.apache.commons:commons-text from 1.13.1 to 1.14.0 (#288)

[BL-1657](https://ortussolutions.atlassian.net/browse/BL-1657) Bump commons-io:commons-io from 2.19.0 to 2.20.0

[BL-1659](https://ortussolutions.atlassian.net/browse/BL-1659) Re-instate parsing errors for unclosed brackets

### Bug

[BL-1214](https://ortussolutions.atlassian.net/browse/BL-1214) Documentation of Image module

[BL-1367](https://ortussolutions.atlassian.net/browse/BL-1367) BX Compiler Issues

[BL-1415](https://ortussolutions.atlassian.net/browse/BL-1415) Cast error on BoxFuture.all()

[BL-1496](https://ortussolutions.atlassian.net/browse/BL-1496) Can't cast a Java Array to a modifiable Array.

[BL-1539](https://ortussolutions.atlassian.net/browse/BL-1539) DateFormat vs TimeFormat vs DateTimeFormat BIF Separations

[BL-1548](https://ortussolutions.atlassian.net/browse/BL-1548) Private static struct function not found

[BL-1555](https://ortussolutions.atlassian.net/browse/BL-1555) round does not accept second argument for number of places, despite being documented

[BL-1562](https://ortussolutions.atlassian.net/browse/BL-1562) Issue with clone when using zonedatetimes

[BL-1564](https://ortussolutions.atlassian.net/browse/BL-1564) dump template for Java class not handling static field

[BL-1567](https://ortussolutions.atlassian.net/browse/BL-1567) java boxpiler not always compiling array literal

[BL-1568](https://ortussolutions.atlassian.net/browse/BL-1568) JDBC - Unable to execute query in nested transaction unless outer transaction has a query that executes first

[BL-1569](https://ortussolutions.atlassian.net/browse/BL-1569) JDBC - Failed to set savepoint... is too long

[BL-1570](https://ortussolutions.atlassian.net/browse/BL-1570) date mask when parsing string dates

[BL-1573](https://ortussolutions.atlassian.net/browse/BL-1573) Fix for this scope access from function in custom tag

[BL-1575](https://ortussolutions.atlassian.net/browse/BL-1575) stack overflow in session shutdown cache interceptor

[BL-1578](https://ortussolutions.atlassian.net/browse/BL-1578) ToscriptTest not accounting for the timezone of the tests

[BL-1580](https://ortussolutions.atlassian.net/browse/BL-1580) ParseDateTimeTest using non timezone tests and would be unpredictable on certain conditions

[BL-1582](https://ortussolutions.atlassian.net/browse/BL-1582) bx:component is missing attributecollection argument

[BL-1584](https://ortussolutions.atlassian.net/browse/BL-1584) DateTimeCaster does not handle request timezones Zones correctly

[BL-1585](https://ortussolutions.atlassian.net/browse/BL-1585) CFML Compat with partial years

[BL-1587](https://ortussolutions.atlassian.net/browse/BL-1587) Different return type when calling \`getTime()\` on \`java.util.GregorianCalendar\`

[BL-1588](https://ortussolutions.atlassian.net/browse/BL-1588) StructSort numeric not sorting on values

[BL-1589](https://ortussolutions.atlassian.net/browse/BL-1589) Regular expression back reference is being ignored

[BL-1592](https://ortussolutions.atlassian.net/browse/BL-1592) ASM not compiling self-closing custom components the same as Java boxpiler

[BL-1593](https://ortussolutions.atlassian.net/browse/BL-1593) outer loop loses query context after inner loop

[BL-1594](https://ortussolutions.atlassian.net/browse/BL-1594) Issue with JSON serialization of dates in a BL class

[BL-1596](https://ortussolutions.atlassian.net/browse/BL-1596) session cookie - samesite handling

[BL-1597](https://ortussolutions.atlassian.net/browse/BL-1597) ArrayResize does not accept long

[BL-1598](https://ortussolutions.atlassian.net/browse/BL-1598) WriteDump Error on Null Array Values

[BL-1606](https://ortussolutions.atlassian.net/browse/BL-1606) Compat: DeSerializeJSON strictMapping ignored

[BL-1607](https://ortussolutions.atlassian.net/browse/BL-1607) SessionRotate and SessionInvalidate null out JSessionId

[BL-1610](https://ortussolutions.atlassian.net/browse/BL-1610) ACF parseDateTime compat

[BL-1611](https://ortussolutions.atlassian.net/browse/BL-1611) Casting ortus.boxlang.runtime.types.DateTime to java.util.Date

[BL-1612](https://ortussolutions.atlassian.net/browse/BL-1612) outer for loop loses query context with inner for loop

[BL-1613](https://ortussolutions.atlassian.net/browse/BL-1613) queryDeleteColumn deletes the column but not the data from the query object

[BL-1615](https://ortussolutions.atlassian.net/browse/BL-1615) fileRead should handle relative files

[BL-1616](https://ortussolutions.atlassian.net/browse/BL-1616) now isn't being cast to java.util.Date

[BL-1620](https://ortussolutions.atlassian.net/browse/BL-1620) Grouped looping is not showing expected output when not inner grouping

[BL-1621](https://ortussolutions.atlassian.net/browse/BL-1621) JDBC - Query caching into bx-redis throws 'failed to serialize object'

[BL-1622](https://ortussolutions.atlassian.net/browse/BL-1622) Httpparam formfield is adding a break line on values when multipart is true

[BL-1623](https://ortussolutions.atlassian.net/browse/BL-1623) FileGetMimeType with strict should be based on file content

[BL-1624](https://ortussolutions.atlassian.net/browse/BL-1624) Deserialized Query Columns are Invalid because they no longer contain query reference

[BL-1626](https://ortussolutions.atlassian.net/browse/BL-1626) DateTime does not properly deserialize because formatter is transient

[BL-1627](https://ortussolutions.atlassian.net/browse/BL-1627) val() with negative value returns 0

[BL-1628](https://ortussolutions.atlassian.net/browse/BL-1628) regex replacement backreferences greater than 9 don't wor

[BL-1629](https://ortussolutions.atlassian.net/browse/BL-1629) regex upper/lower case escapes should apply to all replacement text

[BL-1630](https://ortussolutions.atlassian.net/browse/BL-1630) JDBC race conditions present in threaded (or Future-ed) query execution

[BL-1632](https://ortussolutions.atlassian.net/browse/BL-1632) Zip includes target directory as first level parent.

[BL-1633](https://ortussolutions.atlassian.net/browse/BL-1633) queryObject.columnnames not supported

[BL-1634](https://ortussolutions.atlassian.net/browse/BL-1634) cfcontent is causing files to be corrupted

[BL-1635](https://ortussolutions.atlassian.net/browse/BL-1635) java double\[] not handled by writeoutput / SerializeJSON

[BL-1639](https://ortussolutions.atlassian.net/browse/BL-1639) \`max\` and \`min\` member functions missing

[BL-1641](https://ortussolutions.atlassian.net/browse/BL-1641) list BIFs have inconsistent support for multiCharacterDelimiter

[BL-1652](https://ortussolutions.atlassian.net/browse/BL-1652) PlacehbolderReplacer was not using the String Caster when dealing with map bindings.

[BL-1658](https://ortussolutions.atlassian.net/browse/BL-1658) Servlet: Missing UTF-8 encoding for form fields with multipart/form-data

### New Feature

[BL-842](https://ortussolutions.atlassian.net/browse/BL-842) .env support for the BoxLang miniserver

[BL-1464](https://ortussolutions.atlassian.net/browse/BL-1464) implement nested grouped output/looping

[BL-1515](https://ortussolutions.atlassian.net/browse/BL-1515) Add zipparam support for ZIP functionality

[BL-1525](https://ortussolutions.atlassian.net/browse/BL-1525) BoxLang mappings need to have an extra definition: external which defaults to false

[BL-1595](https://ortussolutions.atlassian.net/browse/BL-1595) runAsync is the alias, the main method is asyncRun() so we can use the \`asyncX\` namespace

[BL-1609](https://ortussolutions.atlassian.net/browse/BL-1609) asyncAll, asyncAllApply, asyncAny bifs and constructs for parallel programming

[BL-1654](https://ortussolutions.atlassian.net/browse/BL-1654) Add simple health checks for miniserver, especially for container based loading

[BL-1655](https://ortussolutions.atlassian.net/browse/BL-1655) Basic hidden file protection in MiniServer

### Task

[BL-1576](https://ortussolutions.atlassian.net/browse/BL-1576) Refactor customTagsDirectory to customComponentsDirectory and add shim to support it

[BL-1637](https://ortussolutions.atlassian.net/browse/BL-1637) Rename thisTag scope to thisComponent scope for consistency and transpile the old scope


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://boxlang.ortusbooks.com/readme/release-history/1.4.0.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
