ColdFusion Application.cfc Tutorial And Application.cfc Reference

Posted May 25, 2007 at 7:22 AM

Tags: ColdFusion

I sometimes do in-house presentations here at Nylon Technology. Last night, I was asked to prepare "something" for this morning. In a mad rush, I threw together this presentation on ColdFusion's Application.cfc component. I am sure most of you have seen this stuff before, and a lot of it is right in the ColdFusion documentation, but for some people at my office, this will be new stuff. I am covering things like Application.cfc events, variables, and some tips and tricks that might not be obvious.

I finished working on this last night at like 9:30 so you better believe I did NOT, nor do I care to proof read this :) It's advertised strickly "as is."


ColdFusion Application.cfc Tutorial For Nylon Technology

ColdFusion MX 7 introduced the Application.cfc ColdFusion component. This component replaces the traditional Application.cfm and OnRequestEnd.cfm ColdFusion application templates. Furthermore, if Application.cfc is present, both of these templates are ignored by the application.

In addition to replacing the request start/end functionality of the old application templates, Application.cfc provides hooks into many additional application level events including:

OnApplicationStart()

This fires when the application first runs. It is a single-threaded method call.

OnSessionStart()

This fires when an individual session first runs. It is a single-threaded method call.

OnRequestStart()

This fires when a page request first runs. It is a single-threaded method call.

OnRequest()

This fires when the requested template needs to get processed.

OnRequestEnd()

This fires at the end of every page request. It is a single-threaded method call.

OnSessionEnd()

This fires at the end of every session. This will fire either for a session timeout or if the server is shutting down. It is a single-threaded method call.

OnApplicationEnd()

This fires at the end of the application. This will fire for an application timeout of if the server is shutting down. It is a single-threaded method call.

OnError()

This fires if an exception gets thrown and is not caught by the controlling code.

All of the above methods are optional. You have an Application.cfc that is completely empty. Also, I say that the above methods are single-threaded which means that you do not have to worry about locking the code within them. However, any and all of these methods can be called explicitly by other parts of the application (ex. calling OnApplicationStart() from OnRequestStart() for manually fired application re-initialization). In this case, the manually invoked events are NOT single-threaded and may be open to race conditions.

In addition to application event hooks, Application.cfc provides public properties that define the application in a manner similar to the CFApplication tag. The following are available THIS-scoped properties:

THIS.Name

This is the name of the application and is used to tie a request to existing application memory scopes.

THIS.ApplicationTimeout

The time span an application will exist before it times out (if the application is not accessed in any way). This defaults to the value set in the ColdFusion administrator.

THIS.SessionManagement

A boolean flag to determine if the SESSION scope should be used. This defaults to false.

THIS.SessionTimeout

