Common Issues When Migrating Between Adobe ColdFusion and Lucee
Mar 3 |

In the last several months, I have worked on getting Galaxie Blog to work with both ColdFusion and Lucee. There were quite a few issues found- Galaxie Blog is one of the largest open-source ColdFusion libraries with around 80k lines of ColdFusion code. I am nearly done with this project and wanted to share some significant roadblocks and solutions while porting ColdFusion and Lucee code. In this project, 98% of the code is identical between the two platforms, but surprises can catch you in unexpected places, and the biggest tip I have is to test everything thoroughly!
Table of Contents
- What is Lucee?
- Benefits of Lucee
- The Relationship Between Adobe and Lucee
- How to Programmatically Determine if You're Using ColdFusion or Lucee
- Differences Between ColdFusion and Lucee
- Boolean URL Values
- Caching
- CFProcessing Directives
- Cfdump Differences
- Cryptology
- Date Formatting Differences
- Dynamic Form Evaluation Within Functions
- File Functions
- JSON Differences
- JSoup Issues
- Lucee ORM Issues
- Lucee Offers WebP Image Support!
- Maximum Form Parameters
- Script Protection
- Too Many Connections Issue With Lucee and MySql
What is Lucee?
Lucee is the most popular open-source derivative of Adobe ColdFusion. Like Adobe ColdFusion, Lucee is a scripting language that excels at allowing the rapid development of web applications that compile to Java bytecode. The Lucee Association Switzerland developed Lucee initially based on a fork of Railo, which is no longer in active development.
Benefits of Lucee
Lucee's main benefit is that it brings most of Adobe ColdFusion's functionality to the open-source community. In contrast, Adobe ColdFusion has always been paid subscription-based software, while Lucee is free. Adobe has focused on offering extensive functionality and optimizing ColdFusion for enterprise clients.
Lucee has a much smaller codebase and generally offers improved performance. In my applications, including Galaxie Blog, Lucee is approximately 10-15% faster than Adobe ColdFusion. However, using caching in ColdFusion makes up for much of the speed disparity. Lucee, in addition to BoxLang, has also injected new ideas into the ColdFusion community.
The Relationship Between Adobe and Lucee
Some may assume that Adobe and Lucee are competing directly against each other. However, on the CFML Slack channel, Mark Takata, a ColdFusion evangelist working at Adobe, has publicly stated that he loves Lucee and frequently has backdoor communications with the Lucee team.
How to Programmatically Determine if You're Using ColdFusion or Lucee
I use the following logic to determine if I am using Lucee when I develop web applications that are intended to be used on both platforms:
<cfset serverProduct = server.coldFusion.Productname>
Differences Between ColdFusion and Lucee
The following is a list of issues I have had when migrating Galaxie Blog between ColdFusion and Lucee. Galaxie Blog is a substantial open-source library that I have authored; hopefully, this list is useful to you.
Boolean URL Values
In Lucee, you can't use a URL argument as a boolean value. For example, <cfif URL.valid> will fail.
Caching
Caching is problematic with Lucee when using cfcache. In my experience, Lucee does not seem to honor the cache key. Lucee will cache the specified area identically, even if the cache key differs. However, as I mentioned before, Lucee is faster than ColdFusion and seems to automatically cache the page when 'once' is selected in the performance/caching setting in the Lucee administrative site.
If you want to cache the same area differently depending on the device, you should omit using cfcache with Lucee. If you want extra performance, I will recommend other caching options for Lucee in a future article.
CFProcessing Directives
Each cfprocessingdirective must have a closing tag with Lucee. ColdFusion only requires one cfprocessing directive at the top of the page.
Cfdump Differences
Adobe ColdFusion's cfdump is more comprehensive. Lucee's dump does not show as much information and is prone to timing out when inspecting large ORM objects.
Cryptology
Lucee and ColdFusion handle cryptology differently. If you are porting the code from one platform to another with cryptology, test carefully.
It's important to note that the default hashing algorithm with Lucee is MD5, and you must use named arguments when hashing. If you're using hashing, you should change this and use another hashing algorithm, as MD5 is considered cryptologically broken.
Date Formatting Differences
I have noticed several minor differences with date formatting. According to the Lucee Docs, Lucee does not allow for implicit parsing of a date in the locale format. I have also noticed minor differences between the platforms with the date mask when using the dateAdd function. Check your code carefully when formatting dates when porting the code between platforms.
Dynamic Form Evaluation Within Functions
Lucee supports dynamic form validation within a function without corresponding arguments. ColdFusion doesn't and will fail when evaluating the dynamic values without function arguments.
Unfortunately, this requires that every value be specified in the function's arguments scope, increasing the number of parameters needed to be sent to the server.
The following code works when using Lucee but fails in ColdFusion:
<!--- This works inline within a funtion when using Lucee. With ColdFusion, all of the content templates need to be specified as function arguments --->
<cfset contentTemplates = "navigationMenu,aboutWindow,bioWindow,downloadWindow,downloadPod,subscribePod,cfblogsFeedPod,recentPostsPod, recentCommentsPod,categoriesPod,monthlyArchivesPod,compositeFooter">
<cfloop list="#trim(contentTemplates)#" index="i">
<cfset thisContentTemplateEnable = evaluate(i & 'Enable')>
<cfset thisContentTemplateThemes = evaluate(i & 'Themes')>
<cfset thisContentTemplateDesktopRevert = evaluate(i & 'DesktopRevert')>
<cfset thisContentTemplateMobileRevert = evaluate(i & 'MobileRevert')>
<cfset thisContentTemplateDesktopCode = evaluate(i & 'DesktopCode')>
<cfset thisContentTemplateMobileCode = evaluate(i & 'MobileCode')>
<!--- More code here... --->
</cfloop>
File Functions
File Functions such as fileRead, fileSave, etc, can use a variable to prefix the file functions in Lucee; however, using a variable with the file functions causes an error as the functions don't return a default value when using ColdFusion.
For example, in Lucee, <cfset file = fileRead(filePath)> works, whereas the same code will cause an error when using ColdFusion.
JSON Differences
JSON Serialization
Lucee Automatically serializes Data to JSON when using returnFormat="json" within a function. With ColdFusion, you must serialize the data when returning JSON.
<cffunction name="saveContentTemplate" access="remote" returnformat="json">
<!--- Code --->
<!--- Return statement --->
<cfif application.serverProduct eq 'Lucee'>
<!--- Do not serialize the response --->
<cfreturn Data>
<cfelse>
<!--- Serialize the response --->
<cfreturn serializeJSON( Data ) />
</cfif>
</cffunction>
Lucee Does Not Support the getMeta Method
The getMeta method, used to extract the column names in the proper case from the database, is not present in Lucee. However, in version 11, ColdFusion supports preserving the case when serializing data. You can set the 'Preserve case for Struct keys for Serialization' using the server administrator or inline arguments for Lucee and ColdFusion.
<!-- This function throws an error with Lucee. --->
<cfset realColumnList = arrayToList(queryObj.getMeta().getcolumnlabels())>
JSoup Issues
For some odd reason, ColdFusion and Lucee handle JSoup differently. I have had various errors when using the JSoups clean method in Lucee, even though the clean method is available when you dump the object or when using ColdFusion. If you're using JSoup, be sure to check every function as there may be unexpected behavior when using Lucee.
For example, the following code works in ColdFusion but raises an error in Lucee:
<!--- Init JSoup --->
<cfset JSoupObj = loadJSoup()>
<!--- Init the Safelist object. We need this for the clean method later on. This was named Whitelist. --->
<cfset SafelistObj = createObject("java", "org.jsoup.safety.Safelist")>
<!--- Sanitize the string. Note: this method is in the JSoup parent object. --->
<cfset sanitizedStr = JSoupObj.clean(arguments.str, SafelistObj.relaxed())>
"No matching method for org.jsoup.Jsoup.clean(string, org.jsoup.safety.Safelist) found. there are similar methods with the same name, but diferent arguments:
clean(string, org.jsoup.safety.Safelist);"
Lucee ORM Issues
While the Ortus ORM extension closely mimics Adobe ColdFusion (ACF) ORM functionality, there are differences.
First, after changing the persistent cfc's, Lucee does not always update the underlying database. On several occasions, I have had to change the mappings in the CFCs and manually create the changes in the database. When making design changes, I have also occasionally had to delete the underlying database tables and manually rebuild them. I have also had occasional issues with ACF ORM not updating the tables; however, it is rare and seems to happen more often on Lucee.
Use the Ortus Lucee ORM Extension
I could not get ORM to work using the native ORM in Lucee versions in Lucee 5.4.29 and below and had to use the Ortus ORM extension for Lucee 6+.
Lucee ORM Datasource Declaration
When using Lucee ORM, you may have to hardcode the data source declaration, whereas ColdFusion allows you to declare the data source using a dynamic variable.
I use the following code in Galaxie Blog:
<cfif getServerProduct() eq 'Lucee'>
<!--- For Lucee, this must be set manually (for the time being) --->
<cfset this.datasource = "GalaxieDb"><!--- GalaxieDb --->
<cfelse>
<!--- Get the datasource from the ini file. This is required as the database may not be set up yet prior to installing the blog and we need somewhere to store the db credentials. --->
<cfset this.datasource = getDsn()>
</cfif>
Null Values in Java HashMaps are Treated Differently
ColdFusion and Lucee handle null values differently; this is also true when dealing with Java HashMaps. Java HashMaps is the preferred way to return values from a query when using ORM, and you need a different code for Lucee and ColdFusion when testing for null values.
You can use the isDefined function to test for null values in the hashmaps with Lucee. However, isDefined is not supported with ColdFusion. Instead, use the structKeyExists to test for null values.
Ironically, the structKeyExists function causes an error when testing for null values in hashmap when using Lucee. I have not figured out how to use the same codebase for both platforms when testing for null values and have broken out the logic by platform.
The following code tests for null values in a Java Hashmap and will set the favIconHtmlApplyAcrossThemes variable to false if the column value is null.
<cfif application.serverProduct eq 'Lucee'>
<cfif isDefined("getTheme[1]['FavIconHtmlApplyAcrossThemes']") and len(getTheme[1]["FavIconHtmlApplyAcrossThemes"])>
<cfset favIconHtmlApplyAcrossThemes = getTheme[1]["FavIconHtmlApplyAcrossThemes"]>
<cfelse>
<cfset favIconHtmlApplyAcrossThemes = false>
</cfif>
<cfelse><!---<cfif application.serverProduct eq 'Lucee'>--->
<cfif structKeyExists(getTheme[1],"FavIconHtmlApplyAcrossThemes") and len(getTheme[1]["FavIconHtmlApplyAcrossThemes"])>
<cfset favIconHtmlApplyAcrossThemes = getTheme[1]["FavIconHtmlApplyAcrossThemes"]>
<cfelse>
<cfset favIconHtmlApplyAcrossThemes = false>
</cfif>
</cfif><!---<cfif application.serverProduct eq 'Lucee'>--->
Lucee Offers WebP Image Support!
Lucee's image version 2 extension now supports WebP image support. WebP is a relatively new image format that offers much better compression while retaining excellent image quality. ColdFusion still does not support this important image format, but Adobe has indicated that it will support this format in future ColdFusion editions. If you are using cfimage and ColdFusion and migrating to Lucee, you should consider leveraging WebP images in your workflow.
Maximum Form Parameters
ColdFusion only allows 100 form parameters to be posted to the server. If more than 100 parameters are sent, ColdFusion throws an error. ColdFusion has implemented this to combat potential hashdos attacks where a bad actor sends thousands of form parameters to ColdFusion to cause a denial of service. Pete Freitag, a well-known ColdFusion security expert, has an in-depth article at https://www.petefreitag.com/blog/understanding-hashdos/
Lucee has no form parameter restrictions; however, you can limit form parameters on the webserver.
Script Protection
Lucee handles script protection differently. Lucee is more restrictive with script protection than ColdFusion and will replace more tags with <invalidTag...></invalidTag>. For example, iframes are allowed with ColdFusion but are prohibited with Lucee.
Too Many Connections Issue With Lucee and MySql
While not technically a Lucee issue, most Lucee users prefer using MySql or MariaDB databases. If you use one of the MySql database flavors, you may run into too many connection-related errors, which will cause errors and consume a lot of server resources! This is because Lucee likes to reserve as many available database connections as possible and will exceed the available pool of connections on the database server.
To prevent this, set the Max Connections setting in Lucee to something lower than the database's default max connections setting. At this time, the default setting in MySql and MariaDb is 100, so you should set the Max Connections setting in Lucee to around 75. Alternatively, you can set the max connections setting higher on the server.
Further Reading
Tags
ColdFusion and Lucee
![]() |
Gregory Alexander |
Hi, my name is Gregory! I have several degrees in computer graphics and multimedia authoring, and I have been developing enterprise web applications for the last 25 years. I love web technologies and the outdoors and am passionate about giving back to the community. |
This entry was posted on March 3, 2025 at 10:58 PM and has received 187 views.