Ok, three things I'd like to talk about:
1. Great post. These are exactly the kinds of questions I'd like to see
more CF developers ask.
2. regarding your user object in session:
<cfset Session.user = CreateObject( "component", "UserCFC" ).init(
dsn=Application.DSN, scope="Session" ) >
do I need to lock the session scope when calling a method of
Session.user?
I'd recommend looking into the Facade design pattern to address this
problem. I made a post outlining how we're using it to work with objects
in session:
http://www.iknowkungfoo.com/blog/index.cfm/2007/2/11/Using-a-Session-Facade-to-handle-evolving-session-variables
I think you're using your UserCFC as a Facade since you seem to be using
it to manage session variables related to the user. We use a
SessionFacade.cfc and a UserFacade.cfc
In Application.cfc:onRequestStart(), we use a lock to set the
sessionFacade into the request scope for the life of the page request.
<cflock ...>
<cfset request.SessionFacade = application.SessionFacade />
</cflock>
Now we can safely output #request.SessionFacade.getUser.get*()# anywhere
on the page. The session.user object is read using a lock inside
SessionFacade.getUser().
If you need to access session scoped variables inside another component,
then you can inject the SessionFacade into that component as Nando
described.
3. What Nando mentioned about making a reference to an object:
"In reality, all that is passed is a reference to the object. CFAS
creates a variable when you instantiate an object in memory, and when
you give it some name in some scope, then it has a reference to that
variable. CFCs are passed by reference"
Kelly Brown has a great post about that:
http://www.kellyjo.com/blog/index.cfm/2007/1/4/There-are-no-Pointers-in-ColdFusion
To get around this problem with simple variable types (i.e. string,
struct, numeric), you can use duplicate() to create a separate copy of
an existing variable:
<cfset variables.foo = duplicate(session.foo) />
Now you can change the value of variables.foo without affecting the
value of session.foo. We can't use duplicate() on objects (CFCs) yet and
I've no idea when we ever will. This is why you have to be very careful
when you're injecting session objects into other objects.
I found a problem with exactly that today (the day before open beta of
our new site. Joy!).
Another developer had injected a core session object into another object
in order to pass in its arguments in one shot. The code looked something
like this:
Application.cfc:onRequestStart()
<cflock ...>
<!--- session.data is a bean --->
<cfset request.data = session.data />
</cflock>
some.cfm
<cfset data = request.data />
<--- ... --->
<cfset moreData = createObject("component", "moreData").init()/>
<cfset moreDataDAO = createObject("component", "moreDataObj").init( DSN
= request.DSN ) />
<cfset moreData.read( moreData = moreData, data = data )/>
moreDataDAO.cfc:read()
<cfset arguments.data.init( ... ) />
<!--- etc. --->
moreData extends data and the intent was to inject moreData with data
and call data.get*() inside moreData.init(). The problem is that he
called data.init() instead of just passing the data bean into
moreData.init().
So let's follow the chain of references to see what happened:
session.data -> request.data -> variables.data -> arguments.data.init()
data.init() was called from inside the DAO without passing in values for
all the arguments of the init method. Whenever this process was run, the
data bean stayed in session, but its contents were reverted to their
default, empty values.
Fortunately it only took a few minutes to put a band-aid in place. A
complete fix should be ready by the end of the week. I think this is an
excellent example of how fragile applications can become when we forget
(or don't know) that CFCs can only be referenced in CF.
It's late and this reply has gone on long enough for now. I'm going to
clean up this last section and post it to my site along with some
additional comments. I hope everyone's replies have helped.
-- Adrian J. Moreno
-- Senior Web Developer, Technical Lead
-- Unitrin Specialty
-- Blog @ http://iKnowKungFoo.com
You are subscribed to cfcdev. To unsubscribe, please follow the instructions at
http://www.cfczone.org/listserv.cfm
CFCDev is supported by:
Katapult Media, Inc.
We are cool code geeks looking for fun projects to rock!
www.katapultmedia.com
An archive of the CFCDev list is available at
www.mail-archive.com/cfcdev@cfczone.org