Copy link to clipboard
Copied
I haven't had the chance to use application.cfc when creating web application. Usually this is how I create session variable ,such as, session.userid after user validation. Here is an example:
First, on my application.cfm I did :
<cfapplication name="SomeName" sessionmanagement="Yes" setclientcookies="Yes" CLIENTMANAGEMENT="No" sessiontimeout="#CreateTimeSpan(0,1,0,0)#" applicationtimeout="#CreateTimeSpan(1,0,0,0)#">
Then on my loginaction.cfm page, I validate user login with something like:
<cfquery name="ValidateUser" datasource="#application.DSN#">
SELECT UserId, Username, Password FROM users
WHERE Username = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Form.username#">
AND Password = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Form.Password#">
</cfquery>
<CFIF ValidateUser.Recordcount NEQ 0>
<CFSET session.UserId = "#ValidateUser.UserId#">
</CFIF>
Once this session.UserId is created then I can use it on any query throughout the application.
Now, I want to use Application.cfc instead of Application.cfm. From my reading Within Application.cfc I can create a Function called:
OnApplicationStart, OnSessionStart, etc
It is said that: OnSessionStart 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.
I don't quite understand this explanation and especially when I want to create my session.UserId using the logic I explain above.
Below is my test when trying to work with application.cfc:
On my loginaction.cfm:
<cfinvoke component="cfcomponents.application" method="OnSessionEnd" UserName ="#Trim(Form.MyUsername)#"
Password = "#Trim(Form.myPassword>
On Application.cfc:
<cfcomponent displayname="Application" output="true" hint="Handle the application.">
<cffunction name="OnApplicationStart" access="public" returntype="boolean" output="false" hint="Fires when the application is first created.">
<cfset application.dsn = "OnBoardBuddy">
<cfreturn true/
</cffunction>
<!--- Is this the right way to set session.userid when using application.cfc? --->
<cffunction name="OnSessionEnd" access="public" returntype="void" output="false" hint="Fires when the session is terminated.">
<cfquery name="ValidateUser" datasource="#application.DSN#">
SELECT UserId, Username, Password FROM users
WHERE Username = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Form.username#">
AND Password = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Form.Password#">
</cfquery>
<CFIF ValidateUser.Recordcount NEQ 0>
<CFSET session.UserId = "#ValidateUser.UserId#">
</CFIF>
</cffunction>
</cfcomponent>
Copy link to clipboard
Copied
GKiew,
No. The correct way to establish those settings in Application.cfc is to put them in the pseudo constructor (using the "this" scope), before any of the functions. Here is an example (with all of the functions omitted for simplicity):
<cfcomponent...>
<cfset THIS.Name = "YourApplicationNameHere">
<cfset THIS.ApplicationTimeout = CreateTimeSpan(1, 0, 0, 0)>
<cfset THIS.SessionManagement = true>
<cfset THIS.SessionTimeout = CreateTimeSpan(0,1,0,0)>
<cfset THIS.SetClientCookies = true>
<cfset THIS.ClientManagement = false>
<cffunction ...>
</cffunction>
</cfcomponent>
See the following in the CF 9 Docs for more information:
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-750b.html
Ben Nadel's classic blog post gives you a pretty complete explanation of how all the parts to Application.cfc work:
HTH,
-Carl V.
Copy link to clipboard
Copied
Hi Carl, I did more reading and some questions of mine got answered, thanks for pointing out some of them.
One thing that I'm still confused is setting the session variable.
For example, When I need to create a session variable in my loginaction.cfm, such as, session.userId, HOW IS :
<CFSET session.userId = "#MyQueryName.UserId#"> in my loginaction.cfm and The OnSessionStart function included within an Application.cfc
<cffunction name="OnSessionStart" access="public" returntype="void" output="false" hint="Fires when the session is first created.">
Related to each other?
When using CFAPPLICATION, I have:
<cfapplication name="SomeName" sessionmanagement="Yes" setclientcookies="Yes" CLIENTMANAGEMENT="No" sessiontimeout="#CreateTimeSpan(0,1,0,0)#" applicationtimeout="#CreateTimeSpan(1,0,0,0>
I only need to set sessionmanagement attribute to "yes" and then on my loginaction.cfm I'm ready to do :
<CFSET session.userId = "#MyQueryName.UserId#" without having to call OnSessionStart Function.
But when I use Application.cfc, If I already put:
<cfset THIS.SessionManagement = true>
<cfset THIS.SessionTimeout = CreateTimeSpan(0,1,0,0)>
Practically I'm ready to do <CFSET session.userId = "#MyQueryName.UserId#"> anywhere in my template so why should I call OnSession.Star()?
Copy link to clipboard
Copied
You don't need to use onSessionStart() if you don't want to.
In the case above, I would use onSessionStart() to create the session.userid variable with an empty value. That way it is always there. Then in the login process I would populate it with a value.
There is nothing that says yo NEED to use onSessionStart() if you are using session management, but it is there in case you WANT to use it.
A great example is if you want every user who visits your site to have a shopping cart instantiated and ready to go (whether they are logged in or not). You would create that cart in onSessionStart() and stick it in the user session. Then later after the login process you would also populate the session with appropriate user details and associate that cart with that user.
Hope that makes sense.
Jason
Copy link to clipboard
Copied
GKiew,
Jason (@12Robots) is spot on about onSessionStart() not being necessary if you don't need to use it. In fact, all of the functions/methods in Application.cfc are optional - just use the ones you need. Each provides a hook into the various events that occur during the lifecycle of a ColdFusion application. You don't have to use them.
-Carl V.
Copy link to clipboard
Copied
OK it make sense and I do appreciate all the input. Base on what I read and your input I tried to use
OnSessionStart() in my app.cfc because I think I can set session.EntityId = 0 here and it'll come handy in a lot of places later.
So I did this:
<cffunction name="OnSessionStart" access="public" returntype="void" output="false">
<CFSET session.EntityId=0 >
<cfreturn/>
</cffunction>
Then in one of the template, I have:
<CFIF session.EntityId IS 0>
<cflocation url="index.cfm>
<CFELSE>
do something here
</CFIF>
It turns out I got an error:
It says, session.EntityId is not recognized!!
I thought I read, when using OnSessionStart() on Application.cfc and when a session.variable is set in here like the way I set my session.EntityId=0 then I do not have to use CFIF IsDefined("session.EntityId")> :
So this is unnecessary:
<CFIF IsDefined("session.EntityId">
<cfiifsession.EntityId IS 0>
<cflocation url="index.cfm>
</cfif>
<CFELSE>
do something here
</CFIF>
But when I did not use IsDefined, I got that error.
I thought when user accessing in the beginning CF will call Application.cfc, then call OnApplicationStart() then calls OnSessionStart() and the session.variable will be created why it did not happened on my testing? Am I doing this wrong?
Copy link to clipboard
Copied
Did you already have an existing session? When you added that code and attmepted to visit the page?
The best way to make sure that onSessionStart() fires is to delete your cookies for the site. My guess is you already had cookies for an established, valid session, so CF did not fire onSessionStart().
Jason
Copy link to clipboard
Copied
Hi!
I tried it again this afternoon for the first time today since I posted my question yesterday. The session variable should be gone by now since I only set the session for 1 hr.
When I first get my website up just now, it looks OK but when I click a link to another cfm template, I got this:
The following information is meant for the website developer for debugging purposes. | ||||||||
Error Occurred While Processing Request | ||||||||
|
On top of my profile.cfm I have this query:
<cfquery name="GetProfile" datasource="#application.dsn#">
SELECT * FROM Entity WHERE EntityId = <cfqueryparam cfsqltype="cf_sql_numeric" value="#Trim(session.EntityId)#"></cfquery>
On my Application.cfc I have:
<cfscript>
this.name = "MyTestApp";
this.applicationTimeout = createTimeSpan(0,1,0,0);
this.clientManagement = false;
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0,1,0,0);
this.setClientCookies = true;
this.setDomainCookies = false;
this.scriptProtect = false;
this.secureJSON = false;
this.secureJSONPrefix = "";
this.welcomeFileList = "";
</cfscript>
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<cfset application.dsn = "MyDB">
<cfreturn true/>
</cffunction>
My directory :
www
MyComp
all cfm files are under wwww but Application.cfc is within MyComp folder
Should I put Application.cfc under www together with all cfm files?
Copy link to clipboard
Copied
If /MyComp is in a parallel directory to /www, then an Application.cfc must also be in /www for it to be called for *.cfm files that are in /www. Is /www the root folder for this application?
Copy link to clipboard
Copied
I'm Sorry I did not write my directory correctly:
WWW is the root directory, under www I have the main application folder: MyTestSide where all my .cfm files are.
Then inside MyTestSide I have a few sub folders: MyComp to hold all my .cfc files and MyJSFiles to hold all my .js files
So it looks like this:
WWW
---MyTestSide
--------MyComp
--------MyJSFiles
My question is:
When I do : <cfset application.dsn = "MyDB"> inside OnApplicationStart() in Application.cfc
How come the application scope only recognized by files that are at the same directory as Application.cfc???
So when I place Application.cfc at MyTestSide, only .cfm files recognized #application.dsn#
.cfc files in the SubFolder don't know what #application.dsn# is??? It doesn't make sense.
I thought:
1. Application scope was recognized throughout the whole application
2. CF server first look for Application.cfm and/or Application.cfc before running the application so it doesn't matter
whether Application.cfc is located, am I wrong?
Copy link to clipboard
Copied
Do you have any Application.cfc files in your sub-folders?
Are you running CF9 (or 10)? I believe CF9 added a new feature that allows you to change the default lookup order for the Application.cfc file. What is your's set to? In the admin under Server Settings > Settings. Scroll down and you should see these options:
Application.cfc/Application.cfm lookup order |
Specify the option ColdFusion should use to search for an Application.cfc/Application.cfm if it is not found in the current folder. By default, ColdFusion will search until the system root.
Copy link to clipboard
Copied
Your Application.cfc must be within a direct ancestor directory of the file currently being requested. It cannot be in an adjacent directory, or a directory adjacent to an ancestor. CF finds the Application.cfc by checking the current dir, then moving upwards towards to root of the drive (or the webroot, or the application root, depending on the setting).
EG: if you have this directory structure:
C:\path\to\my\coldfusionroot\then\my\webroot\and\then\the\file\being\requested.cfm, it will look in these directories:
C:\path\to\my\coldfusionroot\then\my\webroot\and\then\the\file\being\
C:\path\to\my\coldfusionroot\then\my\webroot\and\then\the\file\
C:\path\to\my\coldfusionroot\then\my\webroot\and\then\the\
C:\path\to\my\coldfusionroot\then\my\webroot\and\then\
C:\path\to\my\coldfusionroot\then\my\webroot\and\
C:\path\to\my\coldfusionroot\then\my\webroot\
C:\path\to\my\coldfusionroot\then\my\
C:\path\to\my\coldfusionroot\then\
C:\path\to\my\coldfusionroot\
C:\path\to\my\
C:\path\to\
C:\path\
C:\
(depending on a setting, it might stop looking at the indicated places).
It will not look in C:\path\to\my\coldfusionroot\some\subdirectory\
However if you want to organise your files to minimise the number of "non-browseable" files being in your web-browseable directories (which is the correct thing to do), then you can simply out a stub Application.cfc in the webroot, and have that extend another Application.cfc within your non-browseable CF files directory (if that makes sense).
--
Adam
Copy link to clipboard
Copied
Hi all, thank you for helping.
I'm developing locally with CF9 and On my admin the Application.cfc/Application.cfm lookup order is set to "In webroot"
Shoul I change it to "Until webroot"?
I tried to read more about using extends attribute of Application.cfc and for some reason it did not work. Thanks for suggesting Adam!
Because of your suggestion, I googled more and I found Ben Nadel's posting about using cfinclude, including the root's Application.cfc in the subfolder's Application.cfc and it looks like everything works now.
All I did was:
Create Application.cfc inside my subfolder and then I just have the following:
<cfcomponent>
<cfinclude template="../Application.cfc">
</cfcomponent>
Copy link to clipboard
Copied
I'm not sure what is causing that problem. But, seriously, I wasn't kidding. Delete the cookies for that site. It is the most reliable way to ensure that onSessionStart() fires. You could also restart the server, but I think deleting cookies is probably easier.
Jason