by Michael Dinowitz
When I have a problem with my code, I like to debug by 'thinking as the server.' This means walking through the code step by step as if I was the ColdFusion server and seeing what is actually happening. I'll actually talk more about this in another article, but this time I'd like to talk about two things I've discovered in one of these 'walks'.
The first thing is that Application.cfm and OnRequestEnd.cfm are required by the ColdFusion server. When I say required, I don't mean that a template will not work without them but that the ColdFusion server expects them to always exist.
Let's imagine we're the ColdFusion server and we've just been asked to process a page. The first thing we do is to see if an Application.cfm exists in memory for this directory. If not, we'll look at the directory to see if one is there. If we still can't find it, we'll go to the parent directory and do the operation again (check memory and then check disk). This process will continue until we have checked all the way up to the drive root (Yes, the ColdFusion server looks all the way to the drive root rather than to the web or ColdFusion root.) At this point, if we haven't found any Application.cfm files, we simply assume that none exist and start to process the template that was actually requested. Once we're done with the template, we'll do the exact same search for the OnRequestEnd.cfm template.
These searches are actually rather fast and probably don't even show up on the resource monitors, but they do exist. For this reason, I suggest every application has an Application.cfm and an OnRequestEnd.cfm file, even if it simply contains a space character (Template must contain at least one character or an error will occur).
The second thing I found is that the way most people set their variables inside Application.cfm templates is wrong. Again, let's act as the ColdFusion server and process a page, but this time let's just focus on the Application.cfm file.
Someone requests the template index.cfm. Before that template is run, the Application.cfm template is processed. The first line is a CFAPPLICATION tag, which says that index.cfm is part of an application. The next line is a CFSET with a variable of Application.DSN and a value of "datasource". A few more CFSETs are used for different application variables and by the time we're ready to process index.cfm, four variables have been written to memory for this application. So far, so good. The next minute, someone (the same person or someone else, it doesn't matter) asks for a template called outdex.cfm in the same directory. Again, we start with the Application.cfm. The first line is the CFAPPLICATION tag that says that outdex.cfm is part of an application, the same application as index.cfm. This means that it can share the same memory-based variables. The next line is a CFSET with a variable of Application.DSN and a value of "datasource". A few more CFSETs are used for different application variables and, by the time we're ready to process index.cfm, four variables have been written to memory for this application.
Can you see what's wrong here?
If an application variable was set once, why are we setting it again? Why are we setting application.DSN on EVERY template call we make? There's no reason and, in some cases, this can run into variable overwrite errors (in CF 4.0x especially). Instead, what we should be doing is setting the application variables once and never again. This avoids extra work on every page and avoids the potential for errors. This method should be used for Session variables as well.
Old Way
|
<CFSET Application.DSN = "DataSource">
<CFSET Application.Path = "/"> <CFSET Application.Images = "/images/"> <CFSET Application.Attachments = "c:\cfusion\attachments\"> |
New Way
|
<CFIF Not IsDefined('Application.DSN')>
<CFSET Application.DSN = "DataSource"> <CFSET Application.Path = "/"> <CFSET Application.Images = "/images/"> <CFSET Application.Attachments = "c:\cfusion\attachments\"> </CFIF> |
The application variables will only be created if they don't already exist. I use Application.DSN as the 'key' value as most programmers use this to dynamically set their data source names. Finally, you can add a CFLOCK inside the CFIF statment if you are using CF 4.0x.
coral,turquoise jewelry, shell,gemstone jewelry, pearl bridal jewelry and wish pearls gifts in China.