4 Replies Latest reply on Aug 11, 2009 1:52 PM by BKBK

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

    Sp@ceMunkey

      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