Application, Session, and Request Scope in ColdFusion 9

Exclusive offer: get 50% off this eBook here
ColdFusion 9 Developer Tutorial

ColdFusion 9 Developer Tutorial — Save 50%

Create robust professional web applications with ColdFusion

$29.99    $15.00
by John Farrar | July 2010 | Web Development

In the previous article we had an introduction to the Application.cfc object and application variables. Next, we are going to discover the differences between application, session, and request scopes. We will learn how to share some information and how to protect the rest of the information in a controlled manner. In this article by John Farrar, author of ColdFusion 9 Developer Tutorial, we will have a look at the following topics:

  • The special standard method events, which ColdFusion calls in the Application.cfc object.
  • Custom tag paths and mapping settings inside the object—the two special functions of the Application.cfc object.

(For more resources on ColdFusion, see here.)

The start methods

We will have a look at the start methods and make some observations now. Each method has its own set of arguments. All Application.cfc methods return a Boolean value of true or false to declare if they completed correctly or not. Any code you place inside a method will execute when the start event occurs. These are the events that match with the name of the method. We will also include some basic code that will help you build an application core that is good for reuse and discuss what those features provide.

Application start method—onApplicationStart()

The following is the code structure of the application start method. You could actually place these methods in any order in the CFC, as the order does not matter. Code that uses CFCs only require the methods to exist. If they exist, then it will call them. We place them in our code so that it helps us to read and understand the structure from a human perspective.

<cffunction name="onApplicationStart" output="false">
<cfscript>
// create default stat structure and pre-request values
application._stat = structNew();
application._stat.started = now();
application._stat.thisHit = now();
application._stat.hits = 0;
application._stat.sessions = 0;
</cfscript>
</cffunction>

There are no arguments for the onApplicationStart() method. We have included some extra code to show you an example of what can be done in this function. Please note that if we change the code in this method, it will only run at the very first time when an application running in ColdFusion is hit. To hit it again, we need to either change the application name or restart the ColdFusion server. The Application variables section that was previously explained shows how to change the application's name.

From the start methods, we can see that we can access the variable scopes that allow persistence of key information. To understand the power of this object, we will be creating some statistics that can be used in most situations. We could use them for debugging, logging, or in any other appropriate use case. Again, we have to be aware that this only gets hit the first time a request is made to a ColdFusion server for that application. We will be updating many of our statistics in the request methods. We will also be updating one of our variables in the session end method.

Session start method—onSessionStart()

The session start method only gets called when a request is made for a new session. It is good that ColdFusion can keep track of these things. The following is example code that allows us to keep a record of the session-based statistics that is similar to the application-based statistics:

<cffunction name="onSessionStart" output="false">
<cfscript>
// create default session stat structure and pre-request values
session._stat.started = now();
session._stat.thisHit = now();
session._stat.hits = 0;
// at start of each session update count for application stat
application._stat.sessions += 1;
</cfscript>
</cffunction>

You might have noticed that in the previous code we used +=. In ColdFusion prior to version 8, you had to type that particular line in a different way. The following two examples are the same in functionality (example one works in all versions and two works only in version 8 and higher):

  • Example 1: myTotal = myTotal +3
  • Example 2: myTotal += 3

This is common in JavaScript, ActionScript, and many other languages. This syntax was added in ColdFusion version 8. We change the application-based setting because sessions are hidden from one another and cannot see each other. Therefore, we use the application CFC to either count or add a count every time a new session starts.

Request start method—onRequestStart()

This is one of the longest methods in the article. The first thing you will notice is that the script that is called is passed to the onRequestStart() method by ColdFusion. In this example, we will instruct ColdFusion to block any scripts from execution that begin with an underscore when called remotely. This means that you can call the server and request any .cfm page or .cfc page with an underscore at the start, and this protects it from being called outside the local server. The files can still be run if called from pages inside the server. This makes all these files locally accessible:

<cffunction name="onRequestStart" output="false">
<cfargument name="thePage" type="string" required="true">
<cfscript>
var myReturn = true;
//fancy code to block pages that start with underscore
if(left(listLast(arguments.thePage,"/"),1) EQ "_")
{
myReturn = false;
}
// update application stat on each request
application._stat.lastHit = application._stat.thisHit;
application._stat.thisHit = now();
application._stat.hits += 1;
// update session stat on each request
session._stat.lastHit = session._stat.thisHit;
session._stat.thisHit = now();
session._stat.hits += 1;
</cfscript>
<cfreturn myReturn>
</cffunction>

