Copy link to clipboard
Copied
I'm working on an old piece of code that watches a directory = checks the files in it and then renames the file to one other parts of the system recognise based on the contents of the file
Now having rationlised this code significantly making use of CFC's I'm having problems in the way in which the code rename's the file -It should rename it based on a string it may find in the doc otherwise it leaves it alone - However at the moment it randomly assigns it a value that is not in the file although I think its holding on to details from another file but I don't know how - I'm running Coldusion 9 and the production server is running CF8- I don't seen to have the problem on my machine but do on the production box
Any help would be deeply appreciated
Thanks
Copy link to clipboard
Copied
This is a bit of a strange question!
As far as I know and have ever read or heard, cfoutput would have no role what so ever in instantiating or destroying an object.
The roles <cfoutput...> support is to:
1) declare a block of code where variables will be rendered to the output buffer.
2) loop over a record set object and render variables to the output buffer.
Other then the inharent Java undlining all this functionality must be creating and destroying objects somewhere somehow. I do not see how <cfoutput...> would have any role in objects your are creating.
I suspect it is your logic that is creating objects with race conditions and data clashes during the looping from of a <cfoutput....> block.
But since you provide no code, only a vague description of the process, and no actual errors to work with I can only speculate.
Copy link to clipboard
Copied
OK thanks - that helps a bit - I'm not yet a confident ColdFusion programmer - I've only been using it for the last month - My background is Java - as <cfoutput> is looping over the <cfdirectory> query - I amtrying to understand how everything is scoped within the loop
This is the actual code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Pragma" content="no-cache">
<title>Parse PDFs</title>
<!------>
<meta http-equiv="refresh" content="120" >
<cfset dumpPDFDir = configFile.getAttributeFromConfigFile("dumpPDFDir")>
<cfset deliverDir = configFile.getAttributeFromConfigFile("deliverDir")>
<font size="-2">
<a href="au_parse_pdfs.cfm" target="_blank">Parse PDFs</a> - <b>Last Run <cfoutput>#dateformat(now(),"ddd-dd")#-#timeformat(now(),"HH:mm")#</cfoutput></b><br>
<cfdirectory action="list" directory="#dumpPDFDir#" name="TheList" filter="*.pdf" sort="dateLastModified" recurse="no">
<cfobject component="global.deliverySystem.PDFUtils" name="PDFUtils">
<cfoutput query="TheList">
<cfset includeFile="True"/>
<cfif find("INVOICE", ucase(TheList.name[TheList.currentRow]), 0) neq 0>
<cfset includeFile="False"/>
</cfif>
<cfif find("HCP", ucase(TheList.name[TheList.currentRow]),0) neq 0>
<cfset includeFile="True"/>
</cfif>
<cfif TheList.Type[TheList.currentRow] eq "File"
<!--- exclude if --->
AND find("RECEIPT", ucase(TheList.name[TheList.currentRow]), 0) eq 0
AND #includeFile#
AND find("DISPATCH MANIFEST", ucase(TheList.name[TheList.currentRow]), 0) eq 0
<cfset TheFile = PDFUtils.getPDFAsXml(dumpPDFDir="#dumpPDFDir#",fileName="#TheList.name[TheList.currentRow]#")/>
<cfset isValidFile = PDFUtils.isValidFile(file="#TheFile#")/>
<!---cfdump var="#TheFile#"/--->
<cfif isValidFile>
<cfset fileName =""/>
<cfset EnviroType = "">
<cfif find("~", TheFile)>
<cfset TheFirst = find("~",TheFile)>
<cfset TheSecond = find("~", TheFile, TheFirst+1)>
<cfset TheThird = find("~", TheFile, TheSecond+1)>
<cfif TheThird gt TheSecond and TheSecond gt TheFirst and TheThird - TheFirst lt 40>
<cfset FirstString = mid(TheFile,TheFirst+1,TheSecond-TheFirst-1)>
<cfset SecondString = mid(TheFile,TheSecond+1,TheThird-TheSecond-1)>
<font color="000000" size="-2">name=#name# #TheFirst# / #TheSecond# / #TheThird# ***** #TheSecond - TheFirst# / #TheThird - TheSecond# ***** FirstString=*#FirstString#* / SecondString=*#SecondString#* / mmm#left(name,len(name)-4)#mmm<br/></font>
<cfif isnumeric(FirstString) and isnumeric(SecondString) and len(FirstString) gt 3 and (len(SecondString) gt 0 and len(SecondString) lt 30)>
<cfif SecondString eq "8">
<cfset EnviroType = PDFUtils.determineEnviroTypeFromProductType(TheFile="#TheFile#",
startPoint="#TheFirst#")/>
<cfelse>
<cfset EnviroType = "$AUT$$">
</cfif>
</cfif>
<cfset fileName = "#dumpPDFDir#\#trim(FirstString)# #trim(SecondString)##EnviroType#.pdf"/>
</cfif>
</cfif>
<cfdump var="#fileName#"/>
<cfif fileName NEQ "">
<cffile action="rename" source="#dumpPDFDir#\#left(name,len(name)-4)#.pdf" destination="#fileName#">
<cfif directoryExists(deliverDir)>
<cffile action="copy" source="#fileName#" destination="#deliverDir#/monitoringDir"/>
<!---cffile action="move" source="#fileName#" destination="#deliverDir#"--->
<cfelse>
<font color="FF0000" size="-2">Unable to access directory=#deliverDir#<br/></font>
</cfif>
<cfelse>
<font color="FF0000" size="-2">name=#name# - not matched<br/></font>
</cfif>
<cfelse>
<font color="FF0000" size="-2">name=#name# - not found<br/></font>
</cfif>
<cfelse>
<font color="FF0000" size="-2">name=#name# - excluded<br/></font>
</cfif>
<cfset StructClear(TheFile)/>
<cfset fileName = ""/>
<cfset FirstString = ""/>
<cfset SecondString = ""/>
<cfset EnviroType = "">
<cfset TheFirst = "">
<cfset TheSecond = "">
<cfset TheThird = "">
</cfoutput>
<cfset TheList = ""/>
</body>
</html>
With the function calls to the CFC's being:
<cffunction name="getPDFAsXml" access="public" returnType="String" >
<cfargument name="dumpPDFDir" type="String" required="true">
<cfargument name="fileName" type="String" required="true" >
<cfinvoke component="global.common.config.config"
method="getAttributeFromConfigFile"
configAttribute="ddxDir"
returnvariable="ddxDir"/>
<cfinvoke component="global.common.config.config"
method="getAttributeFromConfigFile"
configAttribute="xmlDir"
returnvariable="xmlDir"/>
<cfset inputStruct=StructNew()>
<cfset inputStruct.doc1="#dumpPDFDir#/#fileName#">
<cfset outputType="xml"/>
<cfset outputStruct=StructNew()>
<cfset outputStruct.Out1= xmlDir & "/" & Replace("readPDF.ddx",".ddx","")&"."&outputType/>
<cfpdf action="processddx" ddxfile="#ddxDir#/readPDF.ddx" inputfiles="#inputStruct#" outputfiles="#outputStruct#" name="ddxVar">
<!---cfdump var="#ddxVar#"--->
<cffile variable="xmlOutput"
file="#outputStruct.Out1#"
action="read" charset="utf-8" />
<cfset parsedFile = XmlParse(xmlOutput)/>
<cfreturn parsedFile>
</cffunction>
<cffunction name="determineEnviroTypeFromProductType" access="public" returnType="String">
<cfargument name="TheFile" type="Any" required="true"/>
<cfargument name="startPoint" type="Any" required="true"/>
<cfset EnviroType = "$AUT$">
<cfif find("Referred to RPS", left(TheFile, startPoint)) OR find("Certificate", left(TheFile, startPoint)) OR find("RPS Review", left(TheFile, startPoint))>
<cfif find("Referred to RPS", left(TheFile, startPoint))>
<cfset EnviroType = EnviroType & "Referred to RPS$">
</cfif>
<cfif find("Certificate", left(TheFile, startPoint))>
<cfset EnviroType = EnviroType & "Certificate$">
</cfif>
<cfif find("RPS Review", left(TheFile, startPoint))>
<cfset EnviroType = EnviroType & "RPS Review$">
</cfif>
<cfelse>
<cfset EnviroType = EnviroType & "$">
</cfif>
<cfreturn EnviroType/>
</cffunction>
As I said before - this works absolutely fine on my CF9 server but not on the CF8 production server
Copy link to clipboard
Copied
The first thing I would address is the need to VAR scope variables intended to be local to a CFC component function. With you describing the differences between CF9 and CF8 I suspect this might be very important.
In CF8, naked, unscoped variables delcared inside a <cffunction....> block are put into the PUBLIC "This" scope of the component and thus are very exposed to race conditions and data clashes.
To declare a variable to be PRIVATE to the function, one needs to use the VAR keyword in the variable declaration.
I.E.
<cffunction....>
<cfargument..>
<cfargument...>
<cfset VAR aLocalVarOne...>
<cfset VAR aLocalVarTwo...>
....
</cffunction>
It is my understanding that in CF9 variables in component functions default to being local, private variables, but I have not had the opportunity to play with CF9 yet, so I do not have experience on how this actually differs in coding pratices.
P.S. It is important to that these VAR declarations occur immediately following the <cfargument...> declarations. Otherwise a Error will be thrown.
Copy link to clipboard
Copied
I have lately gotten into the habit of starting with <cfset LOCAL = StructNew()> and thereafter referring to "LOCAL.foobar" in my code.
It's just an ordinary struct-reference, of course, where the name of the struct just happens to be the word, "LOCAL." But it makes things much clearer, and does not slow down anything.
Copy link to clipboard
Copied
I hope your habit ,TLC, is to use <cfset var local = structNew()>.
Otherwise you have just created a structure in the public this scope that is no safer then any other variable created in the this scope.
I suspect that is what you meant, but mistyped, as that is a very common pogramming pratice amoung ColdFusion coders.