Copy link to clipboard
Copied
Hi,
I have 2 CFC's that I have written for a flex based app, 1 is a cache manager to store CFC's in the application scope, the other is something called voFactory.cfc, which will take a query object or structure, and convert it into an array of typed objects for flex. I need to find out where locking would be appropriate here, btw- this is CF 8.
the line in red bold is throwing an error- trying to reference elements in the metadata of a CFC that should exist, but for some reason don't. The error is always something like:
The element at position 19 of dimension 1, of array variable "PROPERTYARRAY," cannot be found.
The element is random though as is the error, there is nothing distinct about where it throws the error, so I'm thinking race condition of some sort.
Here are examples of how they get called in code, followed by snippets of the code,
<cfreturn application.voFactory.query2ValueObjects(qGetEvents,'vo.EventVO') />
and
<cfset dataStruct.CLIENTLIST = application.cacheManager.getComponent("clients").getClientList()>
the two CFCs rely on each other, the voFactory pulls the value object CFCs from the application scope cache.
onApplicationStart() code:
<cfset application.voFactory = createObject("component","API.system.voFactory").init()>
<cfset application.cacheManager = createObject("component","API.system.CacheManager").init()>
Here is relevant part of the cache manager:
<cffunction name="getComponent" access="public">
<cfargument name="componentName" type="string" required="true">
<!--- If it exists in cache, retrieve else create --->
<cfif not structKeyExists(this.componentList,arguments.componentName)>
<cfset this.componentList[arguments.componentName] = createObject("component",'API.' & arguments.componentName)>
</cfif>
<cfreturn this.componentList[arguments.componentName]>
</cffunction>
And the voFactory cfc
<cffunction name="query2ValueObjects" hint="Converts a query to array of value objects" access="public" returntype="array" output="false">
<cfargument name="queryObject" type="query" required="true">
<cfargument name="valueObjectPath" type="string" required="true">
<cfset var path = ''>
<cfset var propertyArray = ''>
<cfset var tVO = ''>
<cfset var loopQuery = ''>
<cfset var property = ''>
<cfset var returnArray = ''>
<cfset loopQuery = arguments.queryObject>
<cfset path = arguments.valueObjectPath>
<!--- I GET THE PROPERTIES OF THE VO, LOOP OVER THEM TO CREATE TYPED OBJECTS --->
<cfset propertyArray = GetMetaData(application.cacheManager.getComponent(path)).properties>
<cfset returnArray = arrayNew(1)>
<cfloop query="loopQuery">
<cfset tVO = structNew()>
<cfset tVO['__type__'] = 'API.' & arguments.valueObjectPath>
<cfloop from="1" to="#ArrayLen(propertyArray)#" index="property">
<cftry>
<!--- ONLY USE SCALAR VALUES --->
<cfif propertyArray[property].TYPE EQ 'string' OR propertyArray[property].TYPE EQ 'numeric' OR propertyArray[property].TYPE EQ 'date'>
<cfset tVO[propertyArray[property].NAME] = loopQuery[propertyArray[property].NAME][loopQuery.CurrentRow]>
</cfif>
<cfcatch>
<!--- debug code --->
<cfrethrow>
</cfcatch>
</cftry>
</cfloop>
<cfset arrayAppend(returnArray,duplicate(tVO))>
</cfloop>
<cfreturn returnArray>
</cffunction
Copy link to clipboard
Copied
Without reviewing any of the logic, I noticed the loopQuery variable is not var scoped.
Copy link to clipboard
Copied
thanks for looking at it, but loopQuery is var scoped, it's the 4th var at the top of the function.
d.
Copy link to clipboard
Copied
You are correct. My bad.
Copy link to clipboard
Copied
It might help to initialize the array right after you define it, something like this
<!--- Define array --->
<cfset var propertyArray=arrayNew(1)>
<!--- Initialization: array expected to hold at least 20 structures --->
<cfset temp = ArraySet(propertyArray, 1,20, structNew())>