January 6, 2009

Pages


Search Site


Topics



Archives

Tweets

Application.cfm: Determining environment

May 09 2007 by Adam
As I mentioned two weeks ago, application.cfm tweaking is important, but reaching the best compromise between efficiency, readability, and functionality is highly subjective and there are exceptions to every rule. The question of how to manage application.cfm in multiple environments or between servers in a cluster is one that every developer you asked would probably answer differently. You could have separate versions of the file for every server, you could have a flag set at the top that indicates what set of code to run, you could check CGI variables… there are a hundred ways to skin a cat. My personal preference is to use CFFile. But before you start to criticize me based on the overhead of reading a file, hear me out. If you still disagree with me, feel free to leave a comment to that effect! Before diving in to the code, let's consider some rules of thumb.
  1. You want your production environment to be the fastest path through the code, for what I hope are obvious reasons.
  2. You want the default case to be production, so that if all else fails, at least production will work.
  3. Your solution should be extensible and scalable for the addition of future environments.
I will admit up front that more overhead is required to use a CFFile tag than to check the contents of a CGI variable or request scope variable, or quite possibly any other method. But with that said, this method is set it and forget it. In order to implement this method, we need to add a small text file to every server.

C:\env.txt on my development server: DEV I'm sure you can extrapolate this to be applicable for your other servers, right? Test should say "TEST", Staging should say "STAGE", and so forth. With one exception: Don't create a file for Production. Or at least, you don't have to. And your code will run precisely 4.3 iotas of a second faster if you don't. Because once you've created these files, you should add this code to your application.cfm:

<cfif not isDefined("application.env") or isDefined("url.resetAppVars")>     <cfif not FileExists("C:\ENV.TXT")>         <cfset application.env = "production">     <cfelse>         <cffile action="read" file="C:\ENV.TXT" variable="application.env">         <cfset application.env = trim(lcase(application.env))>     </cfif> </cfif>
Now, going back to my three rules above:
  1. Production is the fastest path through this code, assuming you don't create the ENV.TXT file in that environment.
  2. The default case is production: If the file doesn't exist, assume production!
  3. Scalable? Check! Adding a new testing server called Test2? Make it's file contents "TEST2" and you're off and running.
Now that you've defined your environment, it's time to set some environment specific variables. Hopefully you remember that you should only set your application variables when they don't exist in memory! I've already demonstrated how to accomplish this above: Check whether or not one of them is defined first. And while you're making that check, you should always give yourself the ability to refresh them at your will, which is why I included the check for the variable url.resetAppVars. Instead of restarting ColdFusion services to reset your application variables, you can simply append ?resetAppVars=true to your URL. When setting your environment specific variables, the same rules apply: Production should be the fastest path through your code, the default case, and your solution should be easily scalable. I like this approach.
<cfif not isDefined("application.myVariable") or isDefined("url.resetAppVars")>     <cflock scope="application" type="exclusive" timeout="30">         <cfif application.env is "production">             <cfset application.myVariable = "my value for production">         <cfelseif application.env is "dev">             <cfset application.myVariable = "my value for development">         </cfif>     </cflock> </cfif>

Posted in Best Practices | ColdFusion |