February 4, 2025
Language Enhancements in ColdFusion 2025 Release (Part 1)
Comments
(0)
February 4, 2025
Language Enhancements in ColdFusion 2025 Release (Part 1)
Guide 8 posts
Followers: 4 people
(0)

This blog provides an overview of the language enhancements introduced in the ColdFusion 2025 release. These enhancements aim to boost developers’ productivity by enabling them to achieve more with less code. In this blog, I will cover the major language enhancements along with corresponding code samples. 

This will be a series of blogs, each discussing multiple features. A link to the next blog will be added at the end of this blog. 

The ColdFusion 2025 release includes the following enhancements :

  • Query Of Query
  • Multi Assign Operators
  • Function Parameters Destructuring
  • Query Caching
  • Thread Functionality Enhancements
  • New Constructs : Trailing Commas and Multiple Exception Arguments in Catch Clause
  • Operators : Elvis and Null Coalescing
  • New Built In Functions (BIFs)
  • CFML Property can be Dynamic Expressions.

Query Of Query:

CFML Developers use Query Of Query when performing database operations involving data located in multiple databases. ColdFusion offers this capability by allowing data from various databases to be fetched into memory, where subsequent database operations can then be executed. 

This release supports the Modulus Operator (%) and Bitwise Operations. 

Modulus Operator (%)

Let’s simulate the QoQ modulus operator with a code snippet. 

<cfset myQuery = QueryNew('foo,bar','integer,varchar',[[40,'hello']]) >
<CFQUERY name="getQuery" dbtype="query">
select myQuery.foo %6 as res, myQuery.bar
from myQuery
</CFQUERY>
<cfset foo = getQuery.res>
<cfoutput>
<br>
#foo.toString()#
</cfoutput>
Output: 4

Bitwise Operations( & , | , ^ , ~ , << , >> )

Query Of Query supports Bitwise Operations on query columns. The following Bitwise Operations are available: 

  1. Bitwise And ( & )
  2. Bitwise Inclusive OR ( | )
  3. Bitwise Exclusive OR ( ^ )
  4. Bitwise NOT ( ~ )
  5. Bitwise Left Shift ( << )
  6. Bitwise Right Shift ( >> )
The examples code-snippets on how the operators can be used in Query Of Query are as shown below:
<cfset myQuery = QueryNew('foo,bar', 'integer,integer', [[3, 2]])>
<cfdump var = "#myQuery#">
<CFQUERY name = "getQuery" dbtype = "query">
select foo^bar as bitwiseXorRes, bar
from myQuery
</CFQUERY>
<cfdump var = "#getQuery#">
<cfset myQuery = QueryNew('foo,bar', 'integer,integer', [[3, 2]])>
<CFQUERY name = "getQuery" dbtype = "query">
select foo&bar as bitwiseAndRes, bar
from myQuery
</CFQUERY>
<cfdump var = "#getQuery#">
<cfset myQuery = QueryNew('foo,bar', 'integer,integer', [[3, 2]])>
<CFQUERY name = "getQuery" dbtype = "query">
select ~foo as bitwiseNotRes, bar
from myQuery
</CFQUERY>
<cfdump var = "#getQuery#">
<cfset myQuery = QueryNew('foo,bar', 'integer,integer', [[3, 2]])>
<CFQUERY name = "getQuery" dbtype = "query">
select foo|bar as bitwiseOrRes, bar from myQuery
</CFQUERY> 
<cfdump var = "#getQuery#">
<cfset myQuery = QueryNew('foo,bar', 'integer,integer', [[3, 2]])>
<CFQUERY name = "getQuery" dbtype = "query">
select bar<<1 as bitwiseLeftShift from myQuery
</CFQUERY>
<cfdump var = "#getQuery#">
<cfset myQuery = QueryNew('foo,bar', 'integer,integer', [[3, 2]])>
<CFQUERY name = "getQuery" dbtype = "query">
select bar>>1 as bitwiseRightShift, bar from myQuery
</CFQUERY>
<cfdump var = "#getQuery#">

Multi Assign Operators (+= , -= , *= , /= , &= , ^= , %= )

