Monthly Archives: December 2009

ColdFusion FileSweeper

I’m tired writing scripts to clean up temporary files.

It’s a nigh trivial task. The chance for error is small, but the consequences can be dire!

DIRE!

DIRE!

I wrote a little utility that makes this a little easier. It simply deletes all the files in a folder (recursive or no) that are older than a specified number of seconds.

Example Usage:

// no init needed, but the function's there if you like
fileSweeper = CreateObject("component", "fileSweeper");   

// all arguments are actually defaulted to the values shown
// so you needn't pass any, fancy eh?
fileSweeper.deleteOldFiles(
    folder   = ExpandPath("/temp"),
    seconds  = 600,
    filter   = "*.*",
    recurse = "no",
    lockname = "deleteFiles",
    timeout  = 60,
    logging  = true
);

Download it!

ColdFusion serializeJSON Problem

I ran into a little problem with the CF8 serializeJSON function. The function doesn’t properly escape quotes in struct keys, which results in invalid JSON being generated.

For Example: (all code is in cfscript)

// Struct Key with quotes in it
heightCounts["6'0"""] = 5;

// Serialize function runs alright...
serialized = serializeJSON(heightCounts);

// But the JSON is invalid. The quotes are unescaped! 
writeOutput(serialized);
// => {"6'0"":5.0}

// As you might expect, deserializing throws an error
deserializeJSON(serialized);

I certainly don’t like the idea of having quotes in struct keys, but that’s beside the point. I filed a bug report, but I also wrote a little function to jsStringFormat my struct keys. Problem solved!

function cleanKeys(dirtyData) {
	var cleanData = structNew();
	var cleanKey = "";
	var i = "";

	if(!isStruct(dirtyData)) {
		return dirtyData;
	}

	for(i in dirtyData) {
		cleanKey = jsStringFormat(i);
		cleanData[cleanKey] = cleanKeys(dirtyData[i]);
	}

	return cleanData;
}

You just pass in your quote-fully keyed struct, and get a clean one back:

// Same example as above
heightCounts["6'0"""] = 5;

// This time we sanitize the struct keys
jsSafeHeightCounts = cleanKeys(heightCounts);

// The serializeJSON call still runs without error
serialized = serializeJSON(jsSafeHeightCounts);

// But this time the output is correct!
writeOutput(serialized);
// => {"6'0"":5.0}

// And the deserialize works as expected
deserializeJSON(serialized);

Ta Da!

Simple ColdFusion Feed Caching Manager

ColdFusion 8 added the cffeed tag, a great and simple utility for fetching and parsing rss and atom feeds. It’s a great and simple to use utility, but there are a couple of issues to keep in mind.

Every time you make a “read” call to an external source, you’re preforming an http request. Most feeds that I’ve pulled in aren’t updated more than a few times per week. Just using cffeed, even a modest hit count can quickly add up to thousands of unnecessary requests. Aside from the bandwidth, you’re fully at the mercy of that external server. Each request is potentially slow, invalid, or (ahem, Twitter) otherwise unavailable.

You can totally bypass these problems by simply caching a copy of the feed to diske, and then quickly and safely parsing that file as needed. If you can grab it once, then you’ll always have that information quickly available. I wrote a lightweight utility for doing just this. It’s simple, but it’s made my life so much easier that I thought I’d share.

First create and instantiate the feed manager.

  feedManager = createObject( "component", "feedManager" );
  feedManager.init( folder = absolutePathToSaveFeedFiles );

Then add the feeds, with unique keys for retrieval.

  feedManager.addFeedURL(
    key = "BLOG",
    url = "http://joezack.com/index.php/feed"
  );

  feedManager.addFeedURL(
    key = "CNN",
    url = "http://cnn.com/feed"
  );

Fetch and save the feeds to disk, if available and valid. I run this in a scheduled task, every hour or so.

  feedManager.cacheFeeds();

  // or to just cache one feed
  feedManager.cacheFeed("CNN");

Finally, to retrieve the cffeed parsed file, just call the getFeed method! So long as there has ever been a feed successfully retrieved, you’ll have data.

  // Request feed from disk.
  feed = feedManager.getFeed(key = "BLOG");

Download the file!