The time span a session will exist before it times out (if the application is not access in any way by that session's user). This defaults to the value set in the ColdFusion administrator.

THIS.SetClientCookies

A boolean flag to determine if the CFID and CFTOKEN values are sent as cookies to the client's browser. This defaults to true.

THIS.SetDomainCookies

A boolean flag to determine if the CFID and CFTOKEN values are set for domain and not just a host value. This defaults to false. I have never used this and so I am not exactly sure what this means.

THIS.ClientManagement

A boolean flag to determine if the CLIENT scope should be used. This defaults to the value set in the ColdFusion administrator.

THIS.ClientStorage

If client management is being used, this determines where the client variables are being stored (cooke, registry, or database). This defaults to the value set in the ColdFusion administrator.

THIS.LoginStorage

The place login information is stored (cookie or session). I have never used this, so I am not exactly sure what that means. Defaults to cookie.

THIS.ScriptProtect

A boolean flag to determine if the variables will be protected from cross-site-scripting attacks. Again, I have never used this and I am not sure what it does. This defaults to the value set in the ColdFusion administrator.

Putting it all together, an Application.cfc ColdFusion component skeleton would look something like this:

 Launch code in new window » Download code as text file »

  • <cfcomponent
  • displayname="Application"
  • output="true"
  • hint="Handle the application.">
  •  
  •  
  • <!--- Set up the application. --->
  • <cfset THIS.Name = "AppCFC" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 0, 1, 0 ) />
  • <cfset THIS.SessionManagement = true />
  • <cfset THIS.SetClientCookies = false />
  •  
  •  
  • <!--- Define the page request properties. --->
  • <cfsetting
  • requesttimeout="20"
  • showdebugoutput="false"
  • enablecfoutputonly="false"
  • />
  •  
  •  
  • <cffunction
  • name="OnApplicationStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="Fires when the application is first created.">
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnSessionStart"
  • access="public"
  • returntype="void"
  • output="false"
  • hint="Fires when the session is first created.">
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnRequestStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="Fires at first part of page processing.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • />
  •  
  • <!--- Return out. --->
  • <cfreturn true />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnRequest"
  • access="public"
  • returntype="void"
  • output="true"
  • hint="Fires after pre page processing is complete.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="TargetPage"
  • type="string"
  • required="true"
  • />
  •  
  • <!--- Include the requested page. --->
  • <cfinclude template="#ARGUMENTS.TargetPage#" />
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnRequestEnd"
  • access="public"
  • returntype="void"
  • output="true"
  • hint="Fires after the page processing is complete.">
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnSessionEnd"
  • access="public"
  • returntype="void"
  • output="false"
  • hint="Fires when the session is terminated.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="SessionScope"
  • type="struct"
  • required="true"
  • />
  •  
  • <cfargument
  • name="ApplicationScope"
  • type="struct"
  • required="false"
  • default="#StructNew()#"
  • />
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnApplicationEnd"
  • access="public"
  • returntype="void"
  • output="false"
  • hint="Fires when the application is terminated.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="ApplicationScope"
  • type="struct"
  • required="false"
  • default="#StructNew()#"
  • />
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  •  
  • <cffunction
  • name="OnError"
  • access="public"
  • returntype="void"
  • output="true"
  • hint="Fires when an exception occures that is not caught by a try/catch.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="Exception"
  • type="any"
  • required="true"
  • />
  •  
  • <cfargument
  • name="EventName"
  • type="string"
  • required="false"
  • default=""
  • />
  •  
  • <!--- Return out. --->
  • <cfreturn />
  • </cffunction>
  •  
  • </cfcomponent>

Now that we understand how all the events and variables are wired together, let's take a closer look at the individual application event methods.

OnApplicationStart()

This is the perfect place to define application-scoped variables (ex. APPLICATION.DSN for data source structures). If this method is invoked manually, be sure to call StructClear() on the APPLICATION scope before you re-initialize the data values. This will help to ensure a clean refresh.

The return boolean signals as to whether or not the application loaded successfully. Returning false will halt the processing of the rest of the events of the current page request.

OnSessionStart()

This is the perfect place to define session-scoped variables (ex. SESSION.Cart for eCommerce cart data). If this method is invoked manually, be sure to call StructClear() on the SESSION scope before you re-initialized the data values. HOWEVER! before clearing the scope, get a copy of the CFID/CFTOKEN values so that you can store them back into the session during re-initialization. ColdFusion will not automatically re-create these values as calling this event method is not actually restarting the session.

OnRequestStart()

This the perfect place to define request-specific and other request-scoped variables (ex. REQUEST.Attributes for the union of the FORM/URL scopes). This is also a good place to do universal FORM value scrubbing (such as removing smart quotes and trimming form field values).

If you application or sessions can handle manual re-initialization, this is a good place to check for those URL flags (ex. StructKeyExist( URL, "resetApp" )) and then manually invoke the OnApplicationStart() or OnSessionStart() application events.

If you are using the OnRequest() method and you expect this application to be used for flash remoting or CFC-based web service calls, this is the ideal time at which to check for the request type (standard page request vs. web service) and if need be, delete the OnRequest() method from the Application.cfc (ex. StructDelete( THIS, "OnRequest" )).

If the return value is false, the page processing will be halted.

OnRequest()