Developers can use multi-assign operators to both operate on a variable and reassign its value. Here are some examples: 

<cfscript>
a=3;
b=2;
writeOutput("+=<br/>");
c= (a+=b )<4;
writeOutput(a&" "&b&" "&c);
writeOutput("<br>");
c= ((a+=b )-3);
writeOutput(a&" "&b&" "&c);
writeOutput("<br/>"&"-=<br/>");

c= (a-=b )<4;
writeOutput(a&" "&b&" "&c);
writeOutput("<br>");

c= ((a-=b )+3);
writeOutput(a&" "&b&" "&c);
writeOutput("<br/>"&"*=<br/>");

c= (a*=b )<4;
writeOutput(a&" "&b&" "&c);
writeOutput("<br>");

c= ((a*=b )-3);
writeOutput(a&" "&b&" "&c);
writeOutput("<br/>"&"/=<br/>");

c= (a/=b )<4;
writeOutput(a&" "&b&" "&c);
writeOutput("<br>");

c= ((a/=b )-3);
writeOutput(a&" "&b&" "&c);
</cfscript>

Thread Functionality Enhancements:

The ColdFusion 2021 release has enhanced thread functionality to align with changes in JDK 21, which no longer supports stopping threads. To address this, we have implemented support for the graceful termination of threads via interrupts. It is important to note that interrupts operate on a best-effort basis and do not guarantee the immediate stopping of a thread.

The following changes have been done for CFThread:

  • Added methods InterruptThread(threadName) and isThreadInterrupted(threadName) to handle the functionality.
  • Tag Syntax: <cfthread action=“interruptname=“myThread”>
  • ThreadTerminate(threadName) method has been removed.

The code snippet below shows the enhanced functionality. The green-highlighted section outlines how a CFML developer can determine if a thread has been terminated and what actions to take afterward.

<cfscript>

//variables.message = "" testThreadName="T1" threadaction="run"name="#testThreadName#" {

count=0;

while(!isThreadInterrupted(testThreadName)){
variables.message=count++;
}
writeOutput("Thread #testThreadName# interrupted. exiting.");
}

writeOutput(now() &"<br>");
writeOutput("isInterrupted:"&isThreadInterrupted(testThreadName) &"<br>") //expect: no
sleep(1000) //let the thread above startup.

interruptThread(testThreadName);
writeOutput(now() &"<br>");
writeOutput("after interrupt, isInterrupted:"&isThreadInterrupted(testThreadName) &"<br>") //expect: yes

threadaction="join"name="#testThreadName#"{} // without this the status is intermittently RUNNING after interruption
writeOutput("Thread #evaluate(testThreadName).NAME# is
#evaluate(testThreadName).STATUS#<br>")

writeOutput("Thread output: #evaluate(testThreadName).OUTPUT#<br>") // after join
</cfscript>

Function Parameter Destructuring :  

Destructuring was introduced in ColdFusion 2021, but Function Parameters support was pending. For initial concepts on using Destructuring in CFML, please refer to the following blog .

The ColdFusion 2025 release includes completed support for Destructuring in ColdFusion Markup Language by incorporating Destructuring arguments in Function Parameters.

Function Destructuring provides a way of Unpacking properties from Objects passed as Function Parameters.

Syntax: 
function displaySummary( {name, scores: { maths = 0, english = 0, science = 0, social = 25} ){}

Function Parameters Destructuring solves many use-cases where-in the developers don’t need to do a check of whether the parameter(attribute) is being passed or not. Some of the common problems that it solves are:

  • Initialize Multiple parameters in one statement (CF_2021,CF_2023,CF_2018} = CFReleaseCN)
  • In case of missing variable, default values can be initialized(CF_2021,CF_2023,CF_2018,CF_2019=”Not Released in this year”} = CFReleaseCN)
  • Rename a variable if required({CF_2021,CF_2018,CF_2023:CF_LAST} = CFReleaseCN)
  • Filter out the essential attributes ignoring the others ({CF_2021,CF_2023,CF_2025, …outoFSupport} = CFReleaseCN)
  • Solves the ordering problems while passing the function parameters, using this a user can just pass the struct and it will filter out and unpack the essential attributes.

