Comment on page
What's New With 7.2.0
November 18, 2023
Welcome to ColdBox 7.2.0, which packs a big punch on stability and tons of new features.

Version 7.2.0
A new helper has been born that assists you with dealing with Database Schema-related methods that are very common and core to ColdBox and supporting modules. This will grow as needed and be decoupled to its own module later.
hasTable()
hasColumn()
getDatabaseInfo()
getTextColumnType()
getDateTimeColumnType()
getQueryParamDateTimeType()
The
allApply()
is great when dealing with async operations on arrays or collections of objects. However, if something blows up, it would blow up with no way for you to log in or know what happened. However, now you can pass an errorHandler
argument which is a UDF/closure that will be attached to the onException()
method of the future object. This way, you can react, log, or recover.results = asyncManager.newFuture().allApply(
items : data,
fn : ( record ) => {
var thisItem = new tests.tmp.User();
thisItem.injectState = variables.injectState;
// Inject Both States
thisItem.injectState( protoTypeState );
thisItem.injectState( record );
return thisItem;
},
errorHandler : ( e ) => systemOutput( "error: #e.message#" )
)
All scheduled tasks now have a
group
property so you can group your tasks. This is now available when creating tasks or setting them manually.task( "email-notifications" )
.setGroup( "admin" )
.call( () => getInstance( "UserService" ).sendNotifications() )
.everyDayAt( "13:00" )
You can then get the group using the
getGroup()
method or it will be added to all task metadata and stats.A new period method shortcut:
everySecond()
. Very useful so you can fill up your logs with data.task( "heartbeat" )
.call( () => systemOutput( "data" ) )
.everySecond()
All task results, if any, are now stored in a ColdBox Optional. Which is a class that can deal with nulls gracefully and it's very fluent:
Optional
API Docs
A container object which may or may not contain a non-null value. If a value is present,
isPresent()
will return true
and get()
will return the value. Additional methods that depend on the presence or absence of a contained value are provided, such as orElse()
(return a default value if value not present) and ifPresent()
(execute a block of code if the value is present). See https://docs.oracle.com/javase/8/docs/api/java/util/Optional.htmlNew method to get the last result, if any, from a task via the
getLastResult()
method.var result = task.getLastResult().orElse( "nada" )
Lot's of great new methods and goodies so you can deal with date and times and timezones Oh My!
now( [timezone] )
getSystemTimezoneAsString()
getLastBusinessDayOfTheMonth()
getFirstBusinessDayOfTheMonth()
dateTimeAdd()
timeUnitToSeconds()
validateTime()
getIsoTime()
toInstant()
toLocalDateTime()
parse()
toLocalDate()
getTimezone()
getSystemTimezone()
toJavaDate()
duration()
period()
If in your binder you declare aspects or AOP bindings. Then WireBox will automatically detect it and load the AOP Mixer listener for you. You no longer have to declare it manually.
new cachebox.system.cache.CacheFactory( {
// LogBox Configuration file
logBoxConfig : "coldbox.system.cache.config.LogBox",
// Scope registration, automatically register the cachebox factory instance on any CF scope
// By default it registers itself on server scope
scopeRegistration : {
enabled : true,
scope : "application", // the cf scope you want
key : "cacheBox"
},
// The defaultCache has an implicit name of "default" which is a reserved cache name
// It also has a default provider of cachebox which cannot be changed.
// All timeouts are in minutes
// Please note that each object store could have more configuration properties
defaultCache : {
objectDefaultTimeout : 120,
objectDefaultLastAccessTimeout : 30,
useLastAccessTimeouts : true,
reapFrequency : 2,
freeMemoryPercentageThreshold : 0,
evictionPolicy : "LRU",
evictCount : 1,
maxObjects : 300,
objectStore : "ConcurrentSoftReferenceStore",
// This switches the internal provider from normal cacheBox to coldbox enabled cachebox
coldboxEnabled : false
}
} );
var logBox = new logbox.system.logging.LogBox(
{
appenders : { myConsoleLiteral : { class : "ConsoleAppender" } },
root : { levelmax : "FATAL", appenders : "*" },
info : [ "hello.model", "yes.wow.wow" ],
warn : [ "hello.model", "yes.wow.wow" ],
error : [ "hello.model", "yes.wow.wow" ]
}
);
When you declare categories in LogBox you usually choose the appenders to send messages to, but you could never exclude certain ones. Now you can use the
exclude
property:root : { levelmax : "INFO", appenders : "*", exclude: "slackAppender" },
categories = {
"coldbox.system" = { levelmax="WARN", appenders="*", exclude: "slackAppender" },
"coldbox.system.web.services.HandlerService" = { levelMax="FATAL", appenders="*", exclude: "slackAppender" },
"slackLogger" = { levelmax="WARN", appenders="slackAppender", exclude: "slackAppender" }
}
You now have two new event listeners that all LogBox appenders can listen to:
preProcessQueue( queue, context )
: Fires before a log queue is processed element by element.postProcessQueue( queue, context )
: After the log queue has been processed and after the listener has slept.
The
processQueueElement( data, context, queue )
now receives the entire queue as well as the queue
third argument.If you use the
RollingFileAppender
the default layout format of the archive package was static and you could not change it. The default is:#filename#-#yyy-mm-dd#-#hh-mm#-#archiveNumber#
Now you have the power. You can set a property for the appender called
archiveLayout
which maps to a closure/UDF that will build out the layout of the file name.
appenders : {
files : {
class : "RollingFileAppender",
properties : {
archiveLayout : variables.getDefaultArchiveLayout
}
}
}
function getDefaultArchiveLayout( required filename, required archiveCount ){
return arguments.fileName &
"-" &
dateFormat( now(), "yyyy-mm-dd" ) &
"-" &
timeFormat( now(), "HH-mm" ) &
"-#arguments.archiveCount + 1#";
}
The full release notes per library can be found below. Just click on the library tab and explore their release notes:
ColdBox HMVC
WireBox
CacheBox
LogBox
COLDBOX-1259 Complete rewrite of Scheduled Task setNextRuntime() calculations to account for start end running scenarios
COLDBOX-1263 Add an errorHandler to the allApply method so you can attach your own error handler to each future computation
COLDBOX-1246 casting to long instead of int when using LocalDateTime and plus methods to avoid casting issues.
COLDBOX-1254 getFirstBusinessDayOfTheMonth(), getLastBusinessDayOfTheMonth() now refactored to the dateTimeHelper
COLDBOX-1245 Scheduled task isConstrainted() on day of the month was calculating the days in month backwards
WIREBOX-61 Make
wirebox.system.aop.Mixer
listener load automatically if any aspects are defined/mappedLOGBOX-79 new rolling appender property
archiveLayout
which is a closure that returns the pattern of the archive layoutLast modified 9d ago