Twitter: raymondcamden


Address: Lafayette, LA, USA

Workarounds for things not supported in ColdFusion Script

04-07-2011 5,334 views ColdFusion 25 Comments

Yesterday a friend on twitter was upset by the fact there was no CFWDDX support within ColdFusion scripting. This got me thinking other things not yet supported and ways that developers can work around them. While scripting has gotten very close to being "100% complete" under ColdFusion 901, there are definitely a few things left you still cannot do (WDDX being one of them) and I thought a discussion about ho to handle that might be nice.

First though - remember that it can sometimes be difficult to see what is supported in scripting because some features aren't listed where you might expect them to be. Consider "try", as in cftry. If you look in the CFML Reference you will find documentation for cftry but see no mention of how to use try within script. You may be included to check the function listing, but it is not there. That's because the try command is a keyword, not a function. You can find a good list of these keywords in the documentation within the Developer's Guide: What is supported in CFScript. Unfortunately this page doesn't tell you how to use these keywords. So for example - consider cflocation. Here is an example of how it is used:

view plain print about
1location(url=group.getHomeUrl(),addtoken=false);

That's nice - but on the flip side, include, the script equivalent of cfinclude, works like so:

view plain print about
1include "render/blogpaneledit.cfm";

These are kind of documented here: Using system level functions But there is no mention of include, or try for that matter.

So that's keywords, but then you also things that are supported via new components. These components may be found in cfinstall\customtags\com\adobe\coldfusion. A documented list may be found here: Script Functions added in ColdFusion 9. These are detailed in the Reference: Script Functions Implemented as CFCs. Be sure to notice the link to the enhancements in 901: Script functions implemented as CFCs in ColdFusion 9 Update 1.

Speaking of 901, don't forget that support for handling file uploads, via fileUpload, as well as directory commands, were added in 901. These were both things that forced me to use tag based CFCs at times in CF9.

Ok - so I said this blog entry was about workarounds for things not supported. Hopefully though you check these docs first to ensure that what you want to do is actually impossible. I've used a few different workarounds in my development and at work. Here are a few examples.

1) What about cfsetting?

cfsetting has a few different options in it, but the one we use mostly is showdebugoutput="false". This is critical for pages that may serve up JSON or XML to remote clients. Unfortunately this is not possible to do in scripting. In the past, I've seen this workaround used:

view plain print about
1include "setting_debug.cfm";

The file, setting_debug.cfm, will have a grand total of one line - a tag based cfsetting. That kinda sucks. But it also means the calling CFC can stay in script. Since you typically only need one of these, the one hack by itself isn't so bad.

2) What about tags like wddx, etc, not supported?

You have a few options. For something like WDDX, it wouldn't take very long to write a UDF "wrapper" for the tag that handles serializing and deserializing WDDX strings. Once done, you can include this into your script based CFC or inject it like a service via your favorite dependency injection tool. This is the route I took for Adobe Groups and file uploads. I wrote Adobe Groups when CF9 was released. I had a few services that needed file operations, like uploading processing, so I simply wrote one tag based CFC to handle all file operations. It was a simple utility component that other services (fancy script based ones) could easily make use of. This wouldn't be necessary in 901.

Another route is to go the component route. Consider that cffeed was added in 901 as a component and not a new function. Unlike WDDX support, RSS parsing is somewhat more complex. Therefore it makes since to have a CFC/object based type approach to handle it. I helped write this component for Adobe. The code in that folder is all unencrypted and follows a standard style that you could mimic yourself. That's exactly what I did. I looked at Adobe's code for the other CFCs, wrote the feed support, and just stored it in the same directory. This gave me feed support in CF9. When 901 was released, I just removed my version.

Finally - don't forget you can file an enhancement request for things like this (script based version of cfwddx). If Adobe doesn't know that this is important to you, it won't be very high on their list of things to work on. The more you document, and vote, the easier it gets for Adobe to prioritize development.