The code-snippets below are self explanatory:

<cfscript>
student = {
name: 'John Doe',
age: 16,
scores: {
maths: 74,
english: 63,
science: 85
}
};

// Without Destructuring
function displaySummary(student) {
writeOutput('Hello, '&student.name&'<br>');
writeOutput('Your Maths score is '& (student.scores.maths)&'<br>');
writeOutput('Your English score is '& (student.scores.english)&'<br>');
writeOutput('Your Science score is '& (student.scores.science)&'<br>');
writeOutput(student.age);
}

// With Destructuring
function displaySummaryWithDestructuring({name, scores: { maths = 0, english = 0, science = 0, social = 25}}) {
writeOutput('Hello, '&name&'<br>');
writeOutput('Your Maths score is '&maths&'<br>');
writeOutput('Your English score is '&english&'<br>');
writeOutput('Your Science score is '&science&'<br>');
writeOutput('Your Social score is '&social&'<br>');
writeOutput(age);
}

writeOutput("<b>Displaying the Details without Destructuring</b><br>");
writeOutput("<br>****************************<br>");
displaySummary(student);

writeOutput("<br>****************************<br>");
writeOutput("<br><b>Displaying the Details with Destructuring</b><br>");
writeOutput("<br>****************************<br>");
displaySummaryWithDestructuring(student);

writeOutput("<br>****************************<br>");
</cfscript>

<cfscript> function drawChart({ size="big", coords= { x: 0, y: 0 }, radius=25 }) { writeOutput("Size: ") writeoutput(size); writeOutput("<br>Coordinates: ") writeDump(coords); writeOutput("Radius: ") writeoutput(radius); } drawChart({ coords: { x: 18, y: 30 }, radius: 31 }) </cfscript>
<cfscript> 
CFReleaseCN= { CF_2025: "CF_NEXT", CF_2023: "Fortuna", CF_2021: "Project Stratus", CF_2018: "Aether", CF_2016: "Raijin" };


functionprintCFReleaseNames(CF_2025, CF_2023) { writeOutput("2025:"&CF_2025);
writeOutput("<br>****************************<br>");
writeOutput("2023:"&CF_2023);
writeOutput("<br>****************************<br>");
}

writeOutput("<br>****************************<br>");

//Ordering Matters Here
printCFReleaseNames(CFReleaseCN.CF_2025, CFReleaseCN.CF_2023);
printCFReleaseNames(CFReleaseCN.CF_2023, CFReleaseCN.CF_2025);

//Extract whats relevant and discard rest
functionprintCFReleaseNamesNew({CF_2025, CF_2023, ...rest}) {
writeOutput("2025:"&CF_2025);
writeOutput("<br>");
writeOutput("2023:"&CF_2023);
writeOutput("<br>");

writeOutput("<b>Older Versions:");
writeDump(rest);
}

writeOutput("<br>****************************<br>");
writeOutput("<br>");
printCFReleaseNamesNew(CFReleaseCN);
</cfscript>

Query Caching:

ColdFusion supports query caching with cachedafter and cachedwithin attributes. The ColdFusion 2025 release introduces a new attribute, cacheMaxIdleTime, in the CFQuery tag. 

  • The query can be cached if accessed within cacheMaxIdleTime. 
  • Unlike cachedwithin, which caches for a fixed time regardless of access frequency, cacheMaxIdleTime resets based on the last request. 
  • The attributes cachedafter, cachedwithin, and cacheMaxIdleTime can be combined in various ways for caching queries. 

The difference can be depicted by the image as shown below:

The attribute can be used as shown in the code below:

<cfset application.cachetm = CreateOdbcDateTime(dateformat(now(),'yyyy-mm-dd') & ' 23:20:20')/>
<cfquery datasource="mysql" name="RS" cachemaxidletime="#createtimespan(0,0,0,5)#" cachedafter="#application.cachetm#" MAXROWS="1">
SELECT 10 AS newColumn, id FROM sample
</cfquery>
<cfdump var ="#RS#">
<cfoutput>#now()#</cfoutput>

This concludes the Language Enhancement Blog 1, The remaining features are discussed here.

0 Comments
Add Comment