The methods in the following sections are used to update all the application and session statistics variables that need to be updated with each request. You should also notice that we are recording the last time the application or session was requested.

The end methods

Previously, some of the methods in this object were impossible to achieve with the earlier versions of ColdFusion. It was possible to code an end request function, but only a few programmers made use of it. We find that by using this object many more people are taking advantage of these features.

The new methods that are added have the ability to run code specifically when a session ends, and when an application ends. This allows us to do things that we could not do previously. We can keep a record of how long a user is online without having to access the database with each request. When the session starts, you can store it in the session scope. When the session ends, you can take all that information and store it in the session log table if logging is desired in your site.

Request end method—onRequestEnd()

We are not going to use every method that is available to us. As we have the concept from the other sections, this would be redundant. The concepts of this method are very similar to the onRequestStart() method with the exception that it occurs after the requested page has been called. If you create content in this method and set the output attribute to true, then it will be sent back to browser requests. Here you can place the code that logs information about our requests:

<cffunction name="onRequestEnd" returnType="void" output="false">
<cfargument name="thePage" type="string" required="true">
</cffunction>

Session end method—onSessionEnd()

In the session end method, we can perform logging functions for analytical statistics that are specific to the end of a session if desired for your site. You need to use the argument's scope variables to read both the application and session variables. If you are changing application variables as in our example code, then you must use the argument's scope for that.

<cffunction name="onSessionEnd" returnType="void" output="false">
<cfargument name="SessionScope" type="struct" required="true">
<cfargument name="ApplicationScope" type="struct" required="false">
<cfscript>
// NOTE: You must use the variable scope below to access the
// application structure inside this method.
arguments.ApplicationScope._stat.sessions -= 1;
</cfscript>
</cffunction>

Application end method—onApplicationEnd

This is our end method for applications. Here is where you can do the logging activity. As in the session method, you need to use the argument's scope in order to read variables for the application. It is also good to note that at this point, you can no longer access the session scope.

<cffunction name="onApplicationEnd" returnType="void" output="false">
<cfargument name="applicationScope" required="true">
</cffunction>

On Error method—onError()

The following code demonstrates how we can be flexible in managing errors sent to this method. If the error comes from Application.cfc, then the event (or method that had an issue) will be contained in the value of the arguments.eventname variable. Otherwise, it will be an empty string. In our code, we change the label on our dump statement, so that it is a bit more obvious where it was generated.

<cffunction name="onError" returnType="void" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfif arguments.eventName NEQ "">
<cfdump var="#arguments.exception#" label="Application core
exception">
<cfelse>
<cfdump var="#arguments.exception#" label="Application
exception">
</cfif>
</cffunction>

ColdFusion 9 Developer Tutorial Create robust professional web applications with ColdFusion
Published: July 2010
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

(For more resources on ColdFusion, see here.)

Scope visibility

There are some places where variable scopes can be seen or used from other code pages, and others where they cannot. In this article, the creation and management of several aspects of these variables will be explained just by referring to the code. Scope just identifies and determines where something is visible. Each variable type listed in the following table has a specific range of code that can see the variable's structure for each of the scopes:

Variable scope Visibility (ability to interact with it)
Application To all ColdFusion code in this unique application while it persists.
Request To all the ColdFusion code within the same request.
Session To all the ColdFusion code in this unique application while the unique session persists and only to the connections that identify themselves to the server as that session.

There are a few other scopes that are available. These include the client scope and the server scope. These are usually avoided, but may be of use in certain unique circumstances such as a cluster of servers for instance. You will also find that there are few applications that do not find everything they need in either of these scopes. The client scope has a number of limitations. The server scope can be a security risk and is a very bad idea on shared hosting servers because people who share your server can read and write to the same values as you. Therefore, in this scenario, it is not considered best practice to use the server scope unless you have a very controlled server environment.

Let us create a set of example pages to exercise the knowledge that we have just gathered. First, we will look at our Application.cfc file:

<cfcomponent output="false">
<cfscript>
this.name = "ApplicationName1";
this.applicationTimeout = createTimeSpan(0,2,0,0);
this.clientManagement = ;false;
this.clientStorage = "";"cookie";
this.loginStorage = "session";
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0,0,0,20);
this.setClientCookies = true;
this.setDomainCookies = false;
this.scriptProtect = false;
</cfscript>
<cffunction name="onApplicationStart" output="false">
<cfscript>
// create default stat structure and pre-request values
application._stat = structNew();
application._stat.started = now();
application._stat.thisHit = now();
application._stat.hits = 0;
application._stat.sessions = 0;
</cfscript>
</cffunction>
<cffunction name="onSessionStart" output="false">
<cfscript>
// create default session stat structure and pre-request values
session._stat.started = now();
session._stat.thisHit = now();
session._stat.hits = 0;
// at start of each session update count for application stat
application._stat.sessions += 1;
</cfscript>
</cffunction>
<cffunction name="onRequestStart" output="false">
<cfargument name="thePage" type="string" required="true">
<cfscript>
var myReturn = true;
// fancy code to block pages that start with underscore
if(left(listLast(arguments.thePage,"/"),1) EQ "_")
{
myReturn = false;
}
// update application stat on each request
application._stat.lastHit = application._stat.thisHit;
application._stat.thisHit = now();
application._stat.hits += 1;
// update session stat on each request
session._stat.lastHit = session._stat.thisHit;
session._stat.thisHit = now();
session._stat.hits += 1;
</cfscript>
<cfreturn myReturn>
</cffunction>
<!--- *** This is generally not used ***
<cffunction name="onRequest" returnType="void">
<cfargument name="thePage" type="string" required="true">
<cfinclude template="#arguments.thePage#">
</cffunction>
<cffunction name="onRequestEnd" returnType="void" output="false">
<cfargument name="thePage" type="string" required="true">
</cffunction>
<cffunction name="onApplicationEnd" returnType="void"
output="false">
<cfargument name="applicationScope" required="true">
</cffunction>
<cffunction name="onSessionEnd" returnType="void" output="false">
<cfargument name="SessionScope" type="struct" required="true">
<cfargument name="ApplicationScope" type="struct"
required="false">
<cfscript>
// NOTE: You must use the variable scope below to access the
//application structure inside this method.
arguments.ApplicationScope._stat.sessions -= 1;
</cfscript>
</cffunction>
<cffunction name="onError" returnType="void" output="true">
<cfargument name="exception" required="true">
<cfargument name="eventname" type="string" required="true">
<cfif arguments.eventName NEQ "2">
<cfdump var="#arguments.exception#" label="Application core
exception">
<cfelse>
<cfdump var="#arguments.exception#" label="Application
exception">
</cfif>
</cffunction>
</cfcomponent>

Now, we will create (or we may use the example file for) a page called index.cfm by making a new page file on the server.

Practical application

In this section, we are going to discuss a couple of variations on where and how to use scoped persistence. This means by using one of the scopes listed earlier, we can have a variable or CFC object last for the entire visibility period in the table.

Let us say we create a CFC called user.cfc, and then inside the Application.cfc in the onSessionStart() method, we created an instance of the class. We would want our object to last for the full life of our session. We would create code similar to this to enhance our former code for the sessionStart method. If we check out the example code on the site, the user.cfc file has already been created. Here is the modified version. The modified code is an example of how we would create a persistent object for the user. It would last until the session expires. One of the best things about application, session, and request scoped variables and objects is that they exist until that scope expires and the server takes care of clearing them out for us when they expire automatically. When we say they no longer exist, it is because the server removes them from the computer memory resources.

<cffunction name="onSessionStart" output="false">
<cfscript>
// create default session stat structure and pre-request values
session._stat.started = now();
session._stat.thisHit = now();
session._stat.hits = 0;
// at start of each session update count for application stat
application._stat.sessions += 1;
// create an instance of the user class
session._user = createObject("component","user").init();
</cfscript>
</cffunction>

Any features that are in this object can be called from the request start or end methods. They could also be called from the actual pages requested. This is fantastic because we have now automated the creation of the user object outside our general page code. With time, we will get into the practice of packaging up more and more information into CFC classes. It would be good if we did the same thing with our statistics. We could create an extended version of the stat base class for any changes, and then all of the code would be in a single file and ready for reuse.

Universal datasource

This one may not seem that big but it sure is nice. We no longer need to pass a variable or manually code our <cfQuery /> or other data interactions. This is a required variable when working with ORM technology. Otherwise it is optional. See the following example code:

<!--- the code used before --->
<cfquery name="myQuery" datasource='myDataSource' />
<!--- the code used after --->
<cfquery name="myQuery"/>

What we should notice is the need to specifically declare the datasource is no longer needed if and only if the datasource is declared in the Application.cfc file using the variable name this.datasource. Outside the Application.cfc file, it will be visible as application.datasource.

Mappings per application

In ColdFusion, since version 8 there is a setting in Admin that allows the Application.cfc file to set custom application mappings. These are not the global mappings that existed previously. It is a great feature. Previously, these were needed to be set from the ColdFusion Administrator. Now we can set these ourselves from the application itself. Here are the instructions on how to enable them:

  • Check the Enable Per App Settings option on the Settings page of the ColdFusion Administrator. (Or ask the hosting provider, or web administrator for the site to do so.)
  • Include code similar to either of the following in your Application.cfc file:

    <cfset this.mappings["/myPDFs"] = "c:\inetpub\myPDFs\">
    <cfset structInsert( this.mappings, "/myPDFs",
    "c:\inetpub\myPDFs\")>

  • If you are using the structInsert approach, make sure that you first create the structure.

Custom tag paths per application

For those using shared hosting providers, you are now able to use custom tag paths in more secure, stable ways.Here is some good news for those using shared hosting providers. This will enable the use of custom tag path mappings set in Application.cfc similar to the previous mappings:

  • Check the Enable Per App Settings option on the Settings page of the ColdFusion Administrator. (Or, ask the hosting provider or web administrator for the site to do so.)
  • Include code similar to the following in your Application.cfc file:

    <cfset customtagpaths = "c:\mapped1,c:\mapped2">
    <cfset customtagpaths = ListAppend(customtagpaths,"c:\mapped3")>
    <cfset This.customtagpaths = customtagpaths>

Summary

This article included information on application, session, and request scope management in ColdFusion.

You may also find it practical to perform logging, closing connections, and more in the end methods of Application.cfc. Here is a list of what was covered in this article series:

  • Application.cfc
  • The concept of variable scope
  • The various methods of the Application.cfc class
  • Setting per application mappings and custom tag paths
  • Use of the OnRequest() method
  • Modification of our persistent application and session items in onRequestStart() and onRequestEnd()
  • Creating persistent variables and packaging them up into classes wherever possible

Further resources on this subject:


ColdFusion 9 Developer Tutorial Create robust professional web applications with ColdFusion
Published: July 2010
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


John Farrar

John started working with computer programming around 1977. He has had the opportunity to work on projects used by Apple, Blue Cross, Brunswick Recreation, Casio, GVSU, Johnson Controls, Sprint, and many others. This history covers over 30 years of knowledge and experience in the industry.

He started doing web development over 10 years ago. In the early days of the Web ColdFusion stood out to him not just as a way to make web pages into web applications but as a maturing solid platform good for the developer, site owner, and end users. He started at version 4.5 and has been enjoying each version upgrade more and more.

John owns a company called SOSensible. His company does work for large companies but has a special focus on also making sure technology is approachable beyond the enterprise. They have developed a number of Open Source solutions including COOP. COOP is a mix of Custom Tags and CFCs that provides structure while keeping development simpler. It demonstrates his love for the things that make ColdFusion/CFML a delightful language to build websites.

He has spoken at national and regional conferences, online meetings, and area user group meetings. He is also an Adobe User Group manager. John knows that community is a viable and productive tool to build developers and the companies they serve. He has learned much from great resources in the community including bloggers, books, conferences, and resources to great in number to mention here. He blogs at sosensible.com for the community.

Contact John Farrar

Books From Packt


JavaFX 1.2 Application Development Cookbook
JavaFX 1.2 Application Development Cookbook

Ext JS 3.0 Cookbook
Ext JS 3.0 Cookbook

ASP.NET 3.5 Application Architecture and Design
ASP.NET 3.5 Application Architecture and Design

NetBeans Platform 6.9 Developer's Guide
NetBeans Platform 6.9 Developer's Guide

Microsoft Silverlight 4 Data and Services Cookbook
Microsoft Silverlight 4 Data and Services Cookbook

YUI 2.8: Learning the Library
YUI 2.8: Learning the Library

Oracle JRockit: The Definitive Guide
Oracle JRockit: The Definitive Guide

MooTools 1.2 Beginner's Guide
MooTools 1.2 Beginner's Guide


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
i
w
j
K
x
Q
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software