CFML Request Parameters

If you've worked with ColdFusion (or CFML) for very long, you've probably noticed that CFML's treatment of request parameters is a little unorthodoxed.  Specifically, it doesn't differentiate between multiple instance of the same parameter being passed.  Consider this url:

page.cfm?a=1&a=2&a=3,4&b=5

As you can see, there are three instances of the 'a' parameter, one of which has a value that contains a comma.  In CFML-land, you're going to get a single value:

url.a == "1,2,3,4"

Uh oh.

Fortunately, the Servlet Specification comes to our rescue.  You can use getParameterValues on the ServletRequest object to get back an array of values:

getPageContext().getRequest().getParameterValues("a") == ["1", "2", "3,4"]

For a more complete series of examples, check out http://barneyb.com/r/params.cfm.  Note that the Servlet spec doesn't differentiate between query string and POST parameters, while CFML does (via the url and form scopes).  If you ask me, however, you shouldn't either.  They're all just parameters - treat them as such.

ColdFusion Struct Literals Are Not Thread Safe (CFML Ones Are)

If you read my blog regularly or follow me on Twitter, you know how much I hate Adobe's quasi-implementation of struct (and array) literals.  I'm really hoping "third time's a charm" and CF9's implementation is sane.  The gripe is that this code:

<cfset s = {
  name = "barney",
  age = 29
} />

is executed as if it were written like this (on Adobe ColdFusion):

<cfset s = structNew() />
<cfset s.name = "barney" />
<cfset s.age = 29 />

The "correct" behaviour is to execute it as if it were written like this (which is how Railo does it):

<cfset temp = structNew() />
<cfset temp.name = "barney" />
<cfset temp.age = 29 />
<cfset s = temp />

This lets you write some really nasty code, causes some weird bugs, and today I realized (through some handy errors on our production cluster) that there are thread safety issues as well.   Consider this code (inside a getCacheForKey() method):

<cfif NOT structKeyExists(key_stats_cache, key)>
<cflock name="getCacheForKey.#key#" type="exclusive" timeout="1">
<cfif NOT structKeyExists(key_stats_cache, key)>
  <cfset key_stats_cache[key] = {
    getCount = 0,
    staleGetCount = 0,
    missCount = 0
  } />
</cfif>
</cflock>
</cfif>

If the struct literal were an expression, this code would be thread safe, because the assignment to 'key_stats_cache[key]' would be atomic.  However, because of the way ColdFusion implements it, it's not thread safe.  It's possible to have the existence checks trigger in a second request while the struct is building in the first request, and therefore some keys will not be present after the outer </cfif> tag of a second request.  Wrapping the outer <cfif> tag with a read-only CFLOCK will address the issue, of course, but if struct literals were implemented as expressions (the second behaviour above), the problem could never manifest itself.  So watch out!  Atomicity of assignment statements is not assured.

Riddle Me This, CFLOOP

Take this simple loop:

<cfloop from="1" to="10" index="i">
  #i#<br />
  <cfif i EQ 3>
    <cfset i += 3 />
  </cfif>
</cfloop>

What is the output?  My answer is the numbers 1-3 followed by 7-10.  But I was dismayed to learn this evening that it doesn't seem to be the case on my server.  There it outputs 1-10 with no breaks.  Can someone please confirm that this is NOT normal behaviour?  I'm running CF 8,0,1,195765 on x64 CentOS 5 (kernel 2.6.18-128.1.6.el5) with 64-bit Java 1.6.0_13.

Update: Clearly I'm just retarded.  It works this way on Windows, on Railo, and everyone else confirms this is known behaviour.  Somehow I've gone 10 years without running into this issue, probably because I always revert to CFSCRIPT when I do "weird" looping.

That syntax above is analogous to collection iteration (in Groovy):

(1..10).each { i ->
  println(i)
  if (i == 3) {
    i += 3
  }
}

It is NOT analogous to this for loop (also in Groovy):

for (i = 1; i <= 10; i += 1) {
  println(i)
  if (i == 3) {
    i += 3
  }
}

Weird.

An Ink Free Year