If you include this event then you must include the requested page via a CFInclude tag. The relative path of the template is passed as the only argument to this function. If you include the in this manner, the processed template becomes what is essentially a "Mix-In" of the Application.cfc meaning that it is actually part of the Application.cfc code. If you do this, the processed page will have access to the THIS and VARIABLES scope of the Application.cfc.

If the request page is included in this manner, it also means that the requested page will have access to all methods defined in the Application.cfc.

This is the perfect place to handle login management. Since this method determines which template gets executed, this is where you can check login status and conditionally include the login template rather than the requested template.

OnRequestEnd()

This is the perfect place to handle page logging. By doing it here (especially if the first command is a CFFlush tag), the user experience will not be affected by any processing overhead of this event method.

OnSessionEnd()

This is the perfect place to clean up sessions that have times out (ex. deleting uncommitted shopping cart information). This method does not have inherent access to the APPLICATION scope or the SESSION scope (as the OnRequestEnd() method has access to the REQUEST scope). In order to access those scopes, you must use the passed in arguments.

OnApplicationEnd()

This is the perfect place to log information about the application. This method does not have inherent access to the APPLICATION scope. In order to access that scope, you must used the passed in argument.

OnError()

This event gets called when an event fires and allows you to handle that error and include an error handling template if you so desire. However, this event cannot display anything to the user if the error occurs during the OnApplicationEnd() or OnSessionEnd() events as those are not request-related (unless called explicitly during a request).

One thing to be aware of (as of MX7) is that the CFLocation tag throws a runtime Abort exception (which makes sense if you understand that the CFLocation tag halts the page and flushes header information to the browser). As a work around to this, you can check the passed in Exception type and if its a Abort exception do not process the error:

 Launch code in new window » Download code as text file »

  • <cfif NOT CompareNoCase(
  • ARGUMENTS.Exception.RootCause.Type,
  • "coldfusion.runtime.AbortException"
  • )>
  •  
  • <!--- Do not process this error. Return out. --->
  • <cfreturn />
  • </cfif>

As a note of caution, if you use the OnError() event method to include a ColdFusion template that is also URL-accessible, you have to put in logic that knows not to use exception-related values if the template is access directly.

Additional Methods

The above event methods are those that the ColdFusion server will attempt to hook into during the application and page life cycle. Application.cfc is a ColdFusion component just like any other CFC file and because of that, there is nothing to stop you from defining as many methods in it that you want. One thing that I like to do sometimes is create a method CreateCFC() within the Application.cfc to provide short hand notation (and other benefits) not only to the other Application.cfc methods but also to any template that shares the Application.cfc memory scopes.

In addition to methods, you can create as many variables as you like within the Application.cfc memory scopes.

What Is A ColdFusion Application?

ColdFusion applications do not really exist. At least not in the way you might think of a traditional desktop application that has a running process. ColdFusion applications do not have a constant process. Instead, they have memory scopes. Each application has its own name which ties it to a chunk of memory somewhere. Every time you define an application through the Application.cfc (or CFApplication), what you are really doing it associating the current page request to the chunk of memory that is associated with that application name.

When you start to look at ColdFusion applications this way, it becomes a little more clear why you cannot explicitly kill an application or a session; there simply is nothing to kill. An application doesn't run unless you have a running page that requests to be associated with it.

When Does The Application.cfc Get Created?

It is important to understand that Application.cfc is newly instantiated for every single page request. This means that all the application settings and page request settings can be different for every page request. This information can be used to set up alternate session management configurations. For example, you might set THIS.SessionManagement to false for browsers that you know cannot accept cookies (and therefore cannot handle session management).

What If I Am In A Rush - Isn't CFApplication Easier To Code Than Application.cfc

This is absolutely not true. Remember, all of the information outlined in this presentation is completely optional. You don't have to have anything in your Application.cfc. For example, the following is a perfectly valid Application.cfc:

 Launch code in new window » Download code as text file »

  • <cfcomponent>
  • <cfset THIS.Name = "TinyApp" />
  • </cfcomponent>

Can you get any more simple than that? This is just as easy as the CFApplication tag, but if you go the Application.cfc route, you will have the advantage of being able to easily add in the other application event methods as you need them.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page




