Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

application scope locking and caching of CFC's (pulling my hair out!)

New Here ,
Aug 10, 2009 Aug 10, 2009

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

TOPICS
Advanced techniques
1.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Aug 10, 2009 Aug 10, 2009

Without reviewing any of the logic, I noticed the loopQuery variable is not var scoped.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 10, 2009 Aug 10, 2009

thanks for looking at it, but loopQuery is var scoped, it's the 4th var at the top of the function.

d.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Aug 10, 2009 Aug 10, 2009

You are correct. My bad.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Aug 11, 2009 Aug 11, 2009
LATEST

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())>

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources