Link to home
Start Free TrialLog in
Avatar of Robert Shia
Robert Shia

asked on

Calling the same ColdFusion component from different templates

In a.cfm I have:
<CFSET VerObj = New cfcomponents.VerFold.Ver_Users()>
<CFSET VerObj.Functiion_1(userid)>

In the next few template, c.cfm, I need to call a different function within Ver_Users.cfc I can do the same thing:
<CFSET VerObj = New cfcomponents.VerFold.Ver_Users()>
<CFSET VerObj.Function_2(userid)>

If I need to call the same cfc again from yet another template down the road and I keep doing this I think it is very awkward and repetitive? the purpose of using .cfc is so that I can reuse or call the functions by just doing:

<CFSET VerObj,Function_1()> or
<CFSET VerObj,Function_2()>

from anywhere without keep instantiating the cfc, am I correct? is there any example on how I can accomplish This?
Avatar of _agx_
_agx_
Flag of United States of America image

The primary purpose of using a CFC is to avoid repeating the same internal code over and over.  There is no one size fits all answer.  Whether or not you need to create a new instance each time all depends on

a) What the component does AND
b) Where/how the component is used.

A stateless component doesn't maintain any information about previous requests, so it is safe to create it once and store it in a shared scope. Then use that shared variable to invoke the function. For example, create an instance in your Application.cfc:

 function onApplicationStart() {
         application.yourVerObj = New cfcomponents.VerFold();
        return true;
 }

Then whenever you want to invoke the function, use the application variable:

         <CFSET application.yourVerObj.Function_2(userid)>

A stateful component, DOES store information about previous requests, and therefore is not safe to be stored in a shared scope. Doing so can cause weird results and bugs due to race conditions.  Usually you should create a new instance for each use, but again... it all depends on what the component does and how it is used.

Could you elaborate on your specific component?
If you are not familiar with statful vs stateless, here's an example.  

This is a stateless component. It doesn't maintain any info from one request to the next and returns the same result every time.  So it's safe to store in the "application" scope:

component {
	public numeric function multiply(numeric val1, numeric val2) {
		return arguments.val1 * arguments.val2;
	}
}

Open in new window


This is a slightly contrived example of a stateful CFC. It contains a variable that's maintained for the life of the component.  So when stored in a shared scope, like "application", the variable can be modified by multiple threads at the same time, leading to possible race conditions.  In some situations, that can be mitigated by locking, but for more complex components, it is simpler to just create a new instance.

component {
	
	variables.visitors = 0;
	public numeric function incrementVisitors() {
		variables.visitors = variables.visitors + 1;
		return variables.visitors;
	}

}

Open in new window

Avatar of Robert Shia
Robert Shia

ASKER

Thank you for the responses.
In my situation, I have to validate and update large user's data. For example, user's  home and business addresses, home and business telephones and emails,etc. I grouped this task by creating a component with several functions that are used to validate and update these data when their value are deemed "bad" or "unacceptable". So in the process, I'll be calling validateaddresses() then calling updateInfo()  for address in one template then telephone and emails in the next template. Thank you for helping me understand more with stateless and statefull component, I appreciated very much!
The CFC might be suitable for storing in the application scope, but .. like I mentioned, it depends on the exact code in the functions and whether or not they maintain any data from previous requests.  Any chance you could post some of the code?

UPDATE:
Some quick things to check:

1. Does the CFC write information to the VARIABLES scope? ie.

           <cfset variables.someVar  = "something">

... or

2. Does the CFC forget to use LOCAL or VAR on function local variables? For example forgetting to scope query objects or loop indexes:

 
 <cffunction name="runQuery" ....>
       <!--- This is NOT thread safe.  Forgetting to VAR / LOCAL the query object "myQuery" 
              means it ends up in the VARIABLES scope  ---->
       <cfquery name="myQuery" .....>
              SELECT Something FROM SomeTable
       </cfquery>

       <cfreturn myQuery>
</cffunction>

Open in new window


If either of those are true, the CFC is stateful and shouldn't be stored in the application scope.  #2 is especially important because it can lead to weird bugs that are difficult to track because they only appear under load.
@Robert Shia - What did you determine about the component?
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.