Ключевые моменты, прежде чем читать дальше
- Все переменные правильно изменены (вам придется мне доверять)
- Области действия не сбрасываются , пока происходят эти длительные процессы
- При сбросе метаданных для предположительно отсутствующего / недопустимого метода я получаю правильную информацию
- Есть только два места, где имя этого метода указано в приложении. Один раз, где он определен, и один раз, когда метод вызывается в коде ниже.
У меня очень странная прерывистая ошибка, которую я не могу отследить. Вот фон (они сильно обрезаны для упрощения публикации).
FeedService.cfc:
<cfcomponent output="false" extends="FeedDAO">
<cffunction name="processXmlFile" access="public" output="false" returntype="struct">
<cfset Var local = StructNew() />
/***************************************
THE VARIABLES ARE ALL VAR'D - PROMISE!!!
Lots of other stuff goes on in here to get the ultimate set of XML nodes to loop through
*****************************************/
<cfloop from="1" to="#ArrayLen(local.arrChannels)#" index="local.currentChannelItem">
... Lots of XML parsing and stuff and things going on here ...
<cfset LOCAL.invCheck = checkCustomerListing(
Acct_ID = local.invStruct.AcctID
, CustomerListingID = local.invStruct.CustomerListingID
) />
... Lots more stuff going on here ...
</cfloop>
</cffunction>
</cfcomponent>
FeedDAO:
<cfcomponent output="false">
<cffunction name="checkCustomerListing" access="public" output="false" returntype="numeric" hint="Returns the numeric inventory ID for an existing inventory listing, or 0 if the listing doesn't exist.">
<cfargument name="Acct_ID" type="numeric" required="true" hint="" />
<cfargument name="CustomerListingID" type="string" required="true" hint="" />
<cfset var rs = "">
<cfquery name="rs" datasource="#Variables.DSNs.Primary#">
SELECT ID FROM TheTable
WHERE
Acct_ID = <cfqueryparam cfsqltype="cf_sql_integer" value="#Arguments.Acct_ID#" />
AND Customer_Listing_ID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#Arguments.CustomerListingID#" />
</cfquery>
<cfif rs.RecordCount>
<cfreturn rs.Inv_ID />
<cfelse>
<cfreturn 0 />
</cfif>
</cffunction>
</cfcomponent>
Я вызываю начальную функцию следующим образом:
<cfset processStruct = Server.FeedService.processXmlFile(filePath) />
Итак, когда фид передается в функцию processXMLFile, он просматривает все элементы в файле. Файл канала может содержать 10, 100 или даже 1000 записей. Я получаю такие сообщения об ошибках во время обработки файла:
[struct]
Detail: The symbol you provided checkCustomerListing is not the name of a function.
Message: Entity has incorrect type for being called as a function.
StackTrace: coldfusion.runtime.CfJspPage$UninvocableEntityException: Entity has incorrect type for being called as a function.
at coldfusion.runtime.CfJspPage._invokeUDF(CfJspPage.java:2441)
at coldfusion.runtime.SuperScope.invoke(SuperScope.java:18)
at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2222)
Дополнительная информация о дампе стека
Type: Application
symbolName: checkCustomerListing
[object of coldfusion.runtime.CfJspPage$UninvocableEntityException]
Class Name: coldfusion.runtime.CfJspPage$UninvocableEntityException
Fields:
java.lang.String symbolName: checkCustomerListing
Parent Class: [object of coldfusion.runtime.ApplicationException]
Class Name: coldfusion.runtime.ApplicationException
Parent Class: [object of coldfusion.runtime.NeoException]
Class Name: coldfusion.runtime.NeoException
Methods:
findAdvancedCFTarget(coldfusion.runtime.AdvancedCFException, java.lang.String[]) returns int
findCustomTarget(coldfusion.runtime.CustomException, java.lang.String[]) returns int
findThrowableTarget(java.lang.Throwable, java.lang.String[]) returns int
getDetail() returns java.lang.String
getLocalizedMessage() returns java.lang.String
getMessage() returns java.lang.String
getRootCause() returns java.lang.Throwable
getString(java.lang.Throwable, java.lang.String, java.util.Locale) returns java.lang.String
getType() returns java.lang.String
setLocale(java.util.Locale) returns void
unwrap(java.lang.Throwable) returns java.lang.Throwable
Parent Class: [object of java.lang.RuntimeException]
Class Name: java.lang.RuntimeException
Parent Class: [object of java.lang.Exception]
Class Name: java.lang.Exception
Parent Class: [object of java.lang.Throwable]
Class Name: java.lang.Throwable
Methods:
fillInStackTrace() returns java.lang.Throwable
getCause() returns java.lang.Throwable
getLocalizedMessage() returns java.lang.String
getMessage() returns java.lang.String
getStackTrace() returns java.lang.StackTraceElement[]
initCause(java.lang.Throwable) returns java.lang.Throwable
printStackTrace(java.io.PrintWriter) returns void
printStackTrace(java.io.PrintStream) returns void
printStackTrace() returns void
setStackTrace(java.lang.StackTraceElement[]) returns void
toString() returns java.lang.String
Я могу получить одну ошибку в 1000 записей, или я могу получить небольшую порцию ошибок за один раз, и остальные процессы подачи работают нормально (из-за некоторой логики try / catch, предотвращающей выпадение всей вещи) ). В какой-то момент checkCustomerListing
находился в совершенно другом объекте области сервера, и у меня никогда не было проблем. Я переместил его в FeedDAO
и начал вызывать его через область действия Super, и именно тогда начались эти случайные ошибки.
ОБНОВЛЕНИЕ : У меня все правильно поменяно, я просто вырезал все это для краткости.
ОБНОВЛЕНИЕ СНОВА : Изменены комментарии к примеру кода, чтобы было ясно, что много вещей происходит до начала первого цикла, включая установку всех ЛОКАЛЬНЫХ переменных, которые будут использоваться в цикле.
Дополнительная информация о коде :
Я должен отметить, что во всем нашем приложении есть только два места (тысячи и тысячи строк кода), где существует строка 'checkCustomerListing'. Один - где вызывается функция, а второй - где объявлена функция. Других экземпляров строки checkCustomerListing
нет нигде.
Обновление: 6 сентября 2011 г.
Я добавил дополнительную проверку ошибок, чтобы узнать, смогу ли я узнать, что приложение думает checkCustomerListing
(спасибо Адаму и Райану). Вот мой новый оператор try / catch:
<cfcatch type="any">
<cfset local.tmpError.cfcatch = cfcatch>
<cfif isDefined("checkCustomerListing")>
<cfset local.tmpError.customerListing = checkCustomerListing />
<cfset local.tmpError.customerListingMeta = getMetaData(checkCustomerListing) />
<cfelse>
<cfset local.tmpError.customerListing = "Checkcustomerlisting is not defined" />
</cfif>
<cfset Server.Utilities.Errors.emailCaughtError(local.tmpError)>
</cfcatch>
Итак, сегодня утром я получил ошибку, и в полученном письме нет узла customerListing
в дампе, но есть мета-узел:
CUSTOMERLISTINGMETA:
[struct]
ACCESS: public
HINT: Returns the numeric inventory ID for an existing inventory listing, or 0 if the listing doesn't exist.
NAME: checkCustomerListing
OUTPUT: false
PARAMETERS:
[array]
1) [struct]
HINT: [empty string]
NAME: Acct_ID
REQUIRED: true
TYPE: numeric
2) [struct]
HINT: [empty string]
NAME: CustomerListingID
REQUIRED: true
TYPE: string
RETURNTYPE: numeric
Вся эта метаинформация точно правильна ... поэтому, если он может найти метаданные для функции, почему он не может найти саму функцию?