Yesterday I turned 29.  One year older on the clock, and about 20 years older in effect.  I'd planned on getting a leaf tattooed on my right calf as a birthday present, but like so much else, it didn't work out.  Since I turned 18, I've gone and had birthday tattoos more than half the years.  Never on my actual birthday, but as my present to myself when scheduling allowed.  I've been to a few shops here in Portland, but never felt right in one.  Last year I got my stars (my only tattoo since moving back from Bellingham) in Seaside where I got my first sword a day shy of 11 years ago.

That same day 11 years ago, Andrew Nygaard died at the Seaside pool.  He got hit in the chest by a medicine ball while doing dryland exercises after practice, died, crumpled to the deck, and never came back.  This year has the same week pattern as 1998: my birthday on Wednesday and the 12th on Friday.  I was just back to the pool in time to see the ball slip through his hands and watch him crumple to the deck through the office windows and down the length of the pool.  I still remember my first reaction: someone has to ensure the medics get from their ambulance to him as directly as possible, and no one is going to think about that.  So while everyone rushed about their business, I sat on the bench outside and waited to direct them through the correct door upon their arrival.  It's was fucking weird, but I was correct that no one else bothered to come outside.

The marks on my body are my own.  All put there by others, but they're there for me, even though I can't see most of them without a mirror.  Every time June rolls around, I think of my sword and Andrew.  And of Judy, his mom.  I skipped practice that day.  It was a chaotic time.  Just graduated from high school.  Off to Arizona on a swimming scholarship.  I barely swam that whole month.  I barely did anything that whole month.  It was a weird time.

It was a time of floating, like that split second when the clutch is all the way in as you slide from one gear to the next.  Everything was in flux.  Probably the case for most high school graduates who know they're shipping off to some remote college.  I feel like that again.  There is nothing here for me except responsibilities I have to fulfill until life slides into gear again.  I just hope it's not shifting from 5th -> reverse.

jQuery TableSorter Comma Parser

Last night I needed a simple HTML table with sortable columns, and after a quick Googling, found the TableSorter jQuery plugin.  I'd come across it before, but never actually used it.  Added a class to my table (for targeting and to leverage the CSS that it comes with), added the required line of JavaScript to initialize it, and I was up and running.

As I tuned the presentation, however, I ran into a couple issues.  First, the included styling sets the table width to 100%, but that was easily fixed with a .css("width", "auto") call.  I also wanted alternating row backgrounds, and a quick look showed that there is a 'zebra' widget built in that does exactly that, it just has to be enabled.

The biggest problem was with number formatting.  Some of the sortable columns contained large numbers, and when I wrapped the output with numberFormat() to add commas, the sorting reverted to textual instead of numeric.  A quick look through the source showed why: the 'digit' parser respects only numbers, the decimal point, and an optional leading +/-.  So the commas made it skip any numeric sorting and fall back to textual sorting.  Fortunately, the fix was simple.  Before initializing the table, I just added a new parser that piggybacks on the 'digit' parser's implementation:

jQuery.tablesorter.addParser({
  id: "commaDigit",
  is: function(s, table) {
    var c = table.config;
    return jQuery.tablesorter.isDigit(s.replace(/,/g, ""), c);
  },
  format: function(s) {
    return jQuery.tablesorter.formatFloat(s.replace(/,/g, ""));
  },
  type: "numeric"
});

The only difference between it and the 'digit' parser is that it strips all commas from the string before handing off to the backing methods (the blue stuff).  Works like a champ.  The separator should probably be parameterized like the decimal stuff is, but I only deal with comma separators in this app, so I didn't bother.

The only thing I wasn't able to figure out (though I'll admit I didn't try very hard) was setting the initial sort to be descending, so when you click a column header for the first time it does a descending sort rather than ascending (with subsequent clicks reversing the sort as normal).  Setting up the on-initialization sort to be descending is simple, but I didn't see a way to parameterize user-triggered sorts.

First Person Documentation

I'm not sure when I started, but I've documented things in the first person for quite a while.  Fusedocs promoted this format, and was probably a significant influence, though I recall doing it back in college as well.  It's clearly not new or uncommon, but I just had a gentleman email me about it (based on finding my old ComboBox script embedded in an app he inherited), and his comments really brought to light why I like the format so much.  Here's an example (from the ComboBox code):

/**
 * I am called to repopulate the dropdown.  There should never be a
 * need to invoke me externally.
 */
ComboBox.prototype.populateDropdown = function() {
  // ...
}

