Went through some trials and tribulations with Application.cfc this afternoon. I used what livedocs gave me, and tested the various functionality associated with each supported native function i.e. onRequestStart, onSessionStart, etc. I found some quarks with their documentation and developed an Application.cfc that works with the way I think their coder/documentation individual meant it to.
So here it is, the biggest problem I saw was with onApplicationEnd. This always throws an error so cflogging was impossible in the method but had to be trapped in onError. Hope this clears up some things for you. Now go convert over your Application.cfm, this is powerful stuff.
Update 1/12/2006: This blog entry featured at coldfusionpodcast, have a listen.
<cfcomponent>
<cfscript>
this.name = "theApp";
this.applicationTimeout = createTimeSpan(0,0,0,1);
this.clientmanagement= "yes";
this.loginstorage = "session" ;
this.sessionmanagement = "yes";
this.sessiontimeout = createTimeSpan(0,0,0,1);
this.setClientCookies = "yes";
this.setDomainCookies = "no";
this.scriptProtect = "all";
</cfscript>
<cffunction name="onApplicationStart" output="false">
<cfscript>
//set your app vars for the application
application.dsn = "theDSN";
application.sessions = 0;
</cfscript>
<cftry>
<!--- Test whether the DB is accessible by selecting some data. --->
<cfquery name="testDb" datasource="#application.dsn#" maxrows="2">
SELECT COUNT(userId)
FROM users
</cfquery>
<!--- If we get a database error, report an error to the user, log the
error information, and do not start the application. --->
<cfcatch type="database">
<cflog file="#this.name#" type="error"
text="DB not available. message: #cfcatch.message# Detail: #cfcatch.detail# Native Error: #cfcatch.NativeErrorCode#" >
<cfthrow message="This application encountered an error connecting to the database. Please contact support." />
<cfreturn false>
</cfcatch>
</cftry>
<cflog file="#this.name#" type="Information" text="Application #this.name# Started">
<cfreturn True>
</cffunction>
<cffunction name="onApplicationEnd" output="false">
<cfargument name="applicationScope" required="true">
</cffunction>
<cffunction name="onSessionStart" output="false">
<cfscript>
session.started = now();
</cfscript>
<cflock scope="application" timeout="5" type="Exclusive">
<cfset application.sessions = application.sessions + 1>
</cflock>
</cffunction>
<cffunction name="onSessionEnd" output="false">
<cfargument name = "sessionScope" required=true/>
<cfargument name = "applicationScope" required=true/>
<cfset var sessionLength = TimeFormat(Now() - sessionScope.started, "H:mm:ss")>
<cflock name="AppLock" timeout="5" type="Exclusive">
<cfset arguments.applicationScope.sessions = arguments.applicationScope.sessions - 1>
</cflock>
<cflog file="#this.name#" type="Information"
text="Session #arguments.sessionScope.sessionid# ended. Length: #sessionLength# Active sessions: #arguments.applicationScope.sessions#">
</cffunction>
<cffunction name="onRequestStart">
<cfargument name="requestname" required=true/>
<!--- Regular maintenance is done late at night. During those hours, tell
people to come back later, and do not process the request further. --->
<cfscript>
if ((Hour(now()) gt 1) and (Hour(now()) lt 3)) {
WriteOutput("The system is undergoing periodic maintenance.
Please return after 3:00 AM Eastern time.");
return false;
} else {
this.start=now();
return true;
}
</cfscript>
<!--- Check for login here --->
</cffunction>
<cffunction name="onError" output="true">
<cfargument name="exception" required=true/>
<cfargument name="eventName" type="String" required=true/>
<!--- Log all errors. --->
<!--- Display an error message if there is a page context. --->
<cfif (trim(arguments.eventName) IS NOT "onSessionEnd") AND (trim(arguments.eventName) IS NOT "onApplicationEnd")>
<cflog file="#this.name#" type="error"
text="Event name: #arguments.eventName#" >
<cflog file="#this.name#" type="error"
text="Message: #arguments.exception.message#">
<cfoutput>
<h2>An unexpected error occurred.</h2>
<p>Please provide the following information to technical support:</p>
<p>Error Event: #arguments.eventName#</p>
<p>Error details:</p>
</cfoutput>
<cfdump var=#arguments.exception#>
<cfelseif (arguments.eventName IS "onApplicationEnd")>
<cflog file="#this.name#" type="Information"
text="Application #this.name# Ended" >
</cfif>
</cffunction>
</cfcomponent>
One question. if you didnt have access to cflog (ie. in a shared hosting environment) what do you recommend logging to? Email? TextFile?
If you don't have access to cflog, I would think you would most likely not have access to cffile. Unless of course your plight is due to a version issue, sorry if it is. This is strictly an implementation issue and I would err on the side of writing to a text file if the capability exists. Use email only for "Critical" issues, i.e. an email associated with a pager or something of that nature. The reason being that if you do end up going through some type of error scenario on your machine you don't want your inbox filling up with the same error and you sure as heck do not want to be paged for every error as well 8-). Hope that helps, good luck.
Even though I have been developing exclusively in CF for 6 years or so, I have been oblivious to Application.cfc! Oh the joys of working for a small company who doesn't believe in R&D.
Anyway, your code is really clear to follow and has certainly made me go 'wow'! I can really see the potential in this. I've been using the same application.cfm for a number of years now. Time for a big change over me thinks.
<cffunction name="onRequestStart" output="true">
<cfset client.memberlanguage = "english">
<cfset client.sitelanguage = "english">
<cfset headerfile = "headerfile.cfm">
and more variables...
</cffunction>
When I run my code i am getting varible not defined error message on my page. Can someone assist, what am i doing wrong here?
Thanks
onRequestStart runs for every request, so only set variables that are absolutely necessary to set for each page request. To answer your question I do not readily see any immediate problem with the variable sets in your code example. My guess is that it is happening somewhere else in your onRequestStart.
Make sure you turn on the advance debug output via the ColdFusion administrator. It will give you line number in your Application.cfc where the error is actually occurring. Good luck.
I have now included the variables in onSessionStart function and I am still getting an error on my index.cfm page where i have included headerfile as <CFINCLUDE TEMPLATE ="#headerfile#"> I am getting error as
Variable HEADERFILE is undefined.
What could be the problem here?
Also can we have cfparam declared within onSessionStart function?
Thanks
One more thing, i have my application.cfm file sitting in the site root. . Should that be a problem here? Do i need to remove the application.cfm file from the code?
Thanks
For a global setting (like headerfile var) it is best to place in Application scope (put in onApplicationStart) and don't change it anywhere but there to avoid possible memory issues. (you should look into cflock and why it can help with memory vars).
Your cfparam question is not needed and I avoid it at as it is a bit of a blanket approach to development. Better to use isDefined in my opinion.
If you are going to use Application.cfc remove the existing Application.cfm. Feel free to take this off-line and email me with your specific questions or code files. It sounds like you are just setting up the application and I want to make sure you get off on the right foot.
I have tried the following piece of code from my application.cfm to convert it into application.cfc ...
<cfcomponent>
<cfset this.name = "myapp">
<cfset this.clientmanagement = "True">
<cfset this.loginstorage = "Session">
<cfset this.sessionmanagement = "True">
<cfset this.sessiontimeout = "#createtimespan(0,0,20,0)#">
<cfset this.applicationtimeout = "#createtimespan(0,1,0,0)#">
<cffunction name="onApplicationStart" output="no">
<!--- onApplicationStart body goes here --->
<CFSET application.datasource = "myappdatasource">
<CFSET application.ds = "myappdatasource">
<cfset application.headerfile = "header.cfm">
<cfset application.footerfile = "footer.cfm">
<cfset application.adminheaderfile = "sysheader.cfm">
<cfset application.adminfooterfile = "sysfooter.cfm">
<cfset application.sectionid = "5">
<cfset application.submissionemail='test@test.com'>
<cfset client.memberlanguage = "english">
<cfset client.sitelanguage = "english">
<cfset client.language_suffix = "">
<cfset client.showeditbar = "0">
<cfset client.pagename = "home">
<cfset client.sectionname = "Main">
<cfset client.showroot = "no">
<CFSET client.sitelocation = "http://mywebsite.com/">
<CFSET client.secsitelocation = "https://mywebsite.com/">
<CFSET client.webservicelocation = "http://mywebsite.com/webservice.asmx?WSDL">
<CFSET client.virtualpath = "">
<cfset client.editorpath="">
<cfset client.editorRpath="/uploads/">
<cfset client.editorBasepath=ExpandPath("./../../..")>
<CFSET client.hostemail = "test@test.com">
<CFSET client.registrationemail="test@test.com">
<cfset client.orderemail="test@test.com">
<cfset client.contactemail="test@test.com">
<cfset client.approvalemail="test@test.com">
<cfset client.contactemail1="test@test.com">
<cfset client.formtoolfromemail="test@test.com">
<CFSETTING SHOWDEBUGOUTPUT="No">
<cfset client.discussionemail="test@test.com">
<cfset client.imagePath="../images/english/formcreator/">
<cfset client.showFormToolDataSet=0>
<cflock scope="APPLICATION" type="EXCLUSIVE" timeout="10">
<cfobject component="cfcs.Categories" name="application.cfcs.Categories">
</cflock>
<cfset client.picofweekpath = "#virtualpath#picofweek/images">
<cfset client.staffThumbpath = "#virtualpath#staffphotos/thumbnails">
<cfset client.staffActualpath = "#virtualpath#staffphotos/images">
<cfset client.PicGalleryThumbpath = "#virtualpath#picturegallery/thumbnails">
<cfset client.PicGalleryActualpath = "#virtualpath#picturegallery/images">
<CFIF #ParameterExists(url.changelanguage)#>
<CFSET client.memberlanguage = "#changelanguage#">
</CFIF>
<cfif client.memberlanguage is "French">
<cfset client.langsuff="french">
<cfset client.imagedir="french">
<cfelse>
<cfset client.langsuff="">
<cfset client.imagedir="english">
</cfif>
<CFSET client.querystring = "">
<CFLOOP LIST="#CGI.QUERY_STRING#" INDEX="index" DELIMITERS="&">
<CFIF NOT #FindNoCase("changelanguage",index)#>
<CFSET client.querystring = #client.querystring# & "&#index#">
</CFIF>
</CFLOOP>
<CFSET client.template = #ListLast(CGI.CF_TEMPLATE_PATH,"\,/")#>
<CFSET client.uploadimagepath = #ExpandPath("./uploads")#>
<CFSET client.uploaddocumentpath = #ExpandPath("./uploads")#>
<CFSET client.uploadwebpath = "#sitelocation#uploads">
<CFSET client.sitename = "My Site">
<CFSET client.querycachedtime = #CreateTimeSpan(0,0,0,0)#>
<CFSET client.SiteSuperAdmin = 1>
<CFSET client.SiteAdmin = 2>
<CFSET client.SiteSubAdmin = 5>
<CFSET client.HostName = "My Site">
<CFSET client.sitedbtype = "sql">
<CFSET client.thumbnailpath = ExpandPath(".\picturegallery\thumbnails")>
<CFSET client.actualimagepath = ExpandPath(".\picturegallery\images")>
<CFSET client.staffthumbnailpath = ExpandPath(".\staffphotos\thumbnails")>
<CFSET client.staffactualimagepath = ExpandPath(".\staffphotos\images")>
<CFSET client.picofweekimagepath = ExpandPath(".\picofweek\images")>
<CFSET client.isMSIE = #FindNoCase("MSIE",CGI.HTTP_USER_AGENT)# OR #FindNoCase("Firefox",CGI.HTTP_USER_AGENT)#>
<cfset client.FrenchMonthsName = 'Jan, Fév, Mars, Avr, Mai, Juin, Juil, Août, Sept, Oct, Nov, Déc'>
<cfreturn />
</cffunction>
<cffunction name="onApplicationEnd" output="no">
<cfargument name = "ApplicationScope" required="true" />
<!--- onApplicationEnd body goes here --->
</cffunction>
<cffunction name="onSessionStart" output="true">
<!--- onSessionStart body goes here --->
<!--- This is where you would put code to initialize any session variables --->
<cfparam name="session.sitelanguage" default="English">
<cfparam name="session.membertypeid" default="18">
<cfparam name="session.brdpath" default="DefaultBoardRoomPath">
<cfparam name="session.argLocation" default="DefaultArgLocationPath">
<cfparam name="session.wholepath" default="DefaultWholePath">
<!--- Comments added by VL07 on 03-27-2007 --->
<cfinclude template="FreeURL.cfm">
<!--- Comments ends by VL07 on 03-27-2007 --->
<CFIF #ParameterExists(session.loginid)#>
<CFSET session.thiscurrentpage = #ListLast(CGI.CF_TEmPLATE_PATH,"\,/")#>
<CFIF Len(Trim(CGI.query_string))>
<CFSET session.thiscurrentpage = #session.thiscurrentpage# & "?#CGI.QUERY_STRING#">
</CFIF>
</CFIF>
<cf_sessioncheck>
</cffunction>
<cffunction name="onSessionEnd" output="true">
<cfargument name = "SessionScope" required=true/>
<cfargument name = "ApplicationScope" required=true/>
<!--- onSessionEnd body goes here --->
</cffunction>
<cffunction name="onRequestStart" output="true">
<!--- OnRequestStart body goes here --->
<cfswitch expression="#session.sitelanguage#">
<cfcase value="French">
<cfset request.sys_imagepath = "#virtualpath#images/English/system">
<cfset request.site_imagepath = "#virtualpath#images/French/Site">
</cfcase>
<cfdefaultcase>
<cfset request.sys_imagepath = "#virtualpath#images/English/system">
<cfset request.site_imagepath = "#virtualpath#images/English/Site">
</cfdefaultcase>
</cfswitch>
</cffunction>
<!--- <cffunction name="onRequestEnd" output="true">
<!--- OnRequestEnd body goes here --->
<cfoutput>OnRequestEnd executed<br></cfoutput>
</cffunction> --->
<!--- onError is equivalent to CFERROR in application.cfm --->
<!--- <cffunction name="onError">
<cfargument name="Exception" required=true/>
<cfargument type="String" name="EventName" required=true/>
<!--- Log all errors. --->
<cflog file="#This.Name#" type="error" text="Event Name: #Arguments.Eventname#">
<cflog file="#This.Name#" type="error" text="Message: #Arguments.Exception.message#">
<cflog file="#This.Name#" type="error" text="Root Cause Message: #Arguments.Exception.rootcause.message#">
<!--- Display an error message if there is a page context. --->
<cfif NOT (Arguments.EventName IS "onSessionEnd") OR (Arguments.EventName IS "onApplicationEnd")>
<cfoutput>
<h2>An unexpected error occurred.</h2>
<p>Please provide the following information to technical support:</p>
<p>Error Event: #Arguments.EventName#</p>
<p>Error details:<br>
<cfdump var=#Arguments.Exception#></p>
</cfoutput>
</cfif>
</cffunction> --->
</cfcomponent>
Wow. Its time to stop your developing and do some studying.
This is not the right way to build an application.
Anna
________________
http://skylinemp3.com/
This is how my application.cfc looks like right now:
<cfcomponent displayname="Application" hint="The Application CFC" output="yes">
<cfset this.name = "testdsnapp">
<cfset this.sessionmanagement = true>
<cfset this.loginstorage="session">
<cfset this.sessiontimeout = CreateTimeSpan(0,0,30,0)>
<cfset this.applicationtimeout = CreateTimeSpan(2,0,0,0)>
<cffunction name="onApplicationStart">
<cfscript>
application.DSN = "dsnname1";
application.dbUserName = "dbusername1";
application.dbPassword = "dbpass1";
</cfscript>
</cffunction>
<cffunction name="onRequestStart">
<cfscript>
request.DSN = "dsnname1";
request.dbUserName = "dsnname1";
request.dbPassword = "dsnname1";
</cfscript>
</cffunction>
</cfcomponent>
------------------------------------
and in my testdb.cfm file it looks like this:
<cfquery name="login_validate" datasource="#request.DSN#" username="#request.dbUserName#" password="#request.dbPassword#">
SELECT User_ID, MemberType, Username, Password, FirstName, LastName, FolderName
FROM tbl_Users
WHERE Username = 'myusername1'
</cfquery>
<cfdump var="#login_validate#">
<cfif login_validate.recordcount eq 1>
<cfoutput>yes</cfoutput>
<CFELSE>
<cfoutput>no</cfoutput>
</cfif>
------------------------------------
this is the error i am getting:
The following information is meant for the website developer for debugging purposes.
Error Occurred While Processing Request
The system has attempted to use an undefined value, which usually indicates a programming error, either in your code or some system code.
Null Pointers are another name for undefined values.
Resources:
Check the ColdFusion documentation to verify that you are using the correct syntax.
Search the Knowledge Base to find a solution to your problem.
Browser Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
java.lang.NullPointerException
at coldfusion.runtime.TemplateProxyFactory.resolveName(TemplateProxyFactory.java:115)
at coldfusion.runtime.TemplateProxyFactory.resolveFile(TemplateProxyFactory.java:85)
at coldfusion.cfc.CFCProxy.<init>(CFCProxy.java:91)
at coldfusion.runtime.AppEventInvoker.<init>(AppEventInvoker.java:32)
at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:116)
at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:51)
at coldfusion.filter.PathFilter.invoke(PathFilter.java:86)
at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:69)
at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:52)
at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
at coldfusion.filter.RequestThrottleFilter.invoke(RequestThrottleFilter.java:115)
at coldfusion.CfmServlet.service(CfmServlet.java:107)
at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:78)
at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:257)
at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:541)
at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:204)
at jrunx.scheduler.ThreadPool$DownstreamMetrics.invokeRunnable(ThreadPool.java:318)
at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:426)
at jrunx.scheduler.ThreadPool$UpstreamMetrics.invokeRunnable(ThreadPool.java:264)
at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)
-------------------------
when I use a DSN less connection, i am able to connted to the db and retrieve the records. The host says the DSN is working fine.
I also recommend you turn on full/detailed debugging for your dev server if you have not. It will give you the line number of the suspect code. Should be a very easy/straightforward resolution.
For financial sites like banking, etc. keep it low. For sites where timeouts become a pain for user experience bump it up. Also, the timeout only runs on inactive sessions or of course if the application itself has been inactive for the specified time. Be sure to check out Server scope as well.
It is great for cross multi-application data storage on the CF instance. Remember not to over utilize any scope that impacts server memory. For instance if you plan to have thousands of users, session storage can become an issue if you are storing large amounts of data there. Best to enhance db calls in this scenario. Good luck!
But in this example, am I reading it wrong? Is not the last value for createTimeSpan seconds? Is this a typo or...
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef...