Friday, September 21, 2012

Undefined elements in structs returned from web service

I was accessing some functions remotely today in CF10 when I came across some weird behavior. Namely, the values returned by StructkeyList, StructkeyExists, and a Dump of a Struct are consistent with each other.

Take the following code and place it somewhere in a CFC to be accessed remotely.

    <cffunction name="getTest" output="no" returntype="struct" access="remote">

        <cfset result=structnew()>
                <cfset result.testvar = "some var">
                <cfset result.fuseactions = ArrayNew(1)>
        <cfreturn result>

Now access it from a calling page. You'll need to put in your own server and CFC name.

    returnvariable = "response"
    refreshWSDL = "true"

This is where it gets interesting. Let's do a dump of our return variable.

Notice that the "FUSEACTIONS" key in our struct seems interesting. Here we see "undefined" where we would have expected an empty array. I'm guessing the empty array goes missing during the serialization.

Ok, but let's go further. Let's do #structKeyList(response)# on the struct. We see, as expected, our two elements.

Now it gets strange. Try to do a StructKeyExists on the FUSEACTIONS key.


It delivers "NO". Trying to dump the struct element results in an error.

Now I know that the concept of NULL values was introduced in CF9. (Something I missed, still toddling along with CF8). So let's try:


Sure enough, it delivers YES.

Still, this seems a little weird to me. Intuitively I would expect to see an empty array inside the Struct, since that was how the variable was declared. In any case, the inconsistency between StructKeyExists and StructKeyList is a change from CF8 and it broke some old code of ours.

 I've filed this as bug 3334756 by Adobe. Let's see what they say.

Wednesday, September 12, 2012

filexists() with a url equals a hung request

I had a bug in one spot where a url was being given to the fileexists() function instead of an absolute path.
According to the documentation this should not work. Sure enough it really doesn't, but instead of returning NO the thread seems to hang. (CF 10 , version 10,282462). Not exactly sure why, more investigation is needed here.

I've never worked on version 9 before, but according to this thread, it was actually possible to do a fileexists on a url as of 9.0.1

Friday, September 7, 2012

getApplicationSettings() Part 2

In the last post I talked about the getApplicationSettings() method, and how we previously used it to look inside the application scopes of other applications in Coldfusion 8.  Well one of the first things I noticed when working with our application administration tool in CF10 is that this function changed in version 10, which was leading to errors.

That's the danger of relying too much on undocumented features!

Most specifically, in CF8 the getApplicationSettings returned us a struct, now it returns a class of  type coldfusion.runtime.ApplicationSettings.

This was rather bad for me, because in the old CF8 version the struct contained, among other things, a further struct with all the custom mappings for the application. A quick glance at the new object showed  that my mappings were nowhere to be found.

So now what? I created an object of type applicationScope and sniffed around.

 <cfset app = createObject("java","coldfusion.runtime.ApplicationScope") /> 
 <cfdump var="#app#">

The answer was pretty easy to find. The new getApplicationSettingsMap() function returns the struct that I used to use in CF8. One quick fix and my tool was back up and running.

Of course it is worth pointing out that this whole change probably happened because of the new getApplicationMetaData function, which gives me a "documented" way to get at some of the things I could only see through sneaky means in the past.

If you just need to see the meta data of the application of the calling template, use that instead.


Years ago we built an administration tool for our servers that allows us to view and administer all of the CF applications currently running. With it we reach into the application scope of each app and can do a number of things,  like refreshing objects cached in the application scope, clearing cached files, and so on.

Anyway, the key behind this magic is the ApplicationScopeTracker object, which lives in the coldfusion runtime.

<cfset apptracker = createObject("java","coldfusion.runtime.ApplicationScopeTracker") />

Above, I have created the variable "apptracker". Let's make a dump of this.

The only method I've ever really played around here with is getApplicationScope(). This function takes the name of an application as argument, and returns the entire application scope of that app.

<cfset appscope = apptracker.getApplicationScope('someappname') />
<cfdump var="#appscope#">

That will give you a dump of your entire application scope. I'll spare you a picture of that since my application scopes tend to be pretty big. :)

What you may not realize at first when looking at the dump though, is that actually we are dealing with an object of type coldfusion.runtime.ApplicationScope, and not a struct. To prove this we can execute a method on it.

<cfdump var="#appscope.getApplicationSettings()#">

And we see this:

Now these functions have been around a pretty long time, and they're  pretty well documented on a lot of other blogs around the web. They can be pretty useful too, although it's important to remember that when working with these  underlying java functions  we are using unofficial and  thus unsupported parts of the Coldfusion engine.

These functions are subject to change and sometimes do. In fact such a change gave me my first CF10 "ouch", which I'll get to in the next post.

The Upgrade

Where I work in Frankfurt there is a lot of Coldfusion. In fact we're probably one of the biggest Coldfusion users in Germany. For the last few years we've been using CF8, but that will be changing during our upcoming upgrade to CF10.

I'm creating this blog to track our experiences for this big leap!