> For the complete documentation index, see [llms.txt](https://coldbox.ortusbooks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://coldbox.ortusbooks.com/digging-deeper/promises-async-programming.md).

# Async Programming

ColdBox Promises, Executors, Async programming and Parallel Computations. Leverage the entire JDK arsenal for asynchronous pipelines, parallel workloads, and scheduled tasks.

## Introduction

ColdBox introduces the concept of asynchronous and parallel programming using Futures and Executors for both **BoxLang** and CFML. We leverage the entire arsenal in the [JDK](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/package-summary.html) to bring you a wide array of features for your applications. From the ability to create asynchronous pipelines, to parallel work loads, work queues, and scheduled tasks.

{% hint style="danger" %}
**YOU DON'T NEED COLDBOX TO RUN ANY SCHEDULED TASKS OR ANY FEATURES OF THE ASYNC PACKAGE. YOU CAN USE ANY OF THE STANDALONE LIBRARIES BY USING CACHEBOX, WIREBOX OR LOGBOX STANDALONE.**
{% endhint %}

![](https://content.gitbook.com/content/XMVfvHPJ9ZanT1mSFxLz/blobs/Q1cebUEe17HVmXdarqsE/async-programming.png)

Our async package `coldbox.system.async` is also available for all the standalone libraries: WireBox, CacheBox, and LogBox. This means that you can use the async capabilities in **ANY** BoxLang or CFML application, not only ColdBox HMVC applications.

{% hint style="success" %}
We leverage Java `Executors`, `CompletableFutures` and much more classes from the concurrent packages in the JDK: <https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/package-summary.html>
{% endhint %}

## 🚀 BoxLang Native Async Constructs

BoxLang, our preferred language, ships with its **own native, language-level async framework** - you don't need ColdBox's `AsyncManager` at all if you're not in a ColdBox app. It includes `futureNew()`/`BoxFuture`, `asyncRun()`, `asyncAll()`, `asyncAny()`, `asyncAllApply()`, `executorNew()`/`executorGet()`, the `thread` component, and a standalone `Scheduler.bx` + `boxlang.json` scheduling model. See the official reference: [BoxLang Asynchronous Programming](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming).

### Which One Should I Use?

| Scenario                                                                                                       | Preferred Approach                                                                                                                                                                                                                      |
| -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| You are inside a **ColdBox application** (BoxLang or CFML)                                                     | ColdBox `AsyncManager` (Futures, Executors, `config/Scheduler.cfc`). It integrates with the module lifecycle, DI container, environment/server-fixation constraints, and works identically whether you run on BoxLang or a CFML engine. |
| You are writing **plain BoxLang** outside of ColdBox (a script, a CLI tool, a microservice, another framework) | BoxLang's native `futureNew()`, `asyncRun()`, `asyncAll()`/`asyncAny()`/`asyncAllApply()`, `executorNew()`/`executorGet()`, and `Scheduler.bx` + `boxlang.json`. No framework dependency required.                                      |
| You need **I/O-bound concurrency** (HTTP calls, queries, file I/O)                                             | Virtual threads: ColdBox's `virtual` executor type, or BoxLang's pre-configured `io-tasks` executor.                                                                                                                                    |
| You need **CPU-bound concurrency** (image processing, encryption, heavy transforms)                            | A fixed pool: ColdBox's `fixed`/`cpuIntensive`-style executor, or BoxLang's `cpu-tasks` executor.                                                                                                                                       |

### Three Different Schedulers - Don't Mix Them Up

The word "scheduler" shows up in three unrelated places in our docs. Pick the row that matches where your code runs:

| Where you are                                                        | What to use                                                                                                                                  | Docs                                                                                                          |
| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Inside a **ColdBox application** (BoxLang or CFML)                   | The convention-based `config/Scheduler.bx` (app or module level), auto-registered and lifecycle-managed by ColdBox as `appScheduler@coldbox` | [ColdBox Scheduled Tasks](/digging-deeper/scheduled-tasks.md)                                                 |
| **Standalone WireBox/CacheBox/LogBox**, no ColdBox (BoxLang or CFML) | The core async package's `Scheduler` object, created manually via `AsyncManager.newScheduler()` and persisted by you                         | See below                                                                                                     |
| **Plain BoxLang**, no Ortus libraries at all                         | The native `Scheduler.bx` class registered in `boxlang.json`, or started with `schedulerStart()`                                             | [BoxLang Asynchronous Programming](https://boxlang.ortusbooks.com/boxlang-framework/asynchronous-programming) |

{% hint style="warning" %}
**Inside a ColdBox app, always use the ColdBox Scheduled Tasks layer** - the higher-level, convention-based API built for ColdBox HMVC apps. Don't call `AsyncManager.newScheduler()` directly there; that's the lower-level standalone API for non-ColdBox usage of WireBox/CacheBox/LogBox.
{% endhint %}

{% hint style="info" %}
Both engines end up calling into the same JDK `CompletableFuture`/`ExecutorService` machinery under the hood, so the concepts (futures, executors, schedulers) transfer directly between the ColdBox API and BoxLang's native API - only the entry-point functions differ.
{% endhint %}

## Sample Gallery

We have created a full sample gallery that we use in our live sessions and trainings. It contains tons of samples you can run and learn from: <https://github.com/lmajano/to-the-future-with-cbFutures>

{% embed url="<https://github.com/lmajano/to-the-future-with-cbFutures>" %}

## AsyncManager

We have created a manager for leveraging all the async/parallel capabilities. We lovingly call it the ColdBox `AsyncManager`. From this manager you will be able to create async pipelines, simple futures, executors and much more.

![Async Package Layout](https://content.gitbook.com/content/XMVfvHPJ9ZanT1mSFxLz/blobs/yzJbhIlEvb9jl9zAnibi/coldbox-async-packages.png)

### What are ColdBox Futures?

A ColdBox future is used for async/parallel programming where you can register a task or multiple tasks that will execute in a non-blocking approach and trigger dependent computations which could also be asynchronous. This Future object can then be used to monitor the execution of the task and create rich completion/combining pipelines upon the results of such tasks. You can still use a `get()` blocking operation, but that is an over simplistic approach to async programming because you are ultimately blocking to get the result.

ColdBox futures are backed by Java's `CompletableFuture` API, so the majority of things will apply as well; even Java developers will feel at home. It will allow you to create rich pipelines for creating multiple Futures, chaining, composing and combining results.

```javascript
// Parallel Executions
async().all(
    () => hyper.post( "/somewhere" ),
    () => hyper.post( "/somewhereElse" ),
    () => hyper.post( "/another" )
).then( (results)=> logResults( results ) );

// Race Conditions, let the fastest dns resolve
var dnsServer = async().any(
    () => dns1.resolve(),
    () => dns2.resolve()
).get();

// Process an incoming order
async().newFuture( () => orderService.getOrder() )
    .then( (order) => enrichOrder( order ) )
    .then( (order) => performPayment( order ) )
    .thenAsync(
        (order) => dispatchOrder( order ),
        async().getExecutor( "cpuIntensive" )
     )
    .then( (order) => sendConfirmation( order ) );

// Combine Futures
var bmi = async().newFuture( () => weightService.getWeight( rc.person ) )
    .thenCombine(
	    async().newFuture( () => heightService.getHeight( rc.person ) ),
        ( weight, height ) => {
            var heightInMeters = arguments.height/100;
            return arguments.weight / (heightInMeters * heightInMeters );
        }
    )
    .get();

// Compose Futures with exceptions
async()
    .newFuture( () => userService.getOrFail( rc.id ) )
    .thenCompose( ( user ) => creditService.getCreditRating( user ) )
    .then( (creditRating) => event.getResponse().setData( creditRating ) )
    .onException( (ex) => event.getResponse().setError( true ).setMessages( ex.toString() ) );
```

{% hint style="info" %}
See <https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html>
{% endhint %}

#### Why Use Them?

You might be asking yourself, why should I leverage ColdBox futures instead of traditional `cfthreads` or even the CFML engine's `runAsync()`. Let's start with the first issue, using ColdBox futures instead of `cfthread`.

#### `cfthread` vs ColdBox Futures

`cfthreads` are an oversimplification approach to async computations. It allows you to spawn a thread backed by a Java Runnable and then either wait or not for it to complete. You then must use the `thread` scope or other scopes to move data around, share data, and well it can get out of hand very quickly. Here are some issues:

* Too over-simplistic
* Threads limited on creation
* Cannot be completed manually
* No concept of a completion stage pipeline
* No control of what executor runs the task
* No way to trap the exceptions and recover
* No way to do parallel computations with futures
* No way to get a result from the computation, except by using a shared scope
* You must track, name and pull information from the threads
* etc.

You get the picture. They exist, but they are not easy to deal with and the API for managing them is poor.

![Runnables are Expensive](https://content.gitbook.com/content/XMVfvHPJ9ZanT1mSFxLz/blobs/dHaICnEHZbYOFneKxfmc/runnables.png)

#### `runAsync()` vs ColdBox Futures (Legacy CFML Engines)

Adobe ColdFusion 2018+ and Lucee 5+ both introduced the concept of async programming via their `runAsync()` function. Lucee also has the concept of executing collections in parallel via the `each(), map(), filter()` operations as well. However, there is much to be desired in these CFML-engine implementations. Here are a list of deficiencies:

* Backed by a custom wrapper to `java.util.concurrent.Future` and not Completable Futures
* Simplistic error handler with no way to recover or continue executing pipelines after an exception
* No way to choose or reuse the executor to run the initial task in
* No way to choose or reuse the executor to run the sub-sequent `then()` operations. Lucee actually creates a new `singleThreadExecutor()` for EVERY `then()` operation.
* No way to operate on multiple futures at once
* No way to have one future win against multiple future operations
* No way to combine futures
* No way to compose futures
* No ability to schedule tasks
* No ability to run period tasks
* No ability to delay the execution of tasks
* Only works with closures, does not work on actually calling component methods
* And so much more

{% hint style="success" %}
**BoxLang doesn't have any of these limitations.** Its native async engine (`futureNew()`, `asyncRun()`, `asyncAll()`, `asyncAny()`, `asyncAllApply()`, `executorNew()`) is built on real `CompletableFuture`s, supports combining/composing, timeouts, custom executors, virtual threads, and a full standalone scheduler - independent of ColdBox. See the "BoxLang Native Async Constructs" section above.
{% endhint %}

### What are Executors?

All of our futures execute in the server's common `ForkJoin` pool the JDK provides. However, the JDK since version 8 provides you a framework for simplifying the execution of asynchronous tasks. It can automatically provide you with a pool of threads and a simple API for assigning tasks or work loads to them. We have bridged the gap between Java and ColdFusion and now allow you to leverage all the functionality of the framework in your applications. You can create many types of executors and customized thread pools, so your work loads can use them.

![Fixed Thread Pool Executor](https://content.gitbook.com/content/XMVfvHPJ9ZanT1mSFxLz/blobs/sWVhYND7Cm5683i9U5Ph/fixedexecutor%20\(1\).png)

Some resources:

* <https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html>
* <https://www.baeldung.com/java-executor-service-tutorial>
* <https://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/>

### Injection/Retrieval

The manager will be registered in WireBox as `AsyncManager@ColdBox` or can be retrieved from the ColdBox main controller: `controller.getAsyncManager()`.

```javascript
property name="async" inject="asyncManager@coldbox";

controller.getAsyncManager();
```

The super type has a new `async()` method that returns to you the instance of the `AsyncManager` so you can execute async/parallel operations as well.

```javascript
function index( event, rc, prc ){
    async().newFuture();
}
```

###


---

# 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://coldbox.ortusbooks.com/digging-deeper/promises-async-programming.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.
