Application.cfc

Contact Us or call 1-877-932-8228
Application.cfc

Application.cfc

There is a special reserved Application.cfc component that works much like the Application.cfm and OnRequestEnd.cfm files, but uses an object-oriented approach, which allows it to be extended in a way that the Application.cfm file cannot.

Like Application.cfm, the Application.cfc component is called before each page request. Its THIS scope is used to set the same application properties that can be set with <cfapplication>'s attributes:

Variable Description
name Name of application.
applicationTimeout Lifespan of application variables. Default is set in Administrator.
clientManagement Enable client variables. Default is set in Administrator.
clientStorage Where to store client variables. Default is set in Administrator.
loginStorage Where to store login variables (in Cookies or Session). Default is "Cookie".
sessionManagement Enable session management. Default is "No".
sessionTimeout Lifespan of session variables. Default is set in Administrator.
setClientCookies Enable cookies. Default is "Yes".
setDomainCookies Sets CFID and CFTOKEN for a domain. Default is "No".
scriptProtect Protect variables from cross-site scripting attacks. Default is set in Administrator.

The Application.cfc component has eight pre-named methods, none of which is required. They are described below.

Application.cfc Methods

onApplicationStart

The onApplicationStart method is invoked when the first page of the application is requested. It can be used to:

  • test database connections.
  • verify the existence of key files.
  • test the mail server.
  • set application variables.
  • log the time the application started.

onApplicationEnd

The onApplicationEnd method is invoked when the application times out. It can be used to log the time the application ended.

onRequestStart

The onRequestStart method is invoked at the start of every page request. It can be used to:

  • authenticate the user.
  • output a standard header.
  • include common function libraries.

onRequest

The onRequest method is invoked immediately after the onRequestStart method. It takes one argument: the path to the target page. The method can be used to:

  • filter content.
  • output a standard header.
  • output a standard footer.

onRequestEnd

The onRequestEnd method is invoked at the end of every page request. It can be used to output a standard footer.

onSessionStart

The onSessionStart method is invoked when a user's session starts. It can be used to:

  • set session variables.
  • log the time the session started.

onSessionEnd

The onSessionEnd method is invoked when the session ends. It can be used to log the time the session ended.

onError

The onError method is invoked when an exception is not caught by a try/catch block. It can be used to:

  • Log errors.
  • Display friendly error messages.
  • Email the site administrator.

We cover the onError method in greater detail in the Handling Errors.

Application.cfc Benefits

Why do we need Application.cfc? What was wrong with Application.cfm? Application.cfm certainly is useful, but it has some major shortcomings, which Application.cfc addresses.

Application.cfm Shortcomings

Only one Application.cfm page per request

Each time a page runs, ColdFusion looks for an Application.cfm page in the current directory and then in each parent directory up to the web root until it finds one. As soon as it finds an Application.cfm page, it runs it and stops looking. The problem with this system is that it makes it difficult to treat any single directory differently from the rest of the application. To do so, you have to create an entirely new Application.cfm file for that directory, even though much of the code will be the same as in the other Application.cfm files in the application. If you decide to make an application-wide change, you will have to make the change in each Application.cfm file.

ColdFusion actually searches for Application.cfc files in the same way it searches for Application.cfm files and it stops as soon as it finds one. The big difference is that one Application.cfc can extend another. This means that we don't have to repeat all the same code every time we want a slight change in functionality.

No easy way to log sessions

Application.cfm does not provide any mechanism for flagging the start and end of sessions. Application.cfc's onSessionStart and onSessionEnd methods are invoked when a session starts and ends, so the developer can easily log information about the visit.

Application code runs every time a page is requested

All the code in Application.cfm runs every time a page is requested. This makes it a less than ideal place for performing expensive tests like verifying a database connection. We can get around this by writing code to check if the database has already been verified:

<cfif NOT isDefined("APPLICATION.DatabaseVerified")> <cftry> <cfquery name="VerifyDB" datasource="Animals"> SELECT AnimalType FROM tblAnimals </cfquery> <cflock timeout="5" throwontimeout="No" type="EXCLUSIVE" scope="SESSION"> <cfset APPLICATION.DatabaseVerified = true> </cflock> <cfcatch type="database"> <cflog file="Animals" type="error" text="Message: #cfcatch.message# Detail: #cfcatch.detail# Native Error: #cfcatch.NativeErrorCode#"> </cfcatch> </cftry> </cfif>

Application.cfc's onApplicationStart method makes this simpler as the method is only invoked one time: when the application is started. This means we don't have to check to see if the connection has already been verified and we don't have to lock application variables. It also allows us to take more serious action, like stopping the application from starting. The method might be written like this:

<cffunction name="onApplicationStart" output="true"> <cftry> <cfquery name="VerifyDB" datasource="Animals"> SELECT AnimalType FROM tblAnimals </cfquery> <cflog file="Animals" type="Information" text="Application Started"> <cfcatch type="database"> <cfoutput>Datasource "Animals" not available.</cfoutput> <cflog file="Animals" type="error" text="Message: #cfcatch.message# Detail: #cfcatch.detail# Native Error: #cfcatch.NativeErrorCode#"> <cfreturn false> </cfcatch> </cftry> </cffunction>

Extending Application.cfc - An Example

Imagine a site for dogs, cats and mice. All certified animals (dogs, cats and mice) can access the main part of the site, but there is a part of the site reserved for cats and another part reserved for dogs. The directory structure looks like this:

In this demo, we will indicate who the user is by passing "who=dog" or "who=cat" along the querystring. We want the application to act as follows:

  • Animals/index.cfm and other pages under the Animals directory, but not under the Cats or Dogs directories.
    • If URL.who is undefined or does not equal "dog", "cat" or "mouse":
    • If URL.who equals "dog", "cat" or "mouse":
  • Animals/Dogs/index.cfm and other pages under the Dogs directory.
    • If URL.who is undefined or does not equal "dog":
    • If URL.who equals "dog" :
  • Animals/Cats/index.cfm and other pages under the Cats directory.
    • If URL.who is undefined or does not equal "cat":
    • If URL.who equals "cat" :

The index.cfm pages all look the same, except for the words "animal", "dog", and "cat". The code for Animals/index.cfm is shown below, followed by the code for its Application.cfc file.

Code Sample:

CFCs/Demos/Animals/index.cfm
<html>
<head>
<title>You're an animal!</title>
</head>
<body>
You're an animal!
</body>
</html>

Code Sample:

CFCs/Demos/Animals/Application.cfc
<cfcomponent>

<cfset THIS.name="Animals">
<cfset THIS.sessionManagement="true">
<cfset THIS.clientManagement="true">
<cfset THIS.setClientCookies="true">
<cfset THIS.applicationTimeout=CreateTimeSpan(2,0,0,0)>
<cfset THIS.sessionTimeout=CreateTimeSpan(0,0,20,0)>

<cffunction name="onApplicationStart">
	<!--- POSSIBLE USES:
		Test database connection
		Test mail server
		Set application variables (do not have to lock code)
		Log the start of the application
	--->
	<cfset APPLICATION.animals = "dog,cat,mouse">
</cffunction>

<cffunction name="onApplicationEnd">
	<!--- POSSIBLE USES:
		Log the end of the application
	--->
</cffunction>

<cffunction name="onRequestStart">
	<!--- POSSIBLE USES:
		Authentication code
		Output header
	--->
	<cfif NOT isDefined("URL.who") OR NOT ListContains(APPLICATION.animals,URL.who)>
		You must be a certified animal to visit this page.
		<cfabort>
	</cfif>
</cffunction>

<cffunction name="onRequest">
	<!--- POSSIBLE USES:
		Filter content
		Output header
		Output footer
	--->
	<cfargument name = "targetPage" type="String" required="true"/>
	<cfsavecontent variable="content">
		<cfinclude template="#ARGUMENTS.targetPage#">
	</cfsavecontent>
	<cfoutput> #replace(content, "badword", "%&!@", "all")# </cfoutput>
</cffunction>

<cffunction name="onRequestEnd">
	<cfargument type="String" name = "targetTemplate" required="true"/>
	<!--- POSSIBLE USES:
		Output footer
	--->
	<hr/>
	&copy; Animals Incorporated
</cffunction>

<cffunction name="onSessionStart">
	<!--- POSSIBLE USES:
		Set session variables
		Log the start of the session
	--->
	<cflock timeout="5" throwontimeout="No" type="EXCLUSIVE" scope="SESSION">
		<cfset APPLICATION.sessions = APPLICATION.sessions + 1>
	</cflock>
	<cflock timeout="5" throwontimeout="No" type="EXCLUSIVE" scope="SESSION">
		<cfset APPLICATION.currentSessions = APPLICATION.currentSessions + 1>
	</cflock>
</cffunction>

<cffunction name="onSessionEnd">
	<cfargument name = "SessionScope" required="true"/>
	<!--- POSSIBLE USES:
		Log the end of the session
	--->
	<cflock timeout="5" throwontimeout="No" type="EXCLUSIVE" scope="SESSION">
		<cfset APPLICATION.currentSessions = APPLICATION.currentSessions - 1>
	</cflock>
</cffunction>

<cffunction name="onError">
	<cfargument name="Exception" required="true"/>
	<cfargument type="String" name = "EventName" required="true"/>
	<!---  POSSIBLE USES:
		Log errors
		Display error
		Email site administrator
	--->
</cffunction>
</cfcomponent>

This Application.cfc file includes code to set the THIS scope variables and it also includes all eight reserved methods. For our purposes, the interesting methods to look at are onApplicationStart, onRequestStart, and onRequestEnd.

onApplicationStart sets APPLICATION.animals, which determines which animals are allowed on the site.

onRequestStart checks to make sure that the visitor is an allowed animal.

onRequestEnd outputs a standard footer.

Now let's look at Dogs/Application.cfc.

Code Sample:

CFCs/Demos/Animals/Dogs/Application.cfc
<cfcomponent extends="Animals.Application" output="yes">
	<cffunction name="onRequestStart" output="yes">
		<cfif NOT isDefined("URL.who") OR URL.who NEQ "dog">
			You must be a dog to visit this page.
			<cfabort>
		</cfif>
	</cffunction>
</cfcomponent>

Things to notice:

  • The component extends Animals.Application. (For this to work, you'll need to create a mapping in Administrator to the CFCs/Demos/Animals.) This means that all the code in Animals/Application.cfc will run unless something is overridden.
  • Only the onRequestStart method, which authenticates the user, is overridden.

CFCs/Demos/Animals/Cats/Application.cfc works exactly the same way.

Next