What's New With 4.0.0
Introduction
ColdBox 4 is a major release in our ColdBox Platform series and includes a new revamped MVC core and all extra functionality has been refactored into modules. We have pushed the modular architecture to a 1st class citizen even in the core itself. There are several compatibility updates that you must do in order to upgrade your ColdBox 3.X applications to ColdBox 4 standards. You will notice that the source and download of ColdBox 4 has been reduced by almost 75% in size. This is now due to our modular approach where functionality can just be brought in dynamically. How you might say?
CommandBox

CommandBox, our new ColdFusion (CFML) command line interface, package manager and REPL. You can now use CommandBox to install dependencies, modules and even ColdBox itself, all from our centralized code repository: ForgeBox. To install ColdBox 4 Bleeding Edge you can just type:
box install coldbox-be
You can even use CommandBox to generate ColdBox applications, modules, handlers, etc. It has a plethora of commands to get you started on a fantastic ColdBox Adventure:
// Get help on all the ColdBox commands
coldbox help
// create a ColdBox app with TestBox support
coldbox create app MyFirstApp --installTestBox
Internal Library Updates
ColdBox is composed of three internal libraries: WireBox (DI & AOP), CacheBox (Caching) and LogBox (Logging). Below you can find what's new with this release for each library:
Major Updates
Performance Updates
The core has been completely revamped by removing ColdFusion 7/8 code, decoupled from many features that are now available as modules and rewrites to pure cfscript
syntax. The end result is the fastest ColdBox release since our 1.0.0 days. In our initial vanilla load tests, normal requests take around 4-6ms to execute.
RunEvent Caching
The runEvent
method has been extended to include caching capabilities very similar to what has previously been available to the renderView
methods. This will allow folks to execute internal or widget-like events and be able to use the built-in caching capabilities of ColdBox to cache the results according to the arguments used. Below is the new signature of the method:
/**
* Executes events with full life-cycle methods and returns the event results if any were returned.
* @event The event string to execute, if nothing is passed we will execute the application's default event.
* @prePostExempt If true, pre/post handlers will not be fired. Defaults to false
* @private Execute a private event if set, else defaults to public events
* @defaultEvent The flag that let's this service know if it is the default event running or not. USED BY THE FRAMEWORK ONLY
* @eventArguments A collection of arguments to passthrough to the calling event handler method
* @cache.hint Cached the output of the runnable execution, defaults to false. A unique key will be created according to event string + arguments.
* @cacheTimeout.hint The time in minutes to cache the results
* @cacheLastAccessTimeout.hint The time in minutes the results will be removed from cache if idle or requested
* @cacheSuffix.hint The suffix to add into the cache entry for this event rendering
* @cacheProvider.hint The provider to cache this event rendering in, defaults to 'template'
*/
function runEvent(
event="",
boolean prePostExempt=false,
boolean private=false,
boolean defaultEvent=false,
struct eventArguments={},
boolean cache=false,
cacheTimeout="",
cacheLastAccessTimeout="",
cacheSuffix="",
cacheProvider="template"
){
Please note that the default cache provider used for event caching is the template cache, so it must be a valid ColdBox Enabled Cache Provider. So if we execute our sample widget below, we will be able to leverage its caching arguments:
<!--- Render with default cache timeouts --->
#runEvent( event="widgets.users", cache=true )#
<!--- Render with specific cache args --->
#runEvent( event="widgets.users", cache=true, cacheTimeout=60 )#
<!--- Render with specific event args --->
#runEvent( event="widgets.users", eventArguments={ filter:true }, cache=true, cacheTimeout=60 )#
Info : Internally ColdBox creates an internal hash of the passed in
event
andeventArguments
arguments for the cache key. It also leverages the template cache for event caching.
Model called Models
The convention has been updated so it matches the other conventions. You now must create a models folder instead of a model folder.
onInvalidHTTPMethod Handler Convention
We have created a new action convention in all your handlers called onInvalidHTTPMethod
which will be called for you if a request is trying to execute an action in your handler without the right HTTP Verb. It will then be your job to determine what to do next:
function onInvalidHTTPMethod( faultAction, event, rc, prc ){
return "Yep, onInvalidHTTPMethod works!";
}
HTTP Content Auto Marshalling
The getHTTPContent
method on the Request Context now takes in two boolean arguments:
json
xml
If set, ColdBox will auto-marshall the HTTP Body content from JSON or XML to native ColdFusion data types.
myStruct = event.getHTTPContent( json=true );
xmlObject = event.getHTTPContent( xml=true );
SES regex route placeholders
You can now define a-la-carte regex matching on route placeholders. If the route matches with that regex in the placeholder the value will now be stored in the RC as well:
addRoute( pattern = 'format/:extension-regex:(xml|json)' );
New Global View Helper
You now have a new ColdBox core setting viewsHelper
which is a template that will be injected and binded to any layout/view that is rendered. This means that finally you have a template that can be globally available to any view/layout in your system.
coldbox = {
viewsHelper = "includes/helpers/ViewHelper.cfm"
};
Application Template Java Support
All the new ColdBox application templates have been updated to include a folder called lib
which is automatically wired for you to class load Java classes and jars. All you have to do is drop any jar or class file into this folder and it will be available via createobject(“java”)
anywhere in your app.
New Core Modules
All internal plugins, and lots of functionality, have been refactored out of the ColdBox Core and into standalone Modules. All of them are in ForgeBox and have their own Git repositories. Also, all of them are installable via CommandBox; Our ColdFusion (CFML) CLI and Package Manager. This has reduced the ColdBox Core by over 75% in source size and complexity. Not only that, but it allows us to be able to release patches and updates for feature functionality without releasing an entire framework release, but just 1 or more modules.
ColdBox Debugger
box install cbdebugger
Storages
box install cbstorages
Feeds
box install cbfeeds
Commons
box install cbcommons
i18n
box install cbi18n
ORM
box install cborm
ioc
box install cbioc
JavaLoader
box install cbjavaloader
AntiSamy
box install cbantisamy
MailServies
box install cbmailservices
MessageBox
box install cbmessagebox
Soap
box install cbsoap
Security
box install cbsecurity
Validation
box install cbvalidation
New Anti-Forgery Module
We have created a nice anti-forgery module called csrf which can be found in ForgeBox and in GitHub: https://github.com/ColdBox/cbox-csrf. This module will enhance your ColdBox applications with Anti-Cross Site Request Forgery capabilities. You can also install it via CommandBox
box install csrf
ORM Module Updates
As you know by now, all the ColdBox ORM features are available as a module that can be installed in your application via CommandBox or downloaded separately. We have done several updates to the ORM extensions like:
Lucee multi-datasource support
Expanded
createAlias()
method to allow for a criteria argumentwhich leverages hibernate's ability to do a where statement on a
join
Script updates
New System Renderer
The ColdBox Renderer plugin has been removed and it is now part of the core as the system renderer (coldbox.system.web.Renderer
).
It has been migrated to full script and optimized for ColdFusion 9+
syntax
We have also created a new DSL to inject it via WireBox:
coldbox:renderer
You can also add mixins or alter its behavior by talking to its
WireBox mapping (
Renderer@coldbox
)All handlers/interceptors/views/layouts have access to the renderer
by calling the
getRenderer()
method in the super typeThe main ColdBox controller has a new method called
getRenderer()
to retrieve the system renderer
New Error Template
By default, we are now not showing any exceptions in the ColdBox default error template for security and encapsulation. You now have to specify the full exception bug template if you would like to see the exceptions via the CustomErrorTemplate
setting:
coldbox = {
customErrorTemplate = "/coldbox/system/includes/BugReport.cfm"
};
This is to be secure by default. The default template used is /coldbox/system/includes/BugReport-Public.cfm
Remote Proxies Autowired
You've always been able to get models in a remote proxy (web-accessible CFC that extends coldbox.system.remote.ColdBoxProxy
) using the getModel()
method. Now you can also autowire your remote proxies using cfproperties
just like you do in handlers and WireBox-managed models.
/remote/myProxy.cfc
component extends="coldbox.system.remote.ColdBoxProxy" {
property name='myService' inject='myService';
remote function doRemote() {
variables.myService.doSomething();
}
}
Note The autowiring only works for web-accessible remote proxies being directly invoked. You can extend the ColdBoxProxy by another manually-created CFC (such as an ORM eventHandler) but it won't be autowired.
Handlers Are Now Singletons
In pre-4.0.0 applications, all event handlers were cached in CacheBox with specific timeouts. We have found that this just created extra noise and complexity for handler CFCs. So now all event handlers will be cached as singletons by default (unless specified in the ColdBox.cfc
).
Bootstrap Enhancement
The ColdBox application bootstrapper, the one used in Application.cfc
has been completely updated and renamed to Bootstrap instead of Coldbox. This brings in lots of performance enhancements and faster startup times to your applications. Just use the included application templates or just update the Coldbox reference to Bootstrap.
// Inheritance
component extends="coldbox.system.Bootstrap"{
}
// Non-Inheritance
component{
public boolean function onApplicationStart(){
application.cbBootstrap = new coldbox.system.Bootstrap( COLDBOX_CONFIG_FILE, COLDBOX_APP_ROOT_PATH, COLDBOX_APP_KEY, COLDBOX_APP_MAPPING );
application.cbBootstrap.loadColdbox();
return true;
}
}
Module Enhancements
There has been tremendous focus on modules in this release as we have moved completely to a modular architecture in the core as well. First of all, we have moved almost 75% of the source into modules so they can be installed a-la-carte by developers. Here are some major updates:
New
getModuleSettings()
&getModuleConfig()
super type methods.This allows you to get access to any module setting or configuration
property rather easily and directly.
All module properties are NOT required anymore except the name.
Modules no longer register their models folder as scan locations
to increase performance.
try/catch around module unloads, so if a module throws an exception
during unload it will be intercepted, unloaded and then throw an
exception. This way it will allow developers to fix the unloading
issues instead of basically restarting the entire CFML engine to
make it work.
Module Inception
We have altered the module services to now allow you to nest modules within modules up to the Nth degree. Our final move to hierarchical MVC is complete. Now you can package a module with other modules that can even contain other modules within. It really opens a great opportunity for better packaging, delivery and a further break from monolithic applications. To use, just create a modules folder in your module and drop the modules there as well.
Module Config New Properties
The ''ModuleConfig.cfc'' has been updated with several new properties:
Setting
Type
Required
Default
Description
activate
boolean
false
true
You can tell ColdBox to register the module but NOT to activate it. By default, all modules activate.
aliases
array
false
[]
An array of names that can be used to execute the module instead of only the module folder name
autoMapModels
boolean
false
true
Will automatically map all model objects under the models folder in WireBox using @modulename
as part of the alias.
cfmapping
string
false
empty
The ColdFusion mapping that should be registered for you that points to the root of the module.
disabled
boolean
false
false
You can manually disable a module from loading and registering
dependencies
array
false
[]
An array of dependent module names. All dependencies will be registered and activated FIRST before the module declaring them.
modelNamespace
string
false
moduleName
The name of the namespace to use when registering models in WireBox. By default it uses the name of the module.
this.autoMapModels = true;
this.modelNamespace = "store";
this.aliases = [ "store", "ecommerce", "shop" ];
this.cfmapping = "cbstore";
this.dependencies = [ "JavaLoader", "CFCouchbase" ];
Module Dependencies
Modules can now declare other module dependencies. This means that before the declared module is activated, the dependencies will be registered and activated FIRST and then the declared module will load.
Module Aliases
In pre-4.0.0 ColdBox applications, the way that you executed module handlers was via its registered module name, which had to be the name of the module folder on disk. This was ok to a certain point, but it would cause issues as it was very restrictive to the name on disk. On ColdBox 4 you can now give the module different execution aliases so you can execute the handler events via the aliases and the module folder name as well.
Module CF Mappings
Every module can now tell ColdBox what ColdFusion mapping to register for it that points to the module root location on disk when deployed. This is a huge feature for portability and the ability to influence the ColdFusion mappings for you via ColdBox.
Module Models Auto Mapped
The entire models folder will now be automatically mapped for you in WireBox via the mapDirectory call with a namespace attached to the objects (the name of the module). This way, all models are automatically mapped for you so you can just use them. Let's say you have a module called store:
property name="orderService" inject="OrderService@store";
As you can see it adds a @moduleName
to discover models that come from a module directly.
Hint You can alter this behavior by setting the
this.autoMapModels
configuration setting tofalse
. You can also alter the namespace used via thethis.modelNamespace
configuration property.
Module Bundles
You can now bundle your modules into an organizational folder that has the convention name of {name}-bundle. This is mostly for organizational purposes.
coldbox-bundle
* cbstorages
* cborm
* cbsecurity
Last updated
Was this helpful?