Breaking Changes between Lucee 7.0 and 7.1

edit

Breaking Changes between Lucee 7.0 and 7.1

This document outlines the breaking changes introduced when upgrading from Lucee 7.0 to Lucee 7.1.

Be aware of these changes when migrating your applications to ensure smooth compatibility.

Other Breaking Changes in Lucee Releases

Struct Key Ordering Changes

The internal ordering of keys in unordered (non-linked) structs has changed in Lucee 7.1. This means that serializeJSON() output for regular structs may produce keys in a different order than previous versions.

Any code that relied on unordered structs having a consistent key order may break (e.g. comparing serialized JSON strings, iterating keys, or generating cached markup).

Example:

var s = { "data": {}, "includes": ["a.js"], "adhoc": {} };
// 7.0: {"data":{},"includes":["a.js"],"adhoc":{}}
// 7.1: {"includes":["a.js"],"adhoc":{},"data":{}}

Workarounds:

  • Use StructNew("ordered") or StructNew("linked") if key order matters
  • Compare deserialized structs instead of raw JSON strings
  • Use structSort() or sorted keys when generating deterministic output
  • As a diagnostic, the lucee.concurrent.map.impl=legacy flag temporarily restores pre-7.1 ordering — flip it on to confirm whether breakage is genuinely an ordering-assumption bug in your code. See Diagnosing struct iteration-order regressions on 7.1 with `lucee.concurrent.map.impl=legacy`.

This change was made to improve struct performance (LDEV-5098).

QoQ SQL String Concatenation with NULL values

Previously, the HSQLDB-backed Query of Queries engine propagated NULL during string concatenation (like MySQL's CONCAT()) — 'foo' || NULL would return NULL. This caused rows with NULL values to be silently excluded from query results when using || or CONCAT() in WHERE clauses.

The native QoQ engine, which previously didn't support || or N-arg CONCAT() and fell back to HSQLDB.

Lucee 7.1 now treats NULL as an empty string during string concatenation in QoQ, matching Adobe ColdFusion behaviour, Oracle's || operator and SQL Server's CONCAT() function.

Examples using || operator:

-- Given a query with four rows: "", "123", NULL, "456"
SELECT name FROM qry WHERE CONCAT( ',', name, ',' ) NOT LIKE '%,123,%'
-- or
SELECT name FROM qry WHERE ',' || name || ',' NOT LIKE '%,123,%'
-- 7.0: returns 1 row (456) — ',' || NULL || ',' returns NULL, and NULL NOT LIKE '%..%' is NULL, not TRUE
-- 7.1: returns 3 rows ("", NULL, "456") — NULL is treated as empty string

Both || and CONCAT() are functionally identical — they now treat NULL as an empty string in both the native and HSQLDB engines.

If your code relies on NULL propagation in QoQ string concatenation, you may need to update your queries.

LDEV-6154

QoQ HSQLDB ORDER BY null position now matches native engine

The HSQLDB engine in Query of Queries sorted nulls first regardless of ASC or DESC direction, diverging from native QoQ and Adobe ColdFusion (which treat nulls as a low value: first ASC, last DESC). Lucee 7.1 aligns the engines.

Opt out of the new behaviour with lucee.qoq.hsqldb.orderBy.nullsLastInDesc=false (or LUCEE_QOQ_HSQLDB_ORDERBY_NULLSLASTINDESC=false).

LDEV-6311

REST request routing now uses specificity scoring

Cross-CFC REST dispatch in 7.0 returned the first match in disk-iteration order, which varied by filesystem. Lucee 7.1 picks the most-specific match (literal > regex-constrained > unconstrained path-var, longer > shorter, with deterministic tie-breaking) — matching JAX-RS rules. See REST Services with Lucee for the full rules.

Three knock-on effects to watch for:

  • Routes that 404'd because the wrong CFC won may now return 200 — audit overlapping restPath values, especially handlers that have been dead for years.
  • Two CFCs in the same mapping declaring the same restPath fail at registration with an ApplicationException naming both files. Pre-7.1 silently shadowed one.
  • Filename-ordering tricks (e.g. aDefault.cfc to exploit alphabetical iteration) no longer work — filenames are only used as a final tie-break.

LDEV-6306

See also