Since I didn't get a single response on the first posting I thought I'd
try again. Below is a snippet of files used w/in an application. I'm
trying to figure out where the appropriate place (or whose job is it)
for locking application scope variables w/in these files. This is post
following up on the 'Application Scoped CFC' and the 'application-scoped
singletons and thread safety' threads from last week. Like I said in my
original post I'm not feeling like I got an answer that clarifies things
for me.
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.)
General flow: Application.cfc fires 1st on a call, then either the
dsp_User.cfm or dsp_Users.cfm will fire and make calls to the
UserManager.cfc via the AppFactory.cfc. Reading and writing to
Application scope can occur during either call so where do I put the locks?
I'm hoping someone out there can help shed the light on this locking
issue for me. Here's the code along w/ my locking questions at the
bottom of the post.
Thanks in advance,
Jason
<!--- ================= 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 again for reading this far..
--
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]