I have a page that prints an array with some information to the screen from a session variable (session.stufailedarray). At the top of the page, there a link to export the information to excel. When I try this (in Firefox, IE and Chrome) it works fine. But users keep telling me that they're receiving an error message: "Element stufailarray is undefined is session". I know the variable is there because it just printed it to the screen and I can see it in the debugging. Why would this be happening and only sometimes?
Code that generates error:
<cfset ind=0>
<cfset anArray=arrayNew(2)>
<cfloop array="#session.stufailarray#" index="k">
<cfset ind+=1>
<cfset session.failed=find("UPDATE FAILED: ", "#k#")>
<cfset session.rrr=REFind("\d{9,9}", "#k#")>
<cfset idno=mid("#k#", REFind("\d{9,9}", "#k#"), 9)>
<cfset failed=mid("#k#", Refind("UPDATE FAILED: ", "#k#"), Len(#k#)-(Refind("UPDATE FAILED: ", "#k#")))>
<cfset anArray[ind][1]=#idno#>
<cfset anArray[ind][2]=#failed#>
</cfloop>
<!--- Set content type. --->
<cfcontent type="Application/vnd.ms-excel">
<cfheader name="Content-Disposition" value="filename=load_status.xls">
<cfoutput>
<table cols=2 border=1>
<cfloop from="1" to ="#ArrayLen(anArray)#" index="row">
<tr>
<td>#anArray[row][1]#</td>
<td>#anArray[row][2]#</td>
</tr>
</cfloop>
</table>
</cfoutput>
Try this instead:
<!--- Set content type. --->
<cfset anArray=[]/>
<cfif isDefined(session.stufailedarray)>
<cfset anArray=session.stufailedarray/>
</cfif>
<cfcontent type="Application/vnd.ms-excel">
<cfheader name="Content-Disposition" value="filename=load_status.xls">
<cfoutput>
<table cols=2 border=1>
<cfloop from="1" to ="#ArrayLen(anArray)#" index="row">
<tr>
<td>#anArray[row][1]#</td>
<td>#anArray[row][2]#</td>
</tr>
</cfloop>
</table>
</cfoutput>
Make sure that you configured and enabled application session properly.
To use session variables, enable them in two places:
ColdFusion Administrator The Application.cfc initialization code
This.sessionManagement variable or the active cfapplication tag.
ColdFusion Administrator, Application.cfc, and the cfapplication tag
also provide facilities for configuring session variable behavior,
including the variable time-out.
Configuring and using session variables
According to your question, you have a variable called session.stufailedarray. However in the code that you posted (which generates the error), you have session.stufailarray. This is also the error message that you are getting.
"Element stufailarray is undefined is session"
Note that the set (available) variable, the failed is passed tense, which the error variable is in present tense.
Related
Our code base has quite a bit of the following example as we allow a lot of our base pages to be customized to our customers' individual needs.
<cfif fileExists("/custom/someFile.cfm")>
<cfinclude template="/custom/someFile.cfm" />
<cfelse>
<cfinclude template="someFile.cfm" />
</cfif>
I wanted to create a custom CF tag to boilerplate this as a simple <cf_custominclude template="someFile.cfm" />, however I ran into the fact that custom tags are effectively blackboxes, so they aren't pulling in local variables that exist prior to the start of the tag, and I can't reference any variable that was created as a result of the tag from importing the file.
E.G.
<!--- This is able to use someVar --->
<!--- Pulls in some variable named "steve" --->
<cfinclude template="someFile.cfm" />
<cfdump var="#steve#" /> <!--- This is valid, however... --->
<!--- someVar is undefined for this --->
<!--- Pulls in steve2 --->
<cf_custominclude template="someFile.cfm" />
<cfdump var="#steve2#" /> <!--- This isn't valid as steve2 is undefined. --->
Is there a means around this, or should I utilize some other language feature to accomplish my goal?
Well, I question doing this at all but I know we all get handed code at times we have to deal with and the struggle it is to get people to refactor.
This should do what you are wanting. One important thing to note is that you will need to ensure your custom tag has a closing or it won't work! Just use the simplified closing, so like you had it above:
<cf_custominclude template="someFile.cfm" />
This should do the trick, called it has you had it : custominclude.cfm
<!--- executes at start of tag --->
<cfif thisTag.executionMode eq 'Start'>
<!--- store a list of keys we don't want to copy, prior to including template --->
<cfset thisTag.currentKeys = structKeyList(variables)>
<!--- control var to see if we even should bother copying scopes --->
<cfset thisTag.includedTemplate = false>
<!--- standard include here --->
<cfif fileExists(expandPath(attributes.template))>
<cfinclude template="#attributes.template#">
<!--- set control var / flag to copy scopes at close of tag --->
<cfset thisTag.includedTemplate = true>
</cfif>
</cfif>
<!--- executes at closing of tag --->
<cfif thisTag.executionMode eq 'End'>
<!--- if control var / flag set to copy scopes --->
<cfif thisTag.includedTemplate>
<!--- only copy vars created in the included page --->
<cfloop list="#structKeyList(variables)#" index="var">
<cfif not listFindNoCase(thisTag.currentKeys, var)>
<!--- copy from include into caller scope --->
<cfset caller[var] = variables[var]>
</cfif>
</cfloop>
</cfif>
</cfif>
I tested it and it works fine, should work fine being nested as well. Good luck!
<!--- Pulls in steve2 var from include --->
<cf_custominclude template="someFile.cfm" />
<cfdump var="#steve2#" /> <!--- works! --->
I am downloading data from an API from one of our vendors. The data is an array but some of the fields are empty and come over as undefined. I am able to get most of the information out with a loop but when I add the field "notes" it fails with the error of:
"Element notes is undefined in a CFML structure referenced as part of an expression. The specific sequence of files included or processed is:
C:\websites\Fire\Reports\xml_parse\Crewsense_payroll_loop.cfm, line:
21 "
When I look at the dump I see that the field shows as "undefined". I've run out of ideas. Any help would be greatly appreciated. I've included the entire code and a link to the dump showing the array.
<cfhttp url="https://api.crewsense.com/v1/payroll? access_token=as;lkdfj;alskdfj;laksdfj&token_type=bearer&start=2019-01-05%2019:00:00&end=2019-01-06%2007:59:00" method="GET" resolveurl="YES" result="result">
</cfhttp>
<cfoutput>
<cfset ApiData = deserializeJSON(result.filecontent)>
<cfset API_ArrayLength = arraylen(ApiData)>
<cfloop index="i" from="1" to=#API_ArrayLength#>
#i# #ApiData[i]["name"]#
#ApiData[i]["employee_id"]#
#ApiData[i]["start"]#
#ApiData[i]["end"]#
#ApiData[i]["total_hours"]#
#ApiData[i]["work_type"]#
#ApiData[i]["work_code"]#
#ApiData[i]["user_id"]#
#ApiData[i]["notes"]# <---Fails here when added--->
<cfset i = i+1>
<br>
</cfloop>
<cfdump var="#ApiData#">
</cfoutput>
Dump
When dealing with data structures that have optional elements you will need to check for their existence before trying to access them. Otherwise you will get that error. I have added a snippet with an if condition utilizing the structKeyExists() function to your code as an example.
<cfhttp url="https://api.crewsense.com/v1/payroll? access_token=as;lkdfj;alskdfj;laksdfj&token_type=bearer&start=2019-01-05%2019:00:00&end=2019-01-06%2007:59:00" method="GET" resolveurl="YES" result="result">
</cfhttp>
<cfoutput>
<cfset ApiData = deserializeJSON(result.filecontent)>
<cfset API_ArrayLength = arraylen(ApiData)>
<cfloop index="i" from="1" to=#API_ArrayLength#>
#i# #ApiData[i]["name"]#
#ApiData[i]["employee_id"]#
#ApiData[i]["start"]#
#ApiData[i]["end"]#
#ApiData[i]["total_hours"]#
#ApiData[i]["work_type"]#
#ApiData[i]["work_code"]#
#ApiData[i]["user_id"]#
<cfif structKeyExists(ApiData[i],"notes")>
#ApiData[i]["notes"]# <!--- Show 'notes' if it exists --->
<cfelse>
'notes' is not available <!--- Do something here (or not) --->
</cfif>
<cfset i = i+1>
<br>
</cfloop>
<cfdump var="#ApiData#">
</cfoutput>
I've got the following code in a method:
<cffunction name="serviceTicketValidate" access="public" output="yes" returntype="void" hint="Validate the service ticket">
<cfargument name="service_ticket" type="string" required="yes" hint="The ST to validate" />
<!--- Contact the CAS server to validate the ticket --->
<cfhttp url="#Variables.cas_server#serviceValidate" method="get">
<cfhttpparam name="ticket" value="#Arguments.service_ticket#" type="url" />
<cfhttpparam name="service" value="#Variables.service#" type="url" />
</cfhttp>
<!--- Received a valid XML response --->
<cfif IsXML(cfhttp.FileContent)>
<cfset XMLobj = XmlParse(cfhttp.fileContent)>
<!--- Check for the cas:user tag --->
<cfset CASuser = XmlSearch(XMLobj, "cas:serviceResponse/cas:authenticationSuccess/cas:user")>
<!--- Set the username to the value --->
<cftry>
<cfif variables.username NEQ ''>
<cfdump var="#Variables.username#" /><cfreturn/>
</cfif>
<cfif ArrayLen(CASuser)>
<cfset Variables['username'] = CASuser[1].XmlText />
</cfif>
<cfcatch>
<cfdump var="#cfcatch#" /><cfabort/>
</cfcatch>
</cftry>
<!--- Search for cas:attributes --->
<cfset CASattributes = XmlSearch(XMLobj, "cas:serviceResponse/cas:authenticationSuccess/cas:attributes")>
<!--- Go through all the attributes and add them to the attributes struct --->
<cfif ArrayLen(CASattributes)>
<cfloop array=#CASattributes[1].XmlChildren# index="attribute">
<cfset StructInsert(Variables.attributes,RemoveChars(attribute.XmlName,1,Find(":",attribute.XmlName)),attribute.XmlText)/>
</cfloop>
</cfif>
</cfif>
Note I added the cftry and cfcatch to see what is going on exactly. I've also added the if username != blank to debug as well. This method is called in another method like so:
<cfinvoke method="serviceTicketValidate">
<cfinvokeargument name="service_ticket" value="#service_ticket#" />
</cfinvoke>
<cfdump var="test2" /><cfabort/>
Again I've added the dump and abort for testing. The variable.username is defied and set to an empty string when the component is initiated and the component is initiated into a session variable.
So get this... when the whole process runs the first time I get output on my screen test2 as expected. Then, the next time the same thing is run, the session exists, thus the variable.username is set to something. In the first code block I can dump variables.username and see the username. However if I try to use variables.username in a conditional expression (like in that if statement) or if I remove the if statement and let the script try to change the value of variable.username, there are no errors, it just breaks out of the script completely. It ends that method, and the method that called it and I don't see test2 like I would think. It all just ends for some reason.
If you need further details I can provide more code but I tried to trim out as much as I thought was relevant. All methods are in the same component, all methods are public. Why can't I change the value of variables.username and why is there no error?
EDIT:
I think it may have something to do with the cflock but I'm debugging some stuff right now. I had a redirect inside the code block that is inside the lock. So I guess it never unlocks. But I even waited after the timeout and it still remained locked. I thought the lock was supposed to expire after the timeout.
I'm a little confused but it seems like you're trying to use a cfc's variables scope to set caller variables. The variables scope is not available to the caller the way it seems you are trying to use it.
index.cfm
<cfoutput>
<cfset objTest = createObject("component", "testscope").init()><br><Br>
<cfset objTest.checkValue()><br><br>
Calling page is checking the existence of testvar: #isDefined("variables.testvar")#
</cfoutput>
testscope.cfm
<cfcomponent displayname="testscope">
<cffunction name="init" access="public">
init() just set variables.testvar.
<cfset variables.testvar = "Okay, set">
<cfreturn This>
</cffunction>
<!--- Set some more variables --->
<cffunction name="checkValue" access="public">=
<cfoutput>Checkvalue is checking the value of testvar: #variables.testvar#</cfoutput>
</cffunction>
</cfcomponent>
The output is
init() just set variables.testvar.
Checkvalue is checking the value of testvar: Okay, set
Calling page is checking the existence of testvar: false
My application pulls lots of data from different applications according to the selected scopes. For e.g. Org level and SubOrg level scopes, this can cause to bring server down and everyday causes server crashing and timeouts.
So I wanted to know whether wrapping cfthread around my cfhttp will solve my timeout problem?
<cfinclude template="fundedScopes.cfm">
<!--- Call the funded scopes --->
<cfset dynVarName = "funded" & bizforShort>
<cfif structKeyExists(variables,dynVarName)>
<cfset howManyCustomScopes = listLen(structkeylist(variables[dynVarName],"|" ),"|" )>
<cfmodule template="#Request.Library.CustomTags.VirtualPath#Scheduler_LogDetail.cfm"
Step="Funded Level Cache" Detail="Custom Scopes to be cached: #howManyCustomScopes#"
LogData=""></cfmodule>
<cfloop collection="#variables[dynVarName]#" item="t">
<cfset tempurl = variables[dynVarName][t]["url"]>
<cfset tempurl = tempurl & "&retainCache=1">
<cfoutput>
<cfhttp url="#tempurl#" method="GET" resolveurl="false" timeout="3000">
#tempurl#<br>
<cfset scopesCachedCounter = scopesCachedCounter + 1>
<cfmodule template="#Request.Library.CustomTags.VirtualPath#Scheduler_LogDetail.cfm" Step="Funded Scopes Cache" Detail="#scopesCachedCounter#.- #t#" LogData="#tempurl#"></cfmodule>
</cfoutput>
</cfloop>
</cfif>
I want to find out the details of scheduled tasks running on 5 or 6 coldfusion web-servers, by just writing a single page on one of them. Is there any way to do it?
It might be done by reading cron.xml on all of them.
I came across with following code
<cflock name="alltasks" type="exclusive" timeout="10">
<cfscript>
factory = CreateObject("java","coldfusion.server.ServiceFactory");
cron_service = factory.CronService;
services = cron_service.listALL();
</cfscript>
This code is good for finding out details for web server on which it will be executed.
I am looking for something similar to this, that will get me details of scheduled tasks running on all web-servers in same network. Thanks!!
You could use the cfschedule tag, and place a page on each server that outputs the scheduled tasks for that machine. You could then use an HTTP request to each server to pick up the tasks it's responsible for and output them to the page on your monitoring server.
<!--- ServerList contains all server's(7,8,9) ipaddress,,, --->
<cfset serverList = 'a.b.c.d, p.q.r.s, ....... , u.v.w.x'>
<cfoutput>
Searched In: #serverList#<br>
<Cfloop list="#serverList#" index="s">
<cfif FileExists('\\#s#\C$\ColdFusion8\lib\neo-cron.xml')>
<cfset pathToFindNeo = '\\#s#\C$\ColdFusion8\lib\neo-cron.xml'>
<cfelseif FileExists('\\#s#\C$\CFusionMX7\lib\neo-cron.xml') >
<cfset pathToFindNeo = '\\#s#\C$\CFusionMX7\lib\neo-cron.xml'>
<cfelseif FileExists('\\#s#\C$\ColdFusion9\lib\neo-cron.xml')>
<cfset pathToFindNeo = '\\#s#\C$\ColdFusion9\lib\neo-cron.xml'>
<cfelseif FileExists('\\#s#\ColdFusion\lib\neo-cron.xml')>
<cfset pathToFindNeo = '\\#s#\ColdFusion\lib\neo-cron.xml'>
<cfelse>
<cfset pathToFindNeo = 0>
</cfif>
<h3>#s# [#pathToFindNeo#]</h3>
<!--- Get the scheduler xml file. It's stored as WDDX in CFroot dir--->
<cfif pathToFindNeo neq 0>
<cffile action="Read" file="#pathToFindNeo#" variable="TaskXML">
<!--- Convert the WDDX to CFML - and array of structs --->
<cfwddx action="WDDX2CFML" input="#TaskXML#" output="GetTasks">
<table border="1" width="100%">
<tr>
<td><strong>Name</strong></td>
<Td><strong>URL</strong></Td>
<td><strong>Interval</strong></td>
<Td><strong>Disabled</strong></Td>
<td><strong>Start Date</strong></td>
<td><strong>Start Time</strong></td>
<td><strong>End Time</strong></td>
<td><strong>Operation</strong></td>
</tr>
<cfloop collection="#GetTasks[1]#" item="key">
<cfif GetTasks[1][key]['disabled'] eq 'NO'>
<tr>
<cfelse>
<tr style="background-color:##CCC">
</cfif>
<td>#key#</td>
<td>#GetTasks[1][key]['url']#</td>
<td>#GetTasks[1][key]['interval']#</td>
<td>#GetTasks[1][key]['disabled']#</td>
<td>#GetTasks[1][key]['start_date']#</td>
<td>#GetTasks[1][key]['start_time']#</td>
<td>
<cfif StructKeyExists(GetTasks[1][key], "end_time")>
#GetTasks[1][key]['end_time']#
<cfelse>
-
</Cfif>
</td>
<td>#GetTasks[1][key]['operation']#</td>
</tr>
</cfloop>
</TABLE>
<CFELSE>
FILE 'neo-cron.xml' NOT FOUND
</cfif>
</Cfloop>
</cfoutput>
What I would probably do is create a cfc on the destination server, that would return the results from the lookup of scheduled tasks into some kind of json, xml, or query that would be available with a set username & password to get the data from 1 server to another, as needed....
The way we take care of this is to add a line to a database table with the URL of the task. If you have all your tasks in the one directory the best way to do this is add the database logging in Application.cfc using the available CGI variables.
This can then be checked against what you expected to run.
Hope that helps!