Learning ColdFusion 9 - ColdFusion 9 tutorials, samples, examples, demos

Reader Comments

Ian
May 25, 2007 at 8:17 AM // reply »
7 Comments

Thanks for the overview. I've got a couple of questions from trying to use Application.cfc.

First, do you set things in the application scope such as your datasource name and then do an application lock every time you need to call it? Or do you dump it into some other non-locking scope when you need it?

Second, when you run the onSessionStart() call, how do you get access to the variables that you create? For example, I have some queries that need to run only when a session starts but I want to cache them in some scope other than the session scope because they are called frequently and I prefer not to use all those locks. Or am I worrying about excessive locking for no reason?

For example, I would like to run this query:

<cfquery name="Request.getSystemSettings"
datasource="#request.ds#"
debug
cachedwithin="#CreateTimeSpan(1,0,0,0)#">
EXEC pr_getSystemSettings '#cgi.http_host#'
</cfquery>

onSessionStart() but I don't seem to have access to the query results outside of the cfc.


May 25, 2007 at 8:29 AM // reply »
207 Comments

"First, do you set things in the application scope such as your datasource name and then do an application lock every time you need to call it? Or do you dump it into some other non-locking scope when you need it?"

You do not need to lock variables set in onApplicationStart. CF single threads it for you.

Later on, if you want to read the values, then you do not need to lock them if they are simple constant variable (like DSN and most app variables.)

"Second, when you run the onSessionStart() call, how do you get access to the variables that you create? For example, I have some queries that need to run only when a session starts but I want to cache them in some scope other than the session scope because they are called frequently and I prefer not to use all those locks. Or am I worrying about excessive locking for no reason?"

You can access the Application scope in onSessionStart, but you would want to ensure you use cflock if you are updating the app scope.


May 25, 2007 at 8:49 AM // reply »
6,516 Comments

@Ian,

As Ray said, you do not need to lock the variable since OnApplicationStart() is inherently single-threaded. However, if you call OnApplicationStart() manually, then it is being called as if it were a regular, every day function:

<cffunction name="OnRequestStart">

<cfif SturctKeyExist( URL, "reset" )>
<cfset THIS.OnApplicationStart() />
</cfif>

</cffunction>

In this case, since we are manually trying to reset the application and not letting the ColdFusion application server call it when the app *starts*, then OnApplicaitonStart() is not single threaded.

Because I usually have something like this going on in my applications, I tend to put an APPLICATION-scoped CFLock in my OnApplicaitonStart() method. At the very least, it cannot hurt.

As far as the scopes to use, sorry about that - my presentation did not go into good detail about that - you would use the same scoping that you would in a traditional CFApplication / Application.cfm scenario:

<cfset APPLICATION.DSN = StructNew() />
<cfset APPLICATION.DSN.Source = "cool_db" />

<cfset SESSION.User = StructNew() />
<cfset SESSION.User.ID = 0 />

You can use APPLICAITON, SESSION, REQUEST, and all the other scope within the Application.cfc just as you would have with the Application.cfm (although not all are available in all the event methods).

As far as using the query results set in OnSessionStart() outside of the CFC, the problem here is that OnSessionStart() is not related to any given page request - it's a session-specific event.

If you want to create objects in an application-level event and then use them on the rest of the page processing, do that stuff in OnRequestStart() or even OnRequest().

And, like Ray said, as far as locking goes, if you are reading simple value, don't worry about locking. Locking has overhead and should only be used if you KNOW a race condition might occur (a race condition is that one thread might be reading a chunk of code while another thread might be trying to update variables within that chunk of code). If you know that NO other thread will ever update something like DSN values, then don't worry about locking.

Even if you are manually restarting the application (calling OnApplicationStart()), which could potentially cause a race condition, I would still say don't worry about it as that is a very small possibility and something that will happen only rarely.... and of course, evaluate the worst case scenario - let's say you are updating the DSN and some dude in Delaware gets a CF error cause he was trying to do a query just as you cleared the APPLICATION scope... and then he refreshes the page and it works... is getting rid of that chance WORTH the overhead of locking every single read of the DSN?