Now you might say that there is no substantial difference between that and the more typical third-persion documentation.  However, I think there's a huge difference.

First, in order to anthropomorphize the method enough to write in first person, you have to get inside what it's doing.  That provides useful insight, and can highlight behaviour that really doesn't make that much sense, even though it doesn't jump out and say "I'm wrong!".  It also makes the comments easier to write, I think, because it's more personal.

Second, writing in the first person lets you make certain statements in a far nicer way.  For example, there's no way to say "Barney implemented this method poorly", despite the fact that it might be true for whatever reason (misunderstandings, time constraints, etc.).  However, saying "I am implemented poorly " doesn't assign blame.  Even better is "I was poorly implemented by Barney", which would never be written by anyone except Barney, and therefore also prevents assignment of blame, but does let Barney take it upon himself.  Hopefully any of the three are immediately followed by how it was implemented poorly, why it was done that way, and even suggestions for improvement.

The inverse of this is it lends a bit of personality to the code.  Seemingly arbitrary business requirements tend to end up with comments that have a bit of "attitude" to them, for example.  This personality is absolutely instilled by the developer(s) themselves, but it becomes an element of the code itself which makes it far easier to deal with.  It supplies a sort of contextual memory for the code when it's cracked open again in a different time.

Finally, the mindset of the reader (even if it's the same person who wrote it) is different when interfacing with something first hand.  The first person gives you the impression that the code is alive and talking to you, and as we all know, code is a living thing.  The third persion is like what you'd see in a museum; information about a static snapshot of something dead.

I'd be quite interested to hear about other's experiences with this style of commenting, good or bad.

Shoot the Engineers

About a week ago, Marc Funaro wrote an interesting blog post about CFML and OO.  The prevailing opinion (via Twitter, blogs, etc) is that Marc is incorrect/inaccurate/inexperienced/whatever, and I disagree completely.  He hit the nail on the head.

HTTP is a stateless, request-response environment.  Nearly all web applications interface with a SQL database, which is also a predominantly stateless request-response environment.  Those are orthogonal to the core OO principle of interacting stateful objects.  It's far closer to the FP (functional programming) paradigm, but particularly on the SQL side, still doesn't match completely.

To use OO in a SQL-backed web app, you hide the mismatches with ORM, an object-based Front Controller implementation, and session facades.  As Marc points out, Java works pretty well in this paradigm for two main reasons:  Java is crazy fast, and Java developers have invested ridiculous amounts of effort in tooling to support this model.  CF has neither of these advantages.  I'm not belittling the effort poured into various frameworks (Fusebox, Model-Glue, ColdSpring, Transfer, etc.), just that they are significantly behind what is available to Java developers.

Unlike Marc, I happen to think that a Front Controller framework is essential, but I don't use a OO one for exactly the reasons he outlines.  I build FB3lite for just this purpose: 70 lines of straightforward procedural code that help me enormously with certain common tasks.  I often masquerade my apps as standalone pages with mod_rewrite (converting /viewUser.html into /index.cfm?do=viewUser), but that's a cheat.

I also use CFCs  and ColdSpring for my business tier, but no object (domain) model for me.  The CFCs are really just glorified function libraries that I can use ColdSpring's AOP engine to wrap transactions around without having to manage them explicitly in my code.  In order to get the AOP I have to use CFCs, and I like the namespacing they provide (so I can have a 'doThing' method in multiple namespaces without conflict), but there is no real OO-ness there.

I know what you're saying.

Yes, I often preach the benefits of OO and encourage people to learn about it and use it.  But using a howitzer to hunt mice in your garage is not a clever idea.  If I'm writing Java (or Groovy), I'm going to use OO structures, but that's because of the programming environment.  I am a pragmatic person.  I like to learn about a wide array of tools and then use as few of them as possible, knowing that there are other options available if I need them.

Yes, built CFGroovy with Hibernate support so I could use ORM in my CFML apps via Groovy objects.  It provides the best of both worlds, the speed and tooling of Java in a CFML environment.  That approach works quite well, but if I don't need the complexity, I'm not going to do it.

My First cf.objective()

I know I'm late to the "cf.objective() recap" party, but I've been both crazy busy and rather tired, so I haven't got to it until now.

First, I'd never been to Minneapolis before, and from the little I saw, it's a pretty nice place.  Obviously I missed the "buried under snow" part, and that definitely puts a damper it as a potential home, but I liked it.  Very walkable, clean, and aside from the second-story causeways between the buildings, a nice asthetic overall.  The hotel was in a great spot, with a pretty varied selection of dining an drinking establishments within easy walking distance.

Before I got there, I hadn't quite internalized how small a 200-person conference actually is.  "Social" is a skill I didn't inherit from my father, unfortunately, but with the number of people I knew already, I didn't feel nearly as isolated as I often do at CFUNITED (which is five times the size).

The sessions were pretty good, over all.  I didn't get to go to several that I would have liked to because of scheduling, but c'est la vie.  Here's a rundown of the notable ones I attended:

Adobe's keynote the first day was interesting, and I might be mixing it in with some other Adobe presentations, but quite fascinating to see crowd reaction to certain Centaur features.  CFFINALLY and CFCONTINUE?  Nothing.  It should be noted that I was the only one to applaud them last year at CFUNITED.  Remote diff of server configuration?  Huge applause.  WTF?!?  Script your production environments, people.  If they're ever out of sync, you're doing your job wrong.   ORM stuff got much applause, of course, and rightfully so.  Drag and drop, full-stack scaffolding also did.  Do people actually use that?  Great marketing/sales tool, no question, but for actual applications?!?!  But I digress…

Marc Escher's talk on unit testing was quite interesting, I thought.  I've tried numerous times, with numerous technologies, to really embrace unit testing and failed every time.  Actually had the best luck doing it with Flex, which just drips with irony.  I'm not predicting success next time I attempt it, but I'm confident I'll do better than last time.  On a similar vein, Sean Corfield's talk on cf.spec provided some nice pointers.  I'm not too sure about the "readable" spec document concept, but an interesting technique.  Until you can have exactly one spec document, I'm not sure of the utility, but I think that's really an editor/syntax problem, not a conceptual one.

Mark Mandel's intro to Transfer was quite interesting as well.  That I attended might surprise you if you're familiar with the various Hibernate projects I've worked on, but ORM is still voodoo in my mind.  Coming back to the basics and being "introduced" to ORM from the ground up is always interesting, because the subtleties in interpretation provide a great introspective of ORM as a whole.  The odds of me picking up Transfer and using it on a "real" project are pretty small, but I didn't go to learn about Transfer in particular, more about ORM in general.

Let me be clear on this, Transfer is amazing.  It does things with CFML that I would have sworn were impossible, and does them fast enough to be perfectly servicable.  It's just not the tool that fits my style.  I've been a Hibernate user for many years, and that's a hard framework to supercede.  Honestly, I bet I'll never replace Hibernate with another ORM solution, but instead replace it with an alternate approach (an object database, for example).

As you might expect, I also went to Adobe's talks about the new ORM functionality coming in Centaur.  When I first was exposed to their Hibernate implementation, I was pretty skeptical.  There seemed to be a global misunderstanding of both the technology and the problem it was design to solve, but that has turned around 180 degrees, and Centaur looks to have pretty robust ORM capabilities.  I've got a major bone to pick with how Adobe is marketing the functionality, but the actual implementation looks pretty sound.  It's hard to get a complete picture with the pre-release secrecy, but I'm a lot more excited about it than I was 6 months ago.

Even more exciting is what will hopefully be coming out of Railo/JBoss in the coming months.  There's been no formal talk of what that looks like yet, and it's probably a safe bet that it'll be similar to ColdFusion's implementation (for obvious reasons), but with Railo and Hibernate both under the JBoss umbrella, I think there's some cool stuff on the way.  Obviously any speculation is just that, but with Railo supplanting ColdFusion in a lot of places I use CFML, I'm understandably excited about it.

The last session was Adam Haskell's talk on mentoring and code review.  That is a misnomer of a title, if you ask me, because while he did talk about that stuff, the point was really about team dynamics.  Working on a team is hard.  Working in a "get things done" environment only makes it worse.  Fostering the team, particularly around helping junior developers move up in the world, takes time and effort, but it's worth it.  I think Adam did a good job of emphasising that any sort of formal process is less effective than an equivalent informal process.  Informal is inherently more personal, and with the typically sterile world of technology and computers, the "personal" stuff is really important.

Of course, the big draw of any conference (though the hardest to justify) is the meals/drinks/etc. that happen outside the actual conference.  (It seems like I just said the same thing two sentences in a row, completely by accident.)  With the conference as small as it was, the informal socialization was a lot tighter, I though.  Far less spreading of groups, and so more churn within them.

I also really liked the way they did lunch, with actual table service, rather than a buffet.  With a more formal meal, you end up sitting and talking with fewer people, but for a longer period of time.  Aside from fostering more involved conversation, it also provides a nice break from the chaos to resettle for the afternoon.

Talking with other developers is always fun, and typically the source of the best tidbits of information.  I always like learning about stuff, even if it has no direct applicability, because it gets you mind thinking in ways it otherwise wouldn't.  And it seems to happen pretty often that 6 months down the road one of those random bits of information suddenly because fairly relevant.  Maybe not directly, but at least opens my eyes to some potential approach I wouldn't have otherwise considered.

Great conference, overall.  I gotta hand it to Jared and his team.

FB3lite as a Custom Tag

Last night at work Koen uncovered an issue with using FB3lite as a custom tag.  Inside the tag it does "formUrl2Attributes" to merge the two scopes into the attributes scope.  What I'd done incorrectly was omit the "don't override" parameter to the structAppend calls, so the URL and FORM scopes would supercede any existing attributes for the invocation.

During normal execution this is irrelevant.  It's similarly irrelevant if you don't have a collision between FORM/URL parameters and custom tag attributes.  However, if you do have a collision, the FORM/URL parameter wins, which is clearly incorrect.

To fix this, I added the missing third parameter to structAppend, as well as reversing the lines (so FORM still overrides URL as it always has).  You can grab the source directly, or pull from Subversion.

Effective Photo Manipulation

Image manipulation is a common tasks for web applications, usually centered around creating and managing thumbnails (of photos, PDFs, videos, whatever).  Photo manipulation is a subset of image manipulation, and has a couple aspects that differentiate it other types.

First and foremost, photo quality is of high importance.  Contrast this with creating a thumbnail of a PDF (especially a text-heavy one); there's no way you can be representative of the original's detail.  A photo's thumbnail, however, must be as representative as possible.  Unfortunately, photos are typically encoded as JPG files, which use a lossy compression algorithm, which means that every time you manipulate them in any way, you're reducing the quality.

Photos are also often subject to user-editing (cropping, annotating, etc.), and while this is commonly done with dedicated photo editing tools (installed on the user's computer), plenty of web apps do it too.  I'm not thinking Photoshop Web, here, I'm talking about your site's photo gallery software that lets you upload originals and rotate them so they're facing the right way.

Between these two things, you (the developer) can get stuck in a bind.  You need to be able to edit photos repeatedly, but at the same time maintain quality.  The trick is to only ever edit a photo once.  Seriously.

This is simpler than it sounds.  The trick is to start thinking about designing your app interms of operations (rotating) instead of states (rotated).

When you get your hands on the original image, put is somewhere safe.  That's the only image you're ever going to deal with.  When your user comes and rotates it, write the specifics of that operation to the database, and then take your original and run all the stored operations on it to create the "current" view.  Then when they crop it, write the operation to the database, and then take your original and run all the stored operations on it to create the "current" view.  You can see where I'm going here.

Same thing goes for thumbnails.  If you need a 150×150 thumbnail of a phote, don't take the "current" view and resize it, take the original, run all the stored operations on it, and tack on a "resize to 150×150″ at the end to create the thumbnail.

This works because you only run through the lossy compression once, so your generated views stay at a noticably higher quality than if you save after each operation.  It might not be apparenty in a 50×50 thumbnail, but if with two operations (rotate then crop) on a full-size image, the difference in quality by doing them together verses encoding in between is quite apparent.

Of course, you can't do this sort of processing on demand, so you have to store the results of the transformations.  The key is to never read those in to do the next step, always start from the original and play back all the manipulations in sequence.  This mechanism fits very nicely with the mod_rewrite-based caching mechanism I wrote about a couple days ago.  When a new operation is saved, wipe out all the cached versions of the photo and let them rebuild as needed.

This isn't a particularly revolutionary idea, and I know many photo tools (e.g. Picasa) do things this way, but I've found that it's worth the extra effort.  Obviously it's utility is predicated on having decent originals, but believe me, your users will notice.