No, I'm not talking stealing from innocent CFCs, but rather about the use of duplicate() on CFC instances. I know I've blogged about it before (although I didn't find it in a quick search), but you must remember to not call duplicate() on a CFC. Here is a Ask a Jedi question I got earlier in the week:
It's long and confusing, but have you observed a condition in which you the variable scope inside a component seems to collapse into the callers variable scope...To wit: (i've been following some of your examples, so bear with me): I have a StudentDAO, StudentBean, and StudentManagerStudentDAO only has create, read and update
StudentBean establishes the variables.instance scope via the init() function, and hass all the getters and setters that interact with variables.instance
StudentManager did this:
established an array
populated the array with Duplicate(Beans) from mutiple reads to StudentDAO.
There was more after this but I stopped reading at the duplicate. Prior to CFMX 7.01 (it may have been CFMX7), you could duplicate a CFC. What you got, however, was a pale shadow of a real CFC. It may have acted, a bit, like a CFC, but it wasn't. Luckily (and again, I can't remember if it was 7.01 or 7) this has been fixed. By "fixed" I mean you will now get an error if you try to duplicate a CFC. That isn't great, but it is a heck of a lot better than silently failing.
So again - forgive me for repeating myself (hey, just get me started on var scoping!) but I wanted to ensure this was on everyone's radar.
I'll be presenting on CFCs at CFUnited, and this is one of the topics I plan on covering. I have a good 3 hours to kill so I will doing both basic syntax (for those who haven't written any CFCs), and more advanced topics on organization, and tips and tricks. (So for example, if you wanted to duplicate a CFC, what are some ways of doing it.)
That's it for me folks. It's off to the airport in lovely Aspen and time to return to a place where the air isn't quite as thin!
Archived Comments
Ray, do you know why it is that we can't duplicate? I know the tricks and ways around it (i definately use them!) but is there a technical reason why adobe cant make it work, a philisophical reason why its a bad idea, or is it just that they havent done it? I can think of several places where it would make life easier...
OK, I must ask why in the world you would want to dupe a .cfc, as opposed to just sticking an instance into the server or application scope....
For instance, I use an image handling .cfc, and I just plunk that puppy into the server scope so multiple applications can use it at once. Why would I want to make a true 'copy'??
In your example, an Image CFC serves like a service. You only need one. But inthe user's example, he was using beans, differnet instances of a CFC where each was unique.
Ryan: Why? No, I don't know.
Ray,
I think Justice is at the point I was a few weeks ago. I used cfc to run queries and do data manipulation, but was setting things specific to users in the session scope. When I was dissecting your LightHouse app to add in Oracle I finally had the eureka moment where it made sense as to why anyone would put a cfc in a session scope.
Justice,
Ray is talking about Beans and DAO and to understand it better, imagine where every user comes to your shopping site. Instead of setting session.whatever for that user you create a cfc called a bean in the session scope. That bean holds all of the normal information you would keep in your session scope. session.userid wold become session.userBean.getUserID, in your cfc the only thing it would do is return variables. To get some more information on this disect some of Ray's applications. I worked on LightHouse and can vouch for that one giving you a better understanding of this process. Now that I have seen how this works I have gone out of my way to try and use this method because it just makes sense. Instead of having session variables set all over my application a developer can open up the bean cfc and know exactly what variables they will have access to throughout the application.
Hope that helps some.
Bob Everland
Hrmmm, that is interesting for sure. I can see how it would be nice to have everything encapsulated, and really the only difference from using a structure in the application scope would be that you could perform function inside your bean and then 'read' variables from it wherever you needed, as well as being able to dispose of it with 1 command.
Now, if you do a <cfset application.myUserData = CreateObject('Component', 'myUserManagerComponent') />, does that not create an instance of your component that can do the same thing without having to duplicate() it?
As a side note, where did the name 'bean' come from, I am assuming its a java thing? =)
Well keep in mind that if you do it in the application scope it would be available to the whole app, if it was specific to the user you would want to create it in the session scope. You don't HAVE to create it in the session scope at all. The main idea behind creating a user bean is that in other languages you can pass an object around, but you can't in ColdFusion(perhaps other web programming languages, can't comment for sure on that though). To get around that and to get around having to read the database each time I want to get a user's information I just put the bean in the session scope(you could work with a bean as a local variable and use your application cfc to read the user recrod each time, this is not a great method because you have to hit the database each time). Another benefit of doing it the bean method is that you can pass a whole bean into an update, or create method. So for instance if you normally have a function that looks like this application.userManager.createRecord(firstName, lastName, email, phone, address1, address2, city, state, zip) you could do this application.userManager.createRecord(userBean). Then inside of that createrecord instead of saying update record set firstname = arguments.firstname you can say update record set firstname = arguments.getfirstname() . That's where it is very helpful for me. I had some functions that I was passing in like 30 parameters, it was becoming unmanageable.
I should clarify, when I said you can't pass the bean around, I meant from page to page. You can pass the bean(local variable) in the page you are, but to pass it to another page it would need to be recreate (hence the duplication issue) or put into a sesion variable. Sorry if I made some confusion