Ian
May 25, 2007 at 9:29 AM // reply »
7 Comments

So for the various query result sets and string values that don't change I can put them in the application scope and not worry about locking because nothing bad can happen?

What would you recommend for the query example I gave that should only be called when the session starts but because it is dynamic gets called on every page request? I can't really dump it to the session scope because the values are used on just about every page of the site.


Ian
May 25, 2007 at 10:01 AM // reply »
7 Comments

On a styling note, do you create the structures in your example so that it is easier to delete them later instead of having to reference each individual value?


May 25, 2007 at 10:15 AM // reply »
6,516 Comments

@Ian,

As far as the query goes, if it needs to be executed for every single page request, then put it in the OnRequestStart() event method. Since that method is called once per page request (unless called manually which I have never seen done), it is essentially single threaded and you will NOT have to worry about locking.

Scoping it directly into the REQUEST scope, as you have done, is valid, and is what I would do.

However, look at what it is doing... it is getting results based on the http_host value. This data, while it may change depending on the host, will NOT change across a user's page requests. In that case, I would put the query in the OnSessionStart() event method and scope it directly into the SESSION scope:

<cfquery name="SESSION.GetSystemSettings">...</cfquery>

Of course, you might take this even one step further; if this is going to be the same for a TON of people, no need to keep going back to the database right? Instead, in your OnSessionStart(), you can try to cache it in the APPLICATION scope:

<cffunction name="OnSessionStart">

<cfif NOT StructKeyExists( APPLICATION.SystemSettings, CGI.http_host )>

<cfquery name="qSystemSettings"></cfquery>

<cfset APPLICATION.SystemSettings[ CGI.http_host ] = qSystemSettings />

</cfif>

<cfset SESSION.SystemSettings = APPLICATION.SystemSettings[ CGI.http_host ] />

</cffunction>

What I am doing there is creating a system settings query object for each http_host that comes in and caching it in the APPLICATION scope. Then, for each session, I check to see if that setting object exists yet. If NOT, I created it and cached it. Then after that conditional check, I know that it exists and can then just get a reference to it in my session.

As far as using Structs vs. individual values, I like using structs cause I can logically group related data. This makes my code more readable (IMO) and also makes it easier to pass data; it's less code to pass a structure containing 10 values than to pass all 10 values.

Hope some of that helps.


May 25, 2007 at 11:12 AM // reply »
15 Comments

Hi Ben,

Yet another great overview. Thanks for the effort.

Could you make your web pages more print-friendly?


May 25, 2007 at 11:23 AM // reply »
6,516 Comments

@Will,

Glad it helped. I am going to work on making a print-friendly version of my blog detail pages. Thanks for bearing with me.


May 31, 2007 at 4:01 PM // reply »
49 Comments

Ben - great post! I'm building an quick application using Ray Camden's Soundings survey application and decided to try to convert his application to use application.cfc - and so far so good but I have run into one issue I'm not sure how best to handle - nested application.cfms...

He has an /admin section where he has another application.cfm which include the one in the root. I've done this myself in the past but not sure the best way to handle it in moving over to application.cfc...

Any thoughts?

Thanks again for all the great blog posts! I don't know how you find the time!


May 31, 2007 at 4:53 PM // reply »
6,516 Comments

@Jim,

Glad you like the work and effort that I am putting into this stuff. I know that you can extend one Application.cfc with another, however, if they are in nested directories, that will require a mapped path. I have never done this so I cannot give you any real advice other then Google "extending Application.cfc".


May 31, 2007 at 4:57 PM // reply »
207 Comments

Adobe has a full tech note on this. Search at GOogle. Sean Corfield also blogged on it.


May 31, 2007 at 7:17 PM // reply »
49 Comments

I bugged Ray about it and he pointed me to Sean's blog where indeed he has the answer!

http://corfield.org/blog/index.cfm/do/blog.entry/entry/Extending_Your_Root_Applicationcfc


Jul 19, 2007 at 11:01 AM // reply »
33 Comments

