Bug When Passing Nested-Struct Data Into CFThread In ColdFusion 10
I know that Adobe ColdFusion 10 is no longer supported by Adobe. But, yesterday, I ran into a rather strange bug involving unreachable struct-data passed into a CFThread context; and, given the fact that other people out there may still be running ColdFusion 10, I figured it would be worth sharing.
From what I can see, there is something about the pass-by-value approach to ColdFusion threads that is causing nested-struct-keys to become unreachable. However, if you serialize the struct and log it, the keys show up in the serialization, plain as day. After bashing my head against a wall for 2-hours, I finally came up with a few simple "work arounds", none of which shed any light on to what is actually going wrong:
- Use the "attributes" scope to reference the passed-in value.
- Alias the passed-in value using a local variable.
- Run the passed-in value through a JSON serialization cycle.
- Run the passed-in value through duplicate().
To see this in action, I've created a simple proof-of-concept that passes a complex structure into a CFThread and then attempts to writeLog() one of the struct leaf-nodes. I am going to perform one writeLog() for each work-around.
<cfscript>
test();
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
public void function test() {
var data = {
b: {
c: {
d: "Third level value."
}
}
};
thread
name = "test-thread"
action = "run"
payload = data
{
writeLog( "D: " & payload.b.c.d );
// There seems to be something rather strange going on when you pass a
// nested struct into a CFThread context in which the nested keys become
// unreachable. However, you can work around this issue a few ways.
// First, you can simply use the explicit ATTRIBUTES scope to reference
// the structure. For whatever reason, this makes the keys work.
writeLog( "D (attributes): " & attributes.payload.b.c.d );
// Second, you can alias the value using a local variable.
var alias = payload;
writeLog( "D (alias): " & alias.b.c.d );
// Third, you can run the value through a serialization cycle.
writeLog( "D (json): " & deserializeJson( serializeJson( payload ) ).b.c.d );
// Fourth, you can duplicate the value.
writeLog( "D (duplicate): " & duplicate( payload ).b.c.d );
}
}
</cfscript>
As you can see, I'm attempting to log the same value, ".b.c.d" several times. And, when we run this code, we get the following ColdFusion log output (truncated for readability):
As you can see, the first attempt to reference "payload.b.c.d" results in an undefined value (which is showing up in the log as an empty string, but trust me that it is truly undefined if you try to use it). However, all of the subsequent attempts to reference the ".b.c.d" value - via the various work-arounds - work perfectly well.
From what I can see, key-casing isn't the issue. I've tried all manner of key variations, including using quotes to define the keys. None of it makes a difference. Honestly, I have no idea what is going on here. I'm just happy that I found a few ways to work around this problem in Adobe ColdFusion 10.
Want to use code from this post? Check out the license.
Reader Comments