Posted in ColdFusion | Posted on 03-24-2008 | 4,536 views
David asks a good question about what he thinks may be a possible negative side effect of using Application-based CFCs:
What are the implications of using a single instance of a CFC that all users' requests will access to handle performing some arbitrary functionality compared with just referencing the CFC normally (not stored in Application scope)? The most important part of my question is, do users 2-1000 have to wait for access to the #application.cfcInstance# to perform the arbitrary functionality while it's handling user 1's request?
If not, is it safe to say that using an application-scoped CFC instance could improve performance significantly if it's a CFC whose methods need to be accessed repeatedly by all users?
So first off - no - there is no "locking" involved when it comes to Application-based CFCs. You can have N issues run the same method and they will not have to wait in line. The only exception to this is if you go out of your way to make it act like so. You can add your own locking to a CFC method that could possibly single-thread the access. Unless you do this though the calls will not be handled like that.
Is it safe to say using Application-scoped instances would improve performance? Certainly in CF7 where CFC creation was a bit slow. In CF8 however this slowdown was greatly removed.
I'm wary of saying that this will always increase performance as there are always so many factors that can be in play. I can say though that if your intent is to create a service used by your entire Application, I can't think of a reason not to create it one time only. Now whether you store it in the Application scope or load it via ColdSpring (or whatever), that depends on the application at hand, but in general, I'd recommend creating it once and keeping it in RAM.


Can you expand on the use-cases of an application based CFC?
On our app, I have a CFC that as of yesterday, will be hit (quite possibly) 100s of times by one user using a new "AutoSave" feature we introduced. In Flex, when users move from item to item, we save the current work to the DB through our CFC. I'm curious if moving this kind of functionality into the application scope would create a worthy speed difference.
It sounds like your Flex app is hitting a CC, is it not? I normally would use a CFC 'proxy', by that I mean a CFC that works with the 'real' application-scoped CFCs. This lets me use Application configured CFC from Flex.
The Flex app has a wizard. The Wizard is between 9 and 13 steps, depending on the options you choose. Flex makes a request on a CFC with a method called "Update" each time the view changes. This logic was just added, because we had kept all the information "in state" on the client, but some people clicked the HTML Header, or their Favorites, or their Home Button, and lost 9-13 steps worth of work. :)
I guess my confusion lies in defining when I wouldn't create my CFCs in the application scope and when I would. For example:
The "Login" CFC would run each time a user hits the app.
The "Fetch Regions" CFC would run each time a user hits the app.
The "UpdateEvent" CFC would run each time a user hits the app.
I could theoretically store all of the above in the application scope. Is that reasonable? Are there drawbacks? What kind of speed gains are there to storing a CFC in the application scope?
Are you loading the CFCs into application scope in the Application.cfc?
I can't tell you if it makes sense to use the App scope w/o knowing even more about your app. It depends! First off - remember you can't hit an Application scoped CFC via Flex. You have to hit a proxy CFC instead that would integrate with the Application scoped CFC. There really aren't any drawbacks if you are using CFCs are basic services, which it sounds like you are.
Regarding the proxy CFC, one example of that would be if you had a 'user' component with an 'authenticate' method, but you needed to be able to authenticate through a flash client, you could create a proxy cfc 'remote' access method named 'userProxy.cfc' and have a remote method in it named 'authenticate' that calls 'application.user.authenticate()' and this way you have a controled method for breaking encapsulation within a cfc.
Hope that makes sense.
I'll give it a shot tonight. I'm curious as to the speed difference.
The application that sparked my initial question can have thousands (and hopefully tens of thousands soon) of users navigating the site at the same time, so moving to a set of application-scoped CFCs, I'm hoping, should cut out a lot of unnecessary workload fat.
Beyond performance though, a side benefit I've noticed is that it just makes sense and seems more logical to store a single instances of CFCs in the application scope from a development standpoint. I much prefer using:
<cfSet wtf = application.instance.freakOut('#session.idUser#', '#now()#') />
to
<cfinvoke component="aksl.sjd.jsdfj" method="freakOut" idUser="#session.idUser#" timeStamp="#now()#" returnVariable="wtf" />
<cffunction name="appStart">
<cfset application.users = CreateObject("component", "cfc.users")>
</cffunction>
<cffunction name="onApplicationStart">
<cfset this.appStart()>
<cfreturn true>
</cffunction>
<cffunction name="onRequestStart">
<cfif IsDefined("URl.AppReset")>
<cfset this.appStart()>
</cfif>
<cfreturn true>
</cffunction>
I'll also take this opportunity to act like a grown up and mention that, "Kids, the example Michael showed above is for development purposes only. When you move your application to a production server, you need to amputate the ability of anonymous users to reset it. Slash stay in school" - Grown Up Dave.
Thanks Michael.
Things like Services (the API to the model) and Gateways (CFCs that deal with database queries) are usually great candidates for the application scope because they have no instance data. You just pass in arguments and get back a result.
On the other hand, CFCs that have state (often called "business objects") do have state, and these are usually created on a per-request basis. They're also called "transient" objects because they only stick around for one request. So something like a User CFC, or an Address, or a Company, do contain state since they represent specific entities. So those would not be good for the application scope (in fact they'd probably be really bad).
Hopefully that helps a bit.
Singletons can certainly have instance data, it just generally doesn't change once the CFC has been created.
The "state" would be represented by the current values of the CFC's properties at any given time. As users and code interact with the application, the CFC's instance variables' values can change, thereby altering its state.
By placing a CFC instance in the application scope, you're ensuring that it, and its properties/state will live before, during, and after each subsequent request until either ColdFusion is restarted or some other mechanism overwrites the instance with a new instance (such as Michael's user-triggered appStart function above).
Can you not call Application.cfc methods from ordinary application-child code?
I have these two methods in Application.cfc:
<!--- f: onApplicationStart --->
<cffunction name="onApplicationStart" returnType="boolean" output="false">
<!--- Initialize application variables --->
<cfreturn reinitializeApplication() />
</cffunction>
<!--- x: onApplicationStart --->
<!--- f: reinitializeApplication --->
<cffunction name="reinitializeApplication" returntype="boolean" output="false" >
<!--- Etc. --->
<cfreturn true />
</cffunction>
<!--- x: reinitializeApplication --->
Although the application correctly initializes as predicted, when I call reinitializeApplication() from the Index.cfm file for example, I get this error:
Error: The initializeApplication method was not found.
Here's the code that calls it, I'm not sure what I'm doing wrong.
<!--- Check for an application reset trigger (development purposes only) --->
<cfif etc eq 'Reset'>
<cfset application.initializeApplication() />
</cfif>
Any ideas? Can you just not call Application.cfc methods outside of the file?
Just ignore that. The same problem still exists even when I attempt to call the correct function name.
you can include this line
<cfset application.applicationCFC = this>
then in your index file and any other file in your application you can reference application.applicationCFC.resetApp or whatever.. I haven't tried this reference but it should work.
I just meant outside of the Application.cfc file, particularly, non-core methods (in this case reinitializeApplication, my custom function).
Michael:
That did it! Exactly what I was looking for. Thanks!
As far as a sitewide maintenance mode, Adobe HAS __kind_of__ provided this for us (I don't know what that underscore syntax means, I've just seen Ray use it before so thought I'd give it a shot).
The onRequestStart method. All we have to do is flip the switch and decide what to show instead.
I wrote this the other day, it's a pretty good example of just how easy ColdFusion makes it. This code goes in the onRequestStart method (probably before anything else).
<!--- Sitewide maintenance mode mechanism. Intercepts any request for site content and aborts it, serving alternate content --->
<!--- Just set sitewideMaintenanceMode to true to activate --->
<cfset sitewideMaintenanceMode = false />
<!--- If sitewide maintenance mode is active, serve alternate content and abort processing on every request --->
<cfif sitewideMaintenanceMode >
<cfinclude template="/Mechanics/AlternateContent/Maintenance.cfm" />
<cfabort />
</cfif>
The coolest thing about it is that you can have various modes and pre-written messages and just toggle them with simple variable / content pairs. In reality you could even move the sitewideMaintenanceMode variable into a password-protected database table and trigger it from a web-based administrator.
Long story short, ColdFusion saves lives.
Although, I'm curious as to whether you could just set handlers for other file types on your Web server and have CF pre-empt them too.
I just tried setting CF script map for the .htm type in IIS 7 and it serves "The service is unavailable". I don't know that much about Web server configuration, but this is kind of an interesting concept. It'd let you protect a lot of non-CF content(like .jpg files for example)from being accessed directly through URLs.
Anyone IISperts out there that can answer this?
I think the "Down for Maint" page is going to need CFHeaders added to let the Search Engine Spiders know that the page is down for "X time" and the redirect is temporary in nature.
This type of functionality should be built in to the App.cfc when it's first generated, I think, because:
1) it's commonly used
2) the details are important
I'd just argue that the Coldfusion framework is well done by Adobe, but Adobe should still support their own homegrown framework with this type of functionality built in.
Thanks!
http://www.alagad.com/blog/post.cfm/troubleshootin...
showing memory leaks if duplicate not used.
"This simple example is just an illustration of how you can get yourself into trouble when pointing a reference to objects from a shared scope like application or server, into a local scope like request. When we make a link from the request scope into the application scope, it maintains a reference such that the request variable would never go away until the referencing application variable gets garbage collected (which would wait for the application timeout). By duplicating the object into the request scope instead, this ensures there is no reference to the application scope variable, which allows it to be cleaned up after the request completes."
Can we really believe these leaks are over?
To be clear, I mean to use the Request scope as a duped copy of app.whatever.
[Add Comment] [Subscribe to Comments]