Adam Tuttle

Entries Tagged as ColdFusion

To Scope, or Not To Scope

Adam Cameron has another of his surveys going, about your personal taste in variable scoping. It's something I've written about in the past, but my approach has evolved since then, so I figure it's worth writing about again.

Previously my position was that all references (if-statements, display, etc.) should be scoped, while it was not strictly necessary for variable definition (foo=42) — unless required to actually put the variable where you want it, e.g. in Request scope. I still think this approach has merit, and for the same reasons (you never find yourself asking, "ok, but WHERE is the variable foo coming from?") but its primary drawback is verbosity.

Since then, CFScript has matured (which is not to say that it "is mature"), and I find myself writing more JavaScript than CFML/CFScript, anyway. So, it's only natural that my personal style when writing CFML/CFScript is starting to take on the appearance of my JavaScript, too.

This means that I am tending to use traditional var foo = 42; statements in my CFCs over my previously-preferred style of var local = {}; local.foo = 42;. I preferred the latter because of its explicitness. As of CF9 we no longer needed the var local = {}; but I still find littering my code with dozens of local. prefixes to be a bit verbose, cumbersome, and at times distracting.

Another part of the evolution of my style has been that my code gets smaller and more decoupled (and in many cases, functional), which means the surface area of any given function is smaller and more manageable, so we don't need as much brain power to keep everything in our heads at once. Since I've got some additional brain bandwidth available from that change, I find myself preferring the more terse var-scoped approach, because I love terseness. This sort of creates a feedback loop: By writing smaller, more discrete functions, I'm able to use a more terse syntax, which takes up less space (mentally and physically), which itself makes the functions smaller and more manageable.

In the end, my preference is still that if you can't look at a variable and immediately know where its value was set — even when reviewing the code 2 years later — then you need to be more explicit. It's just that my tooling and my general style have enabled me to reduce the amount of time that extreme specificity is required.

Tools help! I can look at a FW/1 controller and tell you that a variable named rc.foo is input from the user: a form or url variable. Likewise, this means that things not prefixed with rc. are not user-generated and are then more likely to be var-scoped. My controllers don't use anything variables-scoped except injected services, so those service methods are prefixed by the service name: fooService.getFoos();. I could write variables.fooService.getFoos() but what's the point? All in all, those controllers are very easy to follow. (Well done, Sean!)

Likewise, my FW/1 services use injected service dependencies and no other variables-scoped data. If I need a config setting, it's available through my configService. So knowing this, all unscoped variables inside my functions are (better be!) var-scoped locals.

But that's just my personal style. What is yours like? (And hey, take a minute to fill out Adam Cameron's Survey, too!)

Published 2014-07-24 @ 09:33 in Best Practices ColdFusion

Idiosyncrasies of using CFContent to send files to the client in ColdFusion

I've found some idiosyncrasies in using CFContent to deliver files to the browser with ColdFusion (e.g. shielded downloads), so I thought I would share them here.

I have only tested what I'm about to share in ColdFusion 10, but I have no reason to believe that it will be any different with other versions, as it appears to be entirely how things are handled client-side.

I can never remember what the appropriate header name is for specifying the file name, so the first thing I did was google for it. That took me to Ben Nadel's blog post on streaming files -- a slightly different matter, but it had the answer I was after:

<cfheader name="content-disposition" value="attachment; filename='filename.xlsx'" />

This worked great, at first, in Chrome. When I got around to various browser tests, I found that if my file name contained a space, as in file name.xlsx then Firefox would save it as 'file (no extension -- nothing after the space). Equally as odd, Safari got the name correct (file name.xlsx) but appended .html.

Changing the single quotes to double quotes fixes FireFox's quirk, and adding a Content-Type header fixes Safari's, so the final result looks like this:

<cfheader name="Content-Disposition" value="attachment; filename=""#rc.fileName#""" />
<cfheader name="Content-Type" value="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
<cfcontent reset="true" file="#rc.filePath#" deletefile="true" />

It's 2014... We can make an almost-convincing hoverboard hoax but we still need to test everything in every browser on every platform.

Published 2014-07-18 @ 09:05 in ColdFusion

CFHTTP SSL Stopped Working after OSX Mavericks Upgrade? Here's Why!

Like so many before me, I've recently been banging my head against issues with CFHTTP and SSL, particularly only on Mac OS X. Eventually I landed on the right Google phrase and read enough links to find this gem, which while only tangentially related, brought my memory back in a flash.

Apple, in their infinite wisdom, decided to stop distributing Java with OSX. And I hadn't realized it at the time that I upgraded, because ColdFusion continued to function, but the upgrade deleted much of the Java JDK, including (you're probably guessing right...) the cacerts file. Not even Verisign signed certificates are trusted if you don't have any cacerts file.

It wasn't until I figured out that my cacerts file (and many other bits of the JDK) were missing that I found the Jira ticket that solved the puzzle.

Thanks, Apple!

Here's what you can do about it: ColdFusion 10 now officially supports Java 7 (as of update 8), so you need to upgrade.

Being a fan of minimalism (e.g. not installing tons of useless junk) I opted to download the Java SE 7 JRE package -- because the JRE is for people who want to RUN java apps, while the JDK is for people who want to WRITE java apps -- for OSX, and installed it; though I was perplexed that it didn't let me choose an install location, or even tell me what it was after it was complete. I had to find out via Stack Overflow -- and as indicated in the comments there, using a JRE installed into the Internet Plugins folder to run your app server isn't exactly the brightest idea.

Right then... Thanks, Oracle!

With that great idea flushed down the toilet, I gave up any hope for sanity and downloaded the Java SE 7 JDK. Again, it didn't let me choose an install location, or bother telling me where it installed. Thankfully, someone else in the same Stack Overflow thread mentioned that the command /usr/libexec/java_home -v 1.7 will let you find the location of an installed JDK by version number; and it turned out that mine was installed to: /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home.

Next we need to tell ColdFusion to use this new JDK instead of the kneecapped one that Apple left behind during the Mavericks upgrade. ColdFusion gives us a decent UI for updating the value, but stores it in the file {CF_ROOT}/cfusion/bin/jvm.config, so make a backup of this file before you change anything. And don't delete your old JDK yet. If something goes wrong, you can just put back your backup of jvm.config to point CF back at the old JDK.

With your backup made, open your CF Administrator and navigate to Server Settings > Java and JVM. Next to Java Virtual Machine Path tap the Browse Server button. (Sure, you could paste it in, but why risk a stray space or missing slash, etc screwing things up?) Find the folder listed as the result of the java_home command earlier and select it.

Then just restart ColdFusion and you're good to go! (If you're not, copy your backup of jvm.config back into {CF_ROOT}/cfusion/bin/jvm.config and restart CF again...)

Verify that you're now on Java 7 by clicking the small "i" icon in the upper-right of the CF Administrator, and checking the value of Java Version -- you want to see 1.7.0_60 or later.

I hope I never have to go through that again, and I hope maybe it helps a few of you out there.

Published 2014-06-11 @ 08:25 in Apple ColdFusion

Fix: What Are These Ugly and Useless Error Pages on My Fresh ColdFusion 10 Install?

I recently installed ColdFusion 10 on a new server, and of course I followed the CF10 Lockdown Guide [pdf].

Then I started moving sites onto the newly configured box and testing things out. And I got this lovely piece of work:

(Full disclosure: there are two possibilities, a "missing page" error, as shown above because it's easier to reproduce now for the purposes of the blog article, and a "there was an error" error, which is what I was running into at the time. For all practical purposes there is no difference.)

Viewing the source of this error message, it was clear that it was generated by ColdFusion. The references to files inside /CFIDE/ are a dead give away.

<html>
    <head>
        <InvalidTag http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>404</title>
    <link href="/CFIDE/administrator/templates/assets/style.css" rel="stylesheet"/>
    </head>
    <body>
    <div id="header"></div>
    <div id="spot">
         <image src="/CFIDE/administrator/templates/assets/spot.png" />
        <div id="title">404</div>
    </div>
    <div id="content">
        The page you are trying to access could not be found. Please try again or notify the administrator.
    </div>
    </body>
</html>

And as soon as I saw this I knew instantly why the image didn't work and the page was unstyled. Because the lockdown guide instructs you to remove the /CFIDE/ virtual directory from public-facing sites such as this one. I was curious what it would look like styled, so I briefly added the virtual directory to the site to get a look at it. This was the result:

... marginally better, I suppose. And once I knew that these errors were being served up by ColdFusion, I knew it had to be something I had done as part of the lockdown guide... Except that everything there I was familiar with. Except Secure Profile. Secure Profile is a mysterious setting you can enable during the installer that sets a bunch of settings to more secure default values.

Unfortunately, there's no quick "undo secure profile" toggle, to see if it is causing any problems for you. It just twiddles some knobs. You're capable of twiddling them too, but can't just flip them all like a light switch.

Right, so my hunch is that Secure Profile is causing these error pages. How do I turn them off? I puzzled about this for a few minutes, and eventually decided to read every setting it changes, hoping to find the culprit there. And as luck would have it, I found it pretty close to the top. Items #5 and #6 are Custom missing template error, and Custom site-wide error template. And, as much as I like to harp on Adobe for doing a poor job writing documentation, this page very nicely describes where to find the settings in question ("Server Settings > Settings"). So pop open the CF Administrator and find these settings down near the bottom of the general settings page:

Just empty these values out (or replace them with your preferred error pages) and submit, and you're good to go.

Published 2014-03-17 @ 09:00 in ColdFusion