I've been following the 'Application Scoped CFC' and the
'application-scoped singletons and thread safety' threads with great
interest. Unfortunately I'm no feeling like I've read an answer that
clarifies things for me, hence this post. It's a bit long only b/c I've
included some code snippets to clarify my example. Here's my issue, even
if you var scope variables w/in functions w/a CFC, use the 'variables'
scope to store member data for that CFC, use a factory to access the CFC
and then place that factory w/in application scope, where do I put the
locks? Here's pieces of code for 5 files (AppFactory.cfc,
UserManager.cfc, Application.cfc, dsp_User.cfm & dsp_Users.cfm) to
illustrate. (I've commented and omitted sections to keep it as brief as
possible.)
<!--- ================= AppFactory.cfc ================= --->
<cfcomponent name="appFactory">
<cffunction name="init">
<cfset variables.me = structNew()>
<cfset variables.me.UserMgr = "">
<cfset variables.me.dbMgr = "">
</cffunction>
<cffunction name="initDBManager">
<cfargument name="dsn">
<cfset variables.me.dbMgr =
createObject("component","DBManager").init(arguments.dsn)>
</cffunction>
<cffunction name="getUser" returntype="User">
<cfargument name="UserID">
<cfif isObject(variables.me.UserMgr) eq false>
<!--- Note: omitting code to ensure me.dbMgr really has been
initialized for this example --->
<cfset variables.me.UserMgr =
createObject("component","UserManager").init(variables.me.dbMgr)>
</cfif>
<cfreturn variables.me.UserMgr.getUser(arguments.UserID)>
</cffunction>
<cffunction name="getUsers" returntype="query">
<cfif isObject(variables.me.UserMgr) eq false>
<!--- Note: omitting code to ensure me.dbMgr really has been
initialized for this example --->
<cfset variables.me.UserMgr =
createObject("component","UserManager").init(variables.me.dbMgr)>
</cfif>
<cfreturn variables.me.UserMgr.getUsers()>
</cffunction>
</cfcomponent>
<!--- ================= AppFactory.cfc END ================= --->
<!--- ================= UserManager.cfc ================= --->
<cfcomponent name="UserManager">
<cffunction name="init">
<cfargument name="dbMgr">
<cfset variables.me = structNew()>
<cfset variables.me.dbMgr = arguments.dbMgr>
<cfset variables.me.users = "">
</cffunction>
<cffunction name="getUser">
<cfargument name="userID">
<cfset var retVal = createObject("component","User").init()>
<cfset var local = structNew()>
<cfquery name="local.getUser" dsn="#variables.me.dbMgr.getDSN()#">
SELECT * FROM users WHERE user_id = #arguments.userID#
</cfquery>
<cfset retVal.setUserID(local.getUser.userID)>
<!-- Remainder of sets & code to ensure we actually have
something to set are omitted -->
<cfreturn retVal>
</cffunction>
<cffunction name="getUsers">
<cfargument name="userID">
<cfset var retVal = createObject("component","User").init()>
<cfset var local = structNew()>
<cfquery name="local.getUser" dsn="#variables.me.dbMgr.getDSN()#">
SELECT * FROM users WHERE user_id = #arguments.userID#
</cfquery>
<cfset retVal.setUserID(local.getUser.userID)>
<!-- Remainder of sets & code to ensure we actually have
something to set are omitted -->
<cfreturn retVal>
</cffunction>
<cffunction name="getUsers">
<cfset var local = structNew()>
<cfif isQuery(variables.me.users) eq false>
<cfquery name="local.getUsers"
dsn="#variables.me.dbMgr.getDSN()#">
SELECT * FROM users
</cfquery>
<cfset variables.me.users = local.getUsers>
</cfif>
<cfreturn variables.me.users>
</cffunction>
</cfcomponent>
<!--- ================= UserManager.cfc END ================= --->
<!--- ================= Application.cfc - only applicable methods shown
================= --->
<cffunction name="onRequestStart" returnType="boolean" output="false">
1 <cfargument name="thePage" type="string" required="true">
2 <cfif (structKeyExists(url,"init") eq true)>
3 <cfif url.init eq "reload">
4 <cfset reloadAppScope()>
5 </cfif>
6 </cfif>
7 <cfset variables.appFactory = application.appFactory>
8 <cfreturn true>
</cffunction>
<cffunction name="reloadAppScope" returntype="void" output="false"
access="private" hint="I reload the application scope variabes.">
<cfset var local = structNew()>
<!--- Determine Server Mode --->
<cfif structKeyExists(application,"globalSettings") eq true>
<cfset structDelete(application,"globalSettings")>
</cfif>
<cfset application.appFactory =
createObject("component","com.myapp.AppFactory").init()>
<!--- Default Settings --->
<cfset application.appFactory.initDBManager("myDSN")>
</cffunction>
<!--- ================= Application.cfc END ================= --->
<!--- ================= dsp_User.cfm ================= --->
1- <cfset variables.aUser = variables.appFactory.getUser(url.userID)>
2-
3- <div>First name: #variables.aUser.getFirstName()#</div>
4- <div>Last name: #variables.aUser.getLastName()#</div>
5- <!--- Remainder of display form omitted --->
<!--- ================= dsp_User.cfm END ================= --->
<!--- ================= dsp_Users.cfm ================= --->
1- <cfset variables.users = variables.appFactory.getUsers()>
2- <!--- code outside loop omitted as it's just display stuff --->
3- <cfloop query="variables.users">
4- <tr>
5- <td>#firstName#</td>
6- <td>#lastName#</td>
7- </tr>
8- </cfloop>
<!--- ================= dsp_Users.cfm END ================= --->
Now for the lock location question(s). Do I put an application level
lock on...
1. Line 1 of dsp_Users.cfm since it might be writing to or reading from
an application scope variable? My answer is no since at that 'level' it
shouldn't know or care..
2. Line 1 of dsp_User.cfm since it might be reading from an application
scope variable? Again, I'd say no here. (FYI it's reading the dsn
variables stored in the DBManager which is in application scope)
3. Any appropriate location w/in the UserManager.cfc? Again, I'd say no
here since that object should know or care about the application scope.
4. In every method w/in the AppFactory.cfc that reads or could write to
application scope? My gut tells me know b/c how does the appFactory know
what goes on in the UserManager? It shouldn't so should it therefore
lock everything? No way in my opinion as that creates a bottleneck.
5. Just don't bother? Can't be the right answer based on what I've read
so where do I put the locks?
So my last option is to use duplicate on line 7 w/in the onRequestStart
method in my Application.cfc.
<cfset variables.appFactory = duplicate(application.appFactory)>
This makes some sense since the Application.cfc handles application
level locking w/in it but the amount of copying that one statement might
cause just does not seem right. So now what? I have no idea and am
looking forward to the suggestions that follow.
Thanks,
Jason
--
Jason Daiger
URL: www.jdaiger.com
EML: [EMAIL PROTECTED]
----------------------------------------------------------
You are subscribed to cfcdev. To unsubscribe, send an email to
[email protected] with the words 'unsubscribe cfcdev' as the subject of the
email.
CFCDev is run by CFCZone (www.cfczone.org) and supported by CFXHosting
(www.cfxhosting.com).
An archive of the CFCDev list is available at
www.mail-archive.com/[email protected]