Data-Centric Development with ColdFusion 9 and Flash Builder 4

The second part of my Data-Centric Development with ColdFusion 9 and Flash Builder 4 tutorial is up on DZone. This tutorial builds on the project introduced in part one of the series and covers the new paging and client-side data management features available in Flash Builder 4.

Data-Centric Development with ColdFusion 9 and Flash Builder 4 - Part 2

If you want to find out even more about these seriously cool features be sure to check out the following links:

JSONUtil 1.1

Last year I put together JSONUtil as a proof of concept solution to the issue of ColdFusion's implicit type conversion during JSON serialization. There were some issues with the 1.0 release, and I've had a few people submit patches, but because I had considered the project an experiment I didn't really take the time to update the official release.

Well, last week I was working on an AJAX project where I was making XHR requests to ColdSpring remote proxies using ColdFusion's built in JSON return format when I began running into issues with implicit type conversion. Specifically I had a method that should have returned a query with string values, however numeric strings were getting converted to decimal numbers. (For example the string "001" was being converted to number 1.0.) Because I was already using ColdSpring to generate the proxies I decided to put together a JSONUtil based ColdSpring advice component to handle the serialization. The advice turned out being so handy I thought I'd package it up and include it in the JSONUtil release.

[More]

Another CFScript Query Gotcha

There have been a few issues reported with using the new Query component from cfscript and today I ran into another. Well actually I had a co-worker ask about it, but it still led me to look into the issue. (Little did I know he was researching his own blog post on this. Sorry for stealing your post Adam.) Anyway, my co-worker was trying to run a Query of Queries in cfscript. Here is an example:

<cfscript>
//create an empty query to work with qryFoo = queryNew("a,b,c","varchar,varchar,varchar");

//add a row and fill it with some data queryAddRow(qryFoo);
querySetCell(qryFoo,"a","aaaaaa");
querySetCell(qryFoo,"b","aaaaaa");
querySetCell(qryFoo,"c","aaaaaa");

writeDump(var=qryFoo, label="qryFoo");

qryFoo2 = new query(dbtype="query", sql="select a, 'bbbbb' as b, 'ccccc' as c from qryFoo");
result = qryFoo2.execute();

writeDump(var=result, label="qryFoo2");
</cfscript>

This code resulted in the following error:

Error Executing Database Query.

Query Of Queries runtime error. Table named qryFoo was not found in memory. The name is misspelled or the table is not defined.

At first I was a bit baffled, but when I thought about it for a minute it actually made perfect sense. The script functions implemented as CFCs are just the plain old CFML tags wrapped in components. That means when the cfquery tag actually executes it does so within the context and scope of the component function, not the calling page. To help illustrate the issue consider the following component:

<!--- sample.cfc --->
<cfcomponent>
<cffunction name="doDump">
<cfdump var="#myVar#" />
</cffunction>
</cfcomponent>

You wouldn't really expect the following code to work and it won't. You will get an error stating that myVar is undefined:

<cfset myVar = "This is a test." />
<cfset CreateObject("component","sample").doDump() />

That is basically what is going on with the query of queries example above. One workaround I thought of would be to put the original query in a scope the CFC can access, say the request scope:

<cfscript>
//create an empty query to work with request.qryFoo = queryNew("a,b,c","varchar,varchar,varchar");

//add a row and fill it with some data queryAddRow(request.qryFoo);
querySetCell(request.qryFoo,"a","aaaaaa");
querySetCell(request.qryFoo,"b","aaaaaa");
querySetCell(request.qryFoo,"c","aaaaaa");

writeDump(var=request.qryFoo, label="qryFoo");

qryFoo2 = new query(dbtype="query", sql="select a, 'bbbbb' as b, 'ccccc' as c from request.qryFoo");
result = qryFoo2.execute();

writeDump(var=result, label="qryFoo2");
</cfscript>

This works, but it is obviously less than ideal. Given all of the issues with the current Query.cfc I'm really hoping Adobe can come up with a better solution for full cfscript support in the next version of CF.

Update

Adam Cameron pointed out another solution in the comments below. Apparently you can use the setAttributes method of the Query object to set arbitrary attributes. I didn't realize this as the documentation states that this method supports "all attributes supported by the cfquery tag." But if you look at the implementation for the method you can see it just adds any attributes to the variables scope of the component:

public void function setAttributes()
      {
         if(!structisempty(arguments))
         {
            structappend(variables,arguments,"yes");
         }
      }

Here is a complete example using setAttributes:

<cfscript>
//create an empty query to work with qryFoo = queryNew("a,b,c","varchar,varchar,varchar");

//add a row and fill it with some data queryAddRow(qryFoo);
querySetCell(qryFoo,"a","aaaaaa");
querySetCell(qryFoo,"b","aaaaaa");
querySetCell(qryFoo,"c","aaaaaa");

writeDump(var=qryFoo, label="qryFoo");

qryFoo2 = new query(dbtype="query", sql="select a, 'bbbbb' as b, 'ccccc' as c from qryFoo");
qryFoo2.setAttributes(qryFoo=qryFoo);
result = qryFoo2.execute();

writeDump(var=result, label="qryFoo2");
</cfscript>

Note that there are thread-safety issues with this approach. If you do use setAttributes make sure you create a new instance of the service component for each service call.

Data-Centric Development with ColdFusion 9 and Flash Builder 4

I just posted the first of a two part tutorial over on DZone which walks through using some of the new data-centric development (DCD) features in Flash Builder 4 with ColdFusion 9.

Data-Centric Development with ColdFusion 9 and Flash Builder 4 - Part I

While Flash Builder is still in beta, the DCD features are very impressive and should simplify many ColdFusion/Flex work flows. Please check out the tutorial and let me know what you think. (And be sure to vote it up if you like it!)

New ColdFusion Builder and Flex Builder Betas

In addition to today's release of ColdFusion 9, ColdFusion Builder Beta 2 and Flex Builder 4 Beta 2 have been released on Adobe Labs.

ColdFusion 9 Released

ColdFusion 9 was released today. Go and get it!

http://www.adobe.com/products/coldfusion/

hf801-71643 Breaks Application Specific Custom Tag Paths

About a month ago Adobe released CHF 3 for ColdFusion 8. I was excited about this release because it fixed a bug that has caused quite a few headaches I'm sure, that being application specific custom tags not working under load. At work we recently deployed the cumulative hot fix to one of our production clusters only to find we were still seeing the "Cannot find CFML template for custom tag" error on a pretty consistent basis. Determined to get the bottom of the issue, today I installed CF 8 locally (another post on this later) and put together a quick test app that I could run JMeter against. Our production servers run a few other hot fixes in addition to the CHF so I had a feeling that one of the other hot fixes may be causing the issue. Sure enough, as I tested each hot fix in combination with CHF 3 I found that application specific custom tag paths started failing under load with hf801-71643 applied. That particular hot fix attempts to address some of the issues with CFC serialization to AMF (Flash Remoting) in CF 8. There are numerous issues with CFC serialization to AMF in ColdFuison 8 and hf801-71643 does not fix all of them, so we opted to remove it in favor of working custom tag paths. Anyway, I just thought I'd share this in case others have installed CHF 3 only to find they are still getting "Cannot find CFML template for custom tag" errors with application specific custom tag paths. If your still seeing this error be sure be sure to check the other hot fixes you have installed as they may be the culprit.

ColdFire Security Consideration

Given all the security issues around ColdFusion in the past few months I thought it would be good idea to remind ColdFire users about a potential security issue. One of the enhanced features of ColdFire is the ability to dump variables without changing your code. For example, to see the application scope you can just type "application" in the variables tab, reload the page, and there you have your application scope dumped to the ColdFusion Firebug tab. This is a great feature during development but could also be an attack vector if used on a public server. Imagine you were running ColdFire on a public server and storing something like database credentials in the application scope. Depending on the debugging IP addresses configured in the ColdFusion administrator, someone running the ColdFire Firebug extension could come along and dump the application scope and see those credentials. Anyway, this isn't really an issue with ColdFire, it works as intended, just something to be aware of if you use the tool.

Application Specific Custom Tag Paths Fixed in CHF3

As others have posted, ColdFusion 8.0.1 Cumulative Hot Fix 3 (CHF3) was released today. This hot fix contains a lot of new fixes, but I've been waiting for is this one:

Fix for the error "Cannot find CFML template for custom tag" thrown under load when using THIS.customtagpath in Application.cfc and "enable per app settings" is enabled.

In my testing before this hot fix I would see this error in about 8-10% of requests, even under what I would consider light load. After applying the hot fix and running the same JMeter tests I wasn't able to reproduce the issue.

Be sure to check the TechNote for a complete list of what's fixed in this release.

ColdFusion 9: onCFCRequest and Flash Remoting

ColdFusion 9 introduced the new onCFCRequest method. Unfortunately, this new method breaks Flash Remoting requests. To get around this issue you can resort to a modified version of the old onRequest hack. If you have an Application.cfc that covers remote components that will be used for Flash Remoting, you can add the following to your onRequestStart method:

<cffunction name="onRequestStart">
<cfargument name="targetPage" />

<cfif findNoCase("/flex2gateway",arguments.targetPage) gt 0>
<cfset structDelete(variables,"onCFCRequest") />
<cfset structDelete(this,"onCFCRequest") />
</cfif>

</cffunction>
This will remove the onCFCRequest method for the current request and allow your Flash Remoting call to work. (Note: you may need to search for different paths depending on your BlazeDS endpoint configurations. If you don't know what I'm talking about here you will most likely be fine with the default "/flex2gateway".)

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.