Related Blog Entries

25 Comments

  • Commented on 04-07-2011 at 8:09 AM
    Cool approaches. One thing I have done is create a tag.cfc like so:

    tag.cfc:
    <cfcomponent>
    <cffunction name="cookie">
    <cfcookie attributeCollection="#arguments#">
    </cffunction>
    </cfcomponent>

    Then in the script do:
    tag=new tag();
    tag.cookie( name="cf", value="cool", httpOnly="true" );

    You can drop tag.cfc in the directory as you mention or define a folder in your app via custom tag mapping and put it in there.
  • Commented on 04-07-2011 at 8:12 AM
    Cookie is another good example. Thanks Sam.
  • Commented on 04-07-2011 at 8:32 AM
    Great stuff Ray. I didn't realize you had helped to write the port for cffeed. Very cool.

    Some time back I wrote a post about Extending the Server (http://blog.cutterscrossing.com/index.cfm/2009/10/...) that covered the basics of creating component objects for use across the entire server. I've lacked time, this past year, but think it would be great, as a community, to begin to fill in the gaps. Maybe Adobe could then use those projects as the basis for final implementation? Not sure of the best way to handle some of the smaller items, like cfsetting, but more complex tags, like cfsavecontent, might be really good candidates. I guess it's a matter of defining a standard convention, so that stuff isn't overly fragmented.
  • Commented on 04-07-2011 at 8:37 AM
    Dude - did you know savecontent is supported in script?
  • Commented on 04-07-2011 at 11:09 AM
    No, I didn't. I'll have to go check the docs on that. Was that added in 9.01?
  • Commented on 04-07-2011 at 11:13 AM
    Added in 9 (but hidden deep in the docs).

    Syntax:
    savecontent variable="local.content" {
          writeOutput(string);
          writeDump(arguments);
       }
  • Commented on 04-07-2011 at 1:29 PM
    It's not hidden - it's in one of the links above. However, the syntax is hidden, like most of the stuff.

    What we need is a blog post with all these new keywords and simple examples.

    Agreed?
  • Adam Cameron #
    Commented on 04-07-2011 at 3:15 PM
    Well, what we need is for Adobe to write the docs coherently.

    That would be better than a blog post. No dis' meant, Ray ;-)

    But a blog post would be more like to happen.

    Actually, if you were inclined to write something on this, a better approach would be to annotate livedocs rather than write something entirely separate & disconnected, wouldn't it?

    Do livedocs annotations get indexed by Google (etc)?

    --
    Adam
  • Commented on 04-07-2011 at 3:17 PM
    @Adam: I'm offended. You are not allowed to comment until you buy me another beer. ;)

    Um - I'm petty sure livedocs do get aggregated as they come up in my search. Do the comments? I don't know.

    I agree in general - but I'm not sure this would be appropriate for comments. May be a bit much for the context. Meh.

    I need to excuse to blog - and frankly - I forget myself. I use CFB Snippets for some things (like query in CFC form), so this could be useful to me.
  • Andy K #
    Commented on 04-07-2011 at 3:19 PM
    Hi Ray - FYI I tried to read this on my Droid X and I could not seem to get past this page:

    /www.coldfusionjedi.com/mobile/index.cfm

    Great stuff (as always!)
    Andy
  • Commented on 04-07-2011 at 3:25 PM
    Ping me via email please. The mobile version was updated yesterday - still has kinks to work out. If you can, tell me what you had clicked first, where you ended up, etc.
  • Commented on 04-07-2011 at 5:05 PM
    Looks like Ben's already got a good one pager on the new keywords:

    http://www.bennadel.com/blog/1663-Learning-ColdFus...

    Damn - and after I had written a little demo.
  • Commented on 04-07-2011 at 7:01 PM
    You should still post your entry Ray.

    Just because one person has posted something doesn't mean others can't! Plus I don't have to scroll as much on your entries! :)
  • Commented on 04-07-2011 at 10:32 PM
    how would you handle the group attribute of cfquery?
  • JP #
    Commented on 04-08-2011 at 12:16 AM
    I would love to see cfmodule implemented in script. Yes, I've still got a bunch of custom tags I use!!!
  • Commented on 04-08-2011 at 6:18 AM
    @Sam: Heh, I don't think I'd have anything better than his - but - I may share my CFB snippets. I made some as I had issues with remembering the syntax. To be honest, it is weird to me that same of these things work like this

    include "foo.cfm"

    and some work like so

    throw(.....)

    @Daria: You mean cfoutput don't you? If so - I don't believe you can handle that at all now. You would need to do it manually.

    @JP: In theory - you could build a UDF to replicate that. Need an example?
  • Adam Cameron #
    Commented on 04-08-2011 at 6:31 AM
    Mate, just keep a tally of how many beers you figure I owe you, and I'll see ya right next time you're across here (which is more likely than me being over there).

    Livedocs itself is indeed indexed by Google. Fortunately. Because Google does a much better job than Adobe's search engine (not that that is so different from most site's search engines, so no indictment of Adobe meant there).

    However the annotations are not indexed, unfortunately. I guess this is because - for reasons best known to themselves - Adobe load those as separate requests, rather than just do it as the main request. Sigh.

    I think there should be a separate section in the docs that covers the non-tag-implementations of all functionality as thoroughly as the existing reference covers the tags and the functions. And each should be cross-referenced to the other.

    But anyway.


    I too was bemused why sometimes various - seemingly equivalent - operations take parentheses, and others just quotes. It's the sort of non-uniformity CFML really doesn't need.


    Cheers for the heads-up from Sam re savecontent. I didn't know that. I think it's good it's there for completeness sake, but it's not very elegant compared to the tag analogue, is it?


    Grouped query looping using a for() would be bloody handy, I agree. It doesn't specifically mention gropupings, but there's an issue in the bug tracker for getting query-looping added to script. It might be worth voting / commenting on.

    --
    Adam
  • Commented on 04-08-2011 at 7:03 AM
    @Adam: re: savecontent
    I agree - it isn't elegant - but you don't normally do a lot of outputs in script anyway. I have used this in Adobe Groups though. A lot of the CMS is CFC driven, of course, and many of my CFCs need to generate output. Since my CFCs were script based and I didn't want a bunch of string ops, I did something like this:

    function renderPoo() {
    var result="";
    savecontent variable="result" {
    include template="poo.cfm";
    }
    return result;
    }

    So the savecontent keywords works great for me here. Certainly a rare use case for me, but I'm happy it's there.
  • Aaron DeRenard #
    Commented on 04-08-2011 at 10:11 AM
    @Ray

    I'm dying over here...

    I mean, renderPoo()? Really?

    ... ow, I feel like I'm laughing up some six pack abs ...

    Sorry for the comment that adds nothing to the topic. :-)
  • Commented on 04-08-2011 at 10:12 AM
    I turned 38 today. Unfortunately my maturity is still hovering around 12. On a good day.
  • Adam Cameron #
    Commented on 04-08-2011 at 10:14 AM
    Happy birthday matey.

    Add another beer to the list.

    --
    Adam
  • Commented on 04-08-2011 at 10:21 AM
    Thank you sir.
  • Commented on 04-09-2011 at 4:43 AM
    Many (belated) Happy Returns, Raymond (only 38?)

    Totally agree with Sam, you shouldn't worry about duplicating topics: if an issue's important to me, then the more perspectives I can get on it the better.
  • Commented on 04-09-2011 at 7:51 AM
    I'll post it up Monday.
  • Commented on 04-25-2011 at 8:49 AM
    I did post it on Monday. Just not the Monday I thought:

    http://www.coldfusionjedi.com/index.cfm/2011/4/25/...

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty