ColdBox HMVC Documentation
DocsSourceSupportTraining
6.x
6.x
  • Introduction
  • Intro
    • Release History
      • What's New With 6.11.0
      • What's New With 6.10.0
      • What's New With 6.9.0
      • What's New With 6.8.2
      • What's New With 6.8.1
      • What's New With 6.8.0
      • What's New With 6.7.0
      • What's New With 6.6.1
      • What's New With 6.6.0
      • What's New With 6.5.x
      • What's New With 6.4.0
      • What's New With 6.3.0
      • What's New With 6.2.x
      • What's New With 6.1.0
      • What's New With 6.0.0
      • Upgrading to ColdBox 6
    • About This Book
    • Author
  • For Newbies
    • 60 Minute Quick Start
      • Installing ColdBox
      • My First ColdBox Application
      • My First Handler & View
      • Linking Events Together
      • Working With Event Handlers
      • Adding A Layout
      • Adding A Model
      • RESTFul Data
      • Next Steps
  • Getting Started
    • Getting Started Guide
    • Installation
    • Conventions
    • Configuration
      • ColdBox.cfc
        • Configuration Directives
          • CacheBox
          • ColdBox
          • Conventions
          • Environments
          • Flash
          • InterceptorSettings
          • Interceptors
          • Layouts
          • LayoutSettings
          • LogBox
          • Modules
          • ModuleSettings
          • Settings
          • WireBox
        • System Settings (Java Properties and Environment Variables)
      • Using Settings
      • Bootstrapper - Application.cfc
  • The Basics
    • Request Context
    • Routing
      • Requirements
        • Rewrite Rules
      • Application Router
      • Routing DSL
        • Routing By Convention
        • Pattern Placeholders
        • Routing Methods
        • Resourceful Routes
        • Named Routes
        • Routing Groups
        • Routing Namespaces
      • Building Routable Links
      • RESTFul Extension Detection
      • HTTP Method Spoofing
      • HTML Base Tag
      • Pathinfo Providers
    • Event Handlers
      • How are events called?
      • Getting & Setting Values
      • Setting Views
      • Relocating
      • Rendering Data
      • Sending Files
      • Interception Methods
        • Pre Advices
        • Post Advices
        • Around Advices
      • Model Integration
        • Model Data Binding
      • HTTP Method Security
      • Implicit Methods
      • Executing Events
      • Executing Routes
      • Viewlets - Reusable Events
      • Event Caching
      • Validation
    • Layouts & Views
      • Views
        • Rendering Views
        • Rendering External Views
        • Rendering With Local Variables
        • Rendering Collections
        • View Caching
        • View Helpers
        • View Events
      • Layouts
        • Basic Layouts
        • Default Layout
        • Nested Layouts
        • Overriding Layouts
        • Layouts From A Module
        • Layout Helpers
        • Layout Events
      • Implicit Layout-View Declarations
      • Helpers UDF's
      • ColdBox Elixir
    • Models
      • Domain Modeling
        • Service Layer
        • Data Layers
        • Book
      • Conventions Location
      • WireBox Binder
      • Super Type Usage Methods
      • Injection DSL
        • ColdBox Namespace
        • CacheBox Namespace
        • EntityService Namespace
        • Executor Namespace
        • Java Namespace
        • LogBox Namespace
        • Models Namespace
        • Provider Namespace
        • WireBox Namespace
      • Object Scopes
      • Coding: Solo Style
        • Datasource
        • Contact.cfc
        • ContactDAO.cfc
        • ContactService.cfc
        • Contacts Handler
      • Coding: ActiveEntity Style
        • ORM
        • Contact.cfc
        • Contacts Handler
        • Views
      • Coding: Virtual Service Layer
        • ORM
        • Contacts.cfc
        • Contacts Handler
        • Views
      • Coding: ORM Scaffolding
        • ORM
        • Contacts.cfc
        • Scaffold
    • Interceptors
      • How do they work?
        • Conventions
      • Interceptor Declaration
      • Interceptor Registration
      • Dynamic Registration
      • Core Interception Points
        • Application Life Cycle Events
        • Object Creating Events
        • Layout-View Events
        • Module Events
        • CacheBox Events
      • Restricting Execution
      • Interceptor Output Buffer
      • Custom Events
        • Configuration Registration
        • Programmatic Registration
        • Listening
        • Announcing Interceptions
      • Unregistering Interceptors
      • Reporting Methods
      • Interceptor Asynchronicity
        • Async Announcements
        • Async Listeners With Join
        • Async Listeners No Join
        • Asynchronous Annotations
  • HMVC
    • Modules
      • Core Modules
      • Locations
      • Parent Configuration
      • Module Layout
        • Changing The Module Layout
      • Module Service
        • Module Lifecycle
        • Module Registration
        • Module Activation
        • Module Unloading
        • Common Methods
        • Loading New Modules
        • Loading A-la-carte Modules
        • Module Events
      • ModuleConfig
        • Public Module Properties
        • The Decorated Variables
        • The configure() Method
        • Module Settings
        • Environment Control
        • Interceptor Events
      • Module Event Executions
      • URL Routing
        • Default Route Execution
        • Module Routes Files
      • Module Async Scheduling
      • Request Context Module Methods
      • Layout and View Renderings
        • Layout/View Discovery
        • Overriding Views
        • Overriding Layouts
        • Default Module Layout
        • Explicit Module Renderings
      • Models
      • Module CF Mappings
      • Module Dependencies
      • Module Helpers
      • Module Bundles
      • Module Inception
  • Testing
    • Testing Quick Start
    • Testing ColdBox Applications
      • Test Harness
      • ColdBox Testing Classes
      • Common Testing Methods
      • Integration Testing
        • Life-Cycle Events
        • Request Setup()
        • The execute() Method
        • HTTP Testing Methods
        • Testing Without Virtual Application
        • Test Annotations
      • Interceptor Testing
      • Model Object Testing
      • Tips & Tricks
  • Digging Deeper
    • Async Programming
      • Async Pipelines & Futures
      • Parallel Computations
      • Executors
      • Scheduled Tasks
    • ColdBox Proxy
      • Getting Started
      • The Base Proxy Object
      • The Event Handlers
        • Distinguishing Request Types
        • RenderData()
      • Proxy Events
      • Standard Return Types
      • Caveats & Gotchas
    • Controller Decorator
    • Flash RAM
      • Flash Storage
      • Using Flash RAM
      • Creating Your Own Flash Scope
    • HTML Helper
    • REST Handler
    • Request Context Decorator
    • Recipes
      • Building REST APIs
      • Application Templates
      • ColdBox Exception Handling
      • Debugging ColdBox Apps
      • Clearing the View Cache
      • Basic HTTP Authentication Interceptor
    • Scheduled Tasks
  • Architecture Concepts
    • What is MVC
    • What is ColdBox
    • How ColdBox Works
    • Testing Concepts
      • Functional Testing
      • Non-Functional Testing
      • Bugs Cost Money
      • Static Testing
      • Dynamic Testing
      • Developer Focus
      • Testing Vocabulary