Just wanted to mention I copied your onError code as is and got an error that ARGUMENTS.Exception.RootCause.Type doesn't exist. I'm not sure you typed something wrong or my CF installation is different somehow, but RootCause doesn't exist as a key to Exception for me. There's Exception.Type, which is just a name, not something like coldfusion.runtime... Anyway, thought I'd mention this just in case.


Jul 19, 2007 at 11:04 AM // reply »
207 Comments

Yes, you need to check for the existence first. I make the mistake all the time myself.


Jul 19, 2007 at 11:17 AM // reply »
15 Comments

Yes Thomas you're right.

I noticed it only exists if your Application.cfc contains the onRequest method.


Jul 19, 2007 at 11:25 AM // reply »
6,516 Comments

Interesting. Very interesting. I have to say that I pretty much always use OnRequest() so I have never noticed this. Very good to know. Thanks.


Jul 23, 2007 at 9:28 AM // reply »
6,516 Comments

@Thomas,

Thanks for the tip. I did a quick little example to see what was different:

http://www.bennadel.com/index.cfm?dax=blog:853.view


Aug 15, 2007 at 1:36 PM // reply »
3 Comments

Hi,
I am going through converting an application.cfm to an application.cfc and am running into variables that are set in the variables scope in the application.cfm (used to be accessible in all pages of the application).

Now those variables are not accessible when I set them in the onRequestStart() or outside all the methods of Application.cfc.

The only thing I could think of to make the variables accessible from all application pages is to put them in the application or the request scope.

The problem is that I will have to add a <cfparam ..> at the top of each page that uses the variable to initialize the local variable with application/request scope variable. Can you think of anything simpler than that to accomplish the same thing?


Aug 15, 2007 at 1:40 PM // reply »
207 Comments

If yo use onRequest, then any variables you set will be in the Variables scope. This also has the side of effect of breaking Flash Remoting and Web Services, and copying other info from the CFC. Personally - I'd just use Request variables. It will help them stand out from variables made on the page itself.


Aug 15, 2007 at 1:49 PM // reply »
3 Comments

Thanks Raymond.


Aug 15, 2007 at 2:23 PM // reply »
6,516 Comments

Are you using the OnRequest() event method? That is the only way that the VARIABLES scope of the Application.cfc would be available in the processing template.


Aug 15, 2007 at 3:41 PM // reply »
3 Comments

I was not using the onRequest(). I was only using onRequestStart().
I think I may end up using the onRequest() though since there are many files to update if I use the Application/Request scope vars. The two scenarios that would be affected by using the onRequest() - Flash Remoting and WS do not apply to my app. Thanks for the info.


Aug 15, 2007 at 4:05 PM // reply »
6,516 Comments

@Ahmed,

No problem. And also, FYI, you can always conditionally delete the OnRequest() method if it is a CFC-based method call for flash remoting. But if that doesn't affect you, don't worry about it.


Aug 16, 2007 at 9:24 AM // reply »
10 Comments

Interesting Ben, how an that be done? (deleting onRequest method when making a Flash remoting or web services call)


Aug 16, 2007 at 10:11 AM // reply »
6,516 Comments

@William,

In the OnRequestStart() method, you can check the requested template. If it is a given file type (ex. .CFC) or in a certain directory or something, you can simply delete the function from the CFC scope:

StructDelete( THIS, "OnRequest" )

Then, when the ColdFusion application server finishes executing the OnRequestStart() method, it will look for OnRequest(), but it will no longer exist for that page request.


Aug 16, 2007 at 12:41 PM // reply »
10 Comments

Cool! Rule of the thumb, CFCs are objects whose properties, variables and methods can be dynamically created or removed (as in this case) at runtime.


Aug 16, 2007 at 12:45 PM // reply »
6,516 Comments

Yeah, pretty much. CFCs are super flexible that way.


Oct 9, 2007 at 4:52 AM // reply »
2 Comments

I have now tryed to use the Application.cfc. But in my code I uses cfc's in a sub catalog to make query requests.
But the problem is now that the cfc's cant see the application.DNS!?
Why is that?