Powered by GitBook
On this page
  • Creation Methods
  • Usage
  • ColdFusion (CFML) App Context
  • Completed Futures
  • Usage Methods
  • Execution Status
  • Getting Values
  • Future Pipelines
  • Cancelling Futures
  • Exceptions
  • Combining Futures
  • Composing Futures

Was this helpful?

Edit on GitHub
Export as PDF
  1. Digging Deeper
  2. Async Programming

Async Pipelines & Futures

To The Future with ColdBox Futures

Last updated 5 years ago

Was this helpful?

Creation Methods

You will be able to create async pipelines and futures by using the following AsyncManager creation methods:

  • init( value, executor, debug, loadAppContext ) : Construct a new future. The value argument can be the future closure/udf. You can also pass in a custom executor and some utility flags.

  • newFuture( [task], [executor] ):Future : Returns a ColdBox Future. You can pass an optional task (closure/udf) and even an optional executor.

  • newCompletedFuture( value ):Future : Returns a new future that is already completed with the given value.

Please note that some of the methods above will return a ColdBox Future object that is backed by Java's CompletableFuture ()

Here are the method signatures for the methods above:

/**
 * Create a new ColdBox future backed by a Java completable future
 *
 * @value The actual closure/lambda/udf to run with or a completed value to seed the future with
 * @executor A custom executor to use with the future, else use the default
 * @debug Add debugging to system out or not, defaults is false
 * @loadAppContext Load the CFML engine context into the async threads or not, default is yes.
 *
 * @return ColdBox Future completed or new
 */
Future function newFuture(
    any value,
    any executor,
    boolean debug          = false,
    boolean loadAppContext = true
)

/**
 * Create a completed ColdBox future backed by a Java Completable Future
 *
 * @value The value to complete the future with
 * @debug Add debugging to system out or not, defaults is false
 * @loadAppContext Load the CFML engine context into the async threads or not, default is yes.
 *
 * @return ColdBox Future completed
 */
Future function newCompletedFuture(
    required any value,
    boolean debug          = false,
    boolean loadAppContext = true
)

Usage

There are two ways to start async computations with futures:

  1. Via the newFuture() constructor

  2. Via the run() method

The constructor is the shortcut approach and only allows for closures to be defined as the task. The run() methods allows you to pass a CFC instance and a method name, which will then call that method as the initial computation.

// Constructor
newFuture( () => newUser() )

// Run Operations
newFuture().run( () => newUser() )
newFuture().run( supplier : userService, method : "newUser" )

Here are the run() method signatures:

/**
 * Executes a runnable closure or component method via Java's CompletableFuture and gives you back a ColdBox Future:
 *
 * - This method calls `supplyAsync()` in the Java API
 * - This future is asynchronously completed by a task running in the ForkJoinPool.commonPool() with the value obtained by calling the given Supplier.
 *
 * @supplier A CFC instance or closure or lambda or udf to execute and return the value to be used in the future
 * @method If the supplier is a CFC, then it executes a method on the CFC for you. Defaults to the `run()` method
 * @executor An optional executor to use for asynchronous execution of the task
 *
 * @return The new completion stage (Future)
 */
Future function run(
    required supplier,
    method       = "run",
    any executor = variables.executor
)

Please note that the majority of methods take in an executor that you can supply. This means that you can decide in which thread pool the task will execute in, or by default it will run in the ForkJoinPool or the same thread the computation started from.

WARNING: Once you pass a closure/udf or cfc/method to the run() methods or the constructor, the JDK will create and send the task for execution to the appropriate executor. You do not need to start the thread or issue a start command. It is implied.

ColdFusion (CFML) App Context

The loadAppContext is a boolean flag that allows you to load the ColdFusion (CFML) application context into the running threads. By default, this is needed if your threads will require certain things from the application context: mappings, app settings, etc. However, some times this can cause issues and slowdowns, so be careful when selecting when to load the context or not. As a rule of thumb, we would say to NOT load it, if you are doing pure computations or not requiring mappings or app settings.

Completed Futures

There are also times where you need a future to be completed immediately. For this you can build a future already completed via the newCompletedFuture() or by leveraging the complete() function in the Future object. This can also allow you to complete the future with an initial value if you want to.

f = newCompletedFuture( 100 );

f = newFuture( () => orderService.getData() )
    .complete( initialValue )
    .then()
    .get()

Completed futures are great for mocking and testing scenarios

Usage Methods

There are many many methods in the Java JDK that are implemented in the ColdBox Futures. We have also added several new methods that play very nicely with our dynamic language. Here is a collection of the currently implemented methods.

Method

Returns

Description

all()

Future

Allows for the parallel execution of many closures/futures or an array of closures/futures.

allApply()

Collection

Allows you to apply a function to every element of a collection: array or struct and then reconstructing the collection according to your changes. A parallel map()

anyOf()

Future

Allows for the parallel/execution of many closures/futures or an array of closures/futures, but the only returning the FASTEST future that completes. The race is on!

cancel()

Boolean

If not already completed, completes this Future with a CancellationException.Dependent Futures that have not already completed will also complete exceptionally, with a CompletionException caused by this CancellationException.

complete()

Boolean

If not already completed, sets the value returned by get() and related methods to the given value.

completedFuture()

Future

Returns a new ColdBox Future that is already completed with the given value.

completeExceptionally()

Future

If not already completed, causes invocations of get() and related methods to throw the given exception. The exception type is of java.lang.RuntimeException and you can choose the message to throw with it.

exceptionally() onException()

Future

Register an event handler for any exceptions that happen before it is registered in the future pipeline.

Whatever this function returns, will be used for the next registered functions in the pipeline.

get()

any

Waits if necessary for at most the given time for this future to complete, and then returns its result, if available.

getNative()

Java CompletableFuture

Get the native Java CompletableFuture

getNow()

any

Returns the result value (or throws any encountered exception) if completed, else returns the given defaultValue.

isCancelled()

Boolean

Flag that checks if the computation has been cancelled

isCompletedExceptionally()

Boolean

Flag that checks if the computation threw an exception

isDone()

Boolean

Flag that checks if the computation has finished

run() runAsync()

supplyAsync()

Future

Executes a runnable closure or component method via Java's CompletableFuture and gives you back a ColdBox Future:

then()

thenApply()

Future

Executed once the computation has finalized and a result is passed in to the target

thenAsync()

thenApplyAsync()

Future

Executed once the computation has finalized and a result is passed in to the target but this will execute in a separate thread. By default it uses the ForkJoin.commonPool() but you can pass your own executor service.

thenCombine()

Future

This used when you want two Futures to run independently and do something after both are complete.

thenCompose()

Future

Returns a new CompletionStage that, when this stage completes normally, is executed with this stage as the argument to the supplied function.

withTimeout()

Future

Ability to attach a timeout to the execution of the allApply() method

Execution Status

Getting Values

Future Pipelines

Cancelling Futures

Exceptions

Combining Futures

Composing Futures

For example, the ColdBox file logger uses futures and has no app context loaded, since it does not require it. It only monitors a log queue and streams the content to a file. Remember, cohesion and encapsulation. The purerer your computations are, the better and safer they will be ()

Always checkout the API docs for the latest methods and signatures:

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html
https://en.wikipedia.org/wiki/Pure_function
https://apidocs.ortussolutions.com/coldbox/current