Oct 9, 2007 at 7:11 AM // reply »
207 Comments

I think it depends on what you mean. You say you use CFCs in a sub catalog - do you mean subdirectory? As you know, if CF can't find an App.cfc/cfm in the current folder, it will look up higher in the directory until it finds one - so it should have no problem finding your App.cfc and if yo have app.dsn defined there, all should be well.

But - you really shouldn't be using "outside" variables in your CFCs. Why not let your App.cfc create an instances of the CFC in onApplicationStart? When you make the instance, pass in the DSN value so the CFC can store it inside itself.


Oct 9, 2007 at 7:32 AM // reply »
2 Comments

Yes I ment subdirectory.
Today I tryed to use Application.cfc again and now it worked!?
I don't know what caused the problem last time.

But your sugestion about using Application.cfc to create an instance of the cfc's that I uses sounds like a very good idea.
But how would you do that? And how should they be called from the code?
Today I call the cfc's by <cfinvoke ../>


Oct 9, 2007 at 7:45 AM // reply »
207 Comments

Typically you add a method named init to your cfcs. This method takes any configuaration parameter, like DSN. Then in App.cfc you can do
(note app = application)

cfset app.mycfc = createObject("component","path.to.your.cfc.name").init(app.dsn)>


Jan 21, 2008 at 10:33 AM // reply »
4 Comments

Hey Ben, Good stuff but are you sure you receive the application scope as a variable?

Also I have another question, I define a lot of high level stuff in those methods, yet they're completely accessible to the included template. If I don't want designers muddling with that logic, how can I make them private or inaccessible in the template's scope?

access="private" doesn't work in function definition, because the included template has private access.


Jan 23, 2008 at 10:13 AM // reply »
6,516 Comments

@Matt,

If you don't want the include to have access to the Application.cfc data, don't use the OnRequest() event method. If you exclude that method, then the requested page will simply run; but, since it is not creating a CFC mixin, then you won't have to worry about access.

If you have to use the OnRequest() event method (which I think is a wonderful method), then there is not much you can do.

What are you worried about? Developers messing with cached variables or something? I can assure you that whatever you are doing, even without the CFInclude of the requested template, developers could mess with cached data. The OnRequest() event method does not really change that at all.

I guess the variables stored in the Applicaiton.cfc via the THIS or VARIABLES scope, that is something that is OnRequest() enabled...


Jan 29, 2008 at 6:38 AM // reply »
16 Comments

Hi Ben

great tutorials and files (as ever). Thank you for everything you blog and share.

I'm a CF developer of over two years, but (ashamed to say) never used application.cfc before.
I am also on a CF8 server, and want to create a mapping to a directory to use for custom tags. I have heard that this can be done per application, but I cannot seem to get it working. I currently have the site I am working on in a /V2/ folder, with the application.cfc within.
How can I create a mapping from the .cfc to a directory to create a custom tag path?

Many thanks,

Matt


Feb 26, 2009 at 2:54 PM // reply »
19 Comments

Ben, maybe it would be a good idea to put a comment in the onRequest method that it can not be used together with cfc calls?

And/or maybe something like this in onRequestStart (commented out) for those who really want to have the onRequest in there:

<cfif listLast(arguments.targetPage,'.') is 'cfc'>
<cfset StructDelete( THIS, "OnRequest" )>
</cfif>

It is not so obvious that it does not work with cfc, because the cfc IS included and executed, and the url parames, including the method, IS available for the cfc. Still, for reasons I do not know, the cfc will not know what method to run.

Many thanks to you and this blog for helping me solve this thing. I know (now) it is described in the docs, but you really need to read it like a lawyer to see it.


RJ
May 31, 2009 at 11:23 PM // reply »
1 Comments

Thanks for all of the good examples, I am in the process of converting over an existing application.cfm to an application.cfc and used your references and examples from Skin Spider and this posting. I ran into troubles when I was trying to have an authenticated area of the website that checks for the existence of a key in the Session OnRequest and forward to a login page at a different level. It cannot find the pathing. This same code worked fine in application.cfm and its giving me some troubles here. Let me explain:

[webroot]\application.cfc = Defines application name, session management, etc.
[webroot]\applicationproxy.cfc = Stub <cfcomponent> that extends application.cfc.
[webroot]\login\index.cfm = has login and authentication code (no application.cfc)
[webroot]\members\application.cfc = authenticated area where Session.User object must exist or the user is forwarded to the ..\login\ page.

This code is returning "Could not find the included template ../login/". Any Help?

<cfcomponent
displayname="Application"
output="false"
hint="Handle the application."
extends="ApplicationProxy">

<cffunction name="OnRequest" access="public" returntype="void" output="true"
hint="Fires after pre page processing is complete.">

<!--- Define arguments. --->
<cfargument name="TargetPage" type="string" required="yes" />

<!--- If the member is not logged in --->
<CFIF StructKeyExists(Session, 'User')>
<CFIF StructKeyExists(Session.User, 'userID')>
<!--- All Good, carry on --->
<CFELSE>
<!--- The user has not logged in. --->
<cfinclude template="../login/" />
<!--- Do not allow the rest of the page to execute. --->
<cfabort />
</CFIF>
<CFELSE>
<!--- The user has not logged in. --->
<cfinclude template="../login/" />
<!--- Do not allow the rest of the page to execute. --->
<cfabort />
</CFIF>
</cffunction>

</cfcomponent>


May 31, 2009 at 11:30 PM // reply »
207 Comments

You can't cfinclude a folder. You can only include a file.


Oct 26, 2009 at 7:38 PM // reply »
42 Comments

I am being asked to clear my mysql transations from a shared hosting account. Would their be a place in the application.cfc that would be good for <cfset cfusion_dbconnections_flush()> and would this do what i need ? been looking for an ansewer i cant find it.


Oct 31, 2009 at 2:43 PM // reply »
6,516 Comments

@James,

I am not sure what you are referring to. I don't really do much of anything with databases outside of the CFQuery tag; as such, I am not sure I have any advice on some sort of transaction queue?


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 20, 2009 at 11:32 PM
Five Months Without Hungarian Notation And I'm Loving It
I've used headless camel case for years for not only ColdFusion variables, but also SQL tables and fields... pretty much everything involving code. I also subscribe to the "don't abbreviate and clea ... read »
Nov 20, 2009 at 11:00 PM
Five Months Without Hungarian Notation And I'm Loving It
@Marcel, Yeah, I always err on the side of longer but more readable variable names. As for the camel casing of CF methods and the headless camel casing of custom items, I get around this by always ... read »
Nov 20, 2009 at 10:56 PM
Five Months Without Hungarian Notation And I'm Loving It
I use the following and love it: my.namespace.MyComponents.functionMethodsOrUDF() CONSTANT_VALUES_OR_PROPERTIES One thing I always try is to CamelCaseBuiltInColdFusionFunctions() so others can tell ... read »
Nov 20, 2009 at 5:38 PM
Learning ColdFusion 8: CFImage Part I - Reading And Writing Images
Hi Ben, Great article. I've been looking around to see if ColdFusion image engine can programatically create the following "wrap around" effect: http://www.creativepro.com/article/photoshop-s-she ... read »
Nov 20, 2009 at 5:35 PM
Maintaining ColdFusion Sessions Across SMS Text Message Requests Without Cookies
@Dave: I talked to Gert he suggested: <cfhttp method="get" url="http://{some cf website}" result="stuff" addtoken="yes" /> Note the addition of cfhttp attribute addtoken. That should persist y ... read »
Nov 20, 2009 at 5:23 PM
Maintaining ColdFusion Sessions Across SMS Text Message Requests Without Cookies
@Todd, Ahh, gotcha, yeah that makes sense. ... read »
Nov 20, 2009 at 5:17 PM
Maintaining ColdFusion Sessions Across SMS Text Message Requests Without Cookies
Ben, sorry if I didn't make this clear. You can make it work like that if you want, just put <cfset session.foo = 1> (and <cfset application.foo = 1>) in your OnRequestStart() and it reve ... read »