I’ve been battling with a bug with cflocation ever since I upgraded from CF9 to CF10. I’ve worked on it a number of times but always give up but today it’s finally annoyed me enough that it’s time to solve the problem (I hope).
Firstly, apologies as I have tried to write a simple test case to reproduce this problem but so far I’ve been unable to reproduce it outside of original code.
I have a multi-step import process that should run overnight. The process is made up of about 10 files that chain together. When calling the process via a scheduled task a URL parameter (scheduledtask) is also passed. If the parameter does not exist, at the end of each step it stops and waits for the user to click a link to the next step. If the parameter does exist it uses cflocation to move to the next step.
Of all the steps, the 2nd one is the most complex and time consuming (data from multiple web service requests that then need joining, cleaning and inserting into a database). It’s this second step that has a problem after moving to CF10. The page seems to work fine as it’s getting to the very bottom of the page where the cflocation tag is but it never fires cflocation. I’ve added in a cfmail tag to email me as the cflocation is being called, which is always sent, but again cflocation doesn’t fire.
It can’t get much more basic than:
<cfif scheduledtask EQ "true">
<cfmail from="xxxxx” to="xxxx” subject="About to call duplicate" type="text/html">
<p>calling duplicate check - scheduledtask</p>
</cfmail>
<cflocation url="importDupCheck.cfm?scheduledtask=true" addtoken="false">
</cfif>
I know that there is a problem with cfflush and cflocation and I’ve already checked for that.
As a test I tried moving the above logic up the page to just after all the data is retrieved by the webservice but before it’s processed and this time the cflocation worked. I thought maybe it’s a timeout problem where the scheduled task engine has given up waiting even though the page is being allowed to fully load. I tried testing this by having a basic file that had:
<cfset sleep(240000)>
* 4 minutes
before it called cflocation but it worked fine.
The other steps in the process are working as expected with cflocation, just not this one. All this code runs fine under CF9, just failing with CF10.
Does anyone has some pointers on where I should be looking?
Regards
Mark
* Update *
So I’ve now worked out how to easily reproduce this in a few lines of code. Turns out it has nothing to do with scheduled tasks.
index.cfm
<h1>Testing cflocation</h1>
<cfloop index="i" from="1" to="7000" ><!--- For me it stops working once the loop goes beyond 6808 rows --->
row <cfoutput>#i#</cfoutput>: abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789<br/>
</cfloop>
<p>Now loading resultpage via cflocation</p>
<cflocation url="resultpage.cfm" addtoken="false">
resultpage.cfm
<h1>Made it!</h1>
<p>Reload the first page</p>
In my testing I found that if I looped 6808 times it works but 6809 times fails. With 7000 records we are only talking about a 36 KB file….why is this failing only in CF10?
One last thing I should note in case it has an impact- everything I do is done via https.
Ok I worked it out
In CF Administrator
Maximum Output Buffer size 1024
After which a flush will occur which will stop cflocation working.
Increase it and it works.
I have no idea why your code as it stands doesn't work, I'm afraid. At a guess, it's down to ColdFusion 10's replacement of the scheduled task engine, and it not liking some vagary of client-side redirects.
However maybe you can bypass the situation anyhow.
ColdFusion 10's scheduler has a concept of chaining tasks, so that when a task finishes, another one is kicked off. You could conceivably revise your scheduler to leverage that instead?
I had a similar issue, but I was using the location() function in a cfscript. But I suspect the same principle applies.
Prior to the location() function, we were calling a function that was not wrapped in <cfsilent> tags. As a result, every line of the function, including loops, was being output as an empty line of HTML. When I viewed the source code, there were over 20,000 lines of empty HTML code. That is probably enough to reach the 1024 kb buffer limit and trigger the flush that aborts the redirect.
By adding <cfsilent> tags to the custom function, I reduced the number of empty lines of HTML to 39, and now the location() function works as expected.
To determine if this is the issue you are having, add abort; (or <cfabort>) just ahead of the location(), then view the source code of the resulting - presumably empty - page.
Have you tried adding CFABORT after CFLOCATION? That's what I always do - as the code after CFLOCATION should not be executed.
If you check the response from the server (using Charles proxy, Fiddler or something similar) you may find something in the HTML/JS that's preventing the redirection.
Related
I want to set up a simple scheduled task in ColdFusion. I will not have access to the Administrator. So I plan to use<cfschedule. The web is teeming with examples of how to write a cfschedule tag. But I cannot find any explanation of where to put the code.
Do I place it on any .cfm page? Must it go in the index.cfm or Application.cfm? Or what?
I also could not find any explanation of how the scheduling code is initiated. Is it sufficient that the cfschedule code should be somewhere in the application? And if not, what should I do to make sure it runs.
These questions feel stupid to me, but I just can't find answers. Can anyone enlighten me?.cfm
Off the top of my head I didn't know, so I googled cfschedule example and looked at this page.
The first example was to create or update a task. It says, tell ColdFusion to run 'importData.cfm' daily at 7AM
<cfschedule
action="update"
task="importMyCSVFileToDB"
operation="HTTPRequest"
startDate="5/12/2016"
startTime="7:00 AM"
url="http://www.example.com/scheduled/importData.cfm"
interval="daily" />
My interpretation of that is that you put a <cfschedule> tag with a action="update" attribute on a page on the relevant server, and run it once. If it was me, I'd make it page with only the <cfschedule> tag followed by the word, done.
To test this theory, write a page that sends you a simple email. Then schedule that page as I just described and see if you get the email at the scheduled time.
I have an application that contains a form which, until recently, I was able to save as a PDF using cfdocument. A few weeks ago we swapped out a server. The old server was running CF 9.0.1. The new server is CF 10. Since then, I've been getting this error when I try to save this particular form as a PDF.
--
An exception occurred when performing document processing. The cause
of this exception was that:
coldfusion.document.spi.DocumentExportException:
java.lang.IllegalStateException: This function should be called while
holding treeLock.
--
I have another page in the application that saves PDFs just fine. It's just this page that's throwing the error. I can't find anything about TreeLock anywhere on the web (at least, nothing that pertains to ColdFusion).
Has anyone else run into this, and if so, how did you fix it? Thanks!
I started getting the error upon promoting a new version. Rendered the content in HTML. Found I had forgotten to promote an image (got the dreaded X for image). Promoted the image, cfdocument pdf works again. (I'm using localUrl="yes")
In other words, you can debug CF errors that halt the process but cfdocument pdf blithely assumes HTML content you supply is correct and complete.
I had the same problem and by process of elimination found that cfdocument doesn't like textarea elements within the form. It is fine with input type=text, but whenever I tried to add textarea elements it fell over with this error. Hope this helps someone
I am going through the following code:
<cfset x_dt = LSDateFormat(Now(), 'yyyy-mm-dd') &" "&
LSTimeFormat(Now(), 'HH:mm:ss')>
<cfif VerboseDebug gt 0>x_dt = #x_dt#<BR><cfflush></cfif>
I didn't understand the usage of <cfflush> here. Wondering since I haven't defined interval here, how does it works here?
I read the documentation.
Normally when you run a CF script, the server does not return any output to the client until after all of the CF code has executed. CFFlush allows you to return output as it is becomes available, rather than waiting until the end. Useful in cases where you want to display results incrementally, such as for some sort of progress indicator.
I didn't understand the usage of here. Wondering since I
haven't defined interval here, how does it works here?
When you do not specify an interval, CF automatically flushes any new output when you invoke the tag. From the docs:
The first occurrence of this tag on a page sends back the HTML headers
and any other available HTML. Subsequent cfflush tags on the page send
only the output that was generated after the previous flush.
It looks like your code is using that technique for debugging purposes. When that line of code is reached, the server returns that date string to the client if VerboseDebug is enabled.
I was charged with making some modification to an old application, and I created a new page which was being passed a URL parameter page_name, which is a you guessed it a name of a page with .cfm appended. So, in my haste, I continued using it, and was building out my CFC and using the page_name as the identifier for a record. Then I realized that there is a possibility of that name being duplicated in the table, and changed that url parameter to use the page_id, which is unique. I modified my CFC to use the new key, and nothing worked. So I started going through my code and figured I made a typo, started commenting things out, and finally dumped out my CFC object and voila, none of the edits I made were actually being used. This was fairly obvious, since page_name was a string, and page_id was numeric.
So I started googling,The first thing I saw as adjust things in the CFAdmin. I don't have access to it, and restarting the server isn't an option since I'm using an RDS to live code. The next thing I tried was to add applicationStop(), onApplicationStart(), to my Application.cfc. Well the problem is that the Application.cfc, is actually an Application.cfm. So after fiddling with the <cfapplication ... > tag, and nothing being updated, I'm here asking for help.
So is there a quick fix for this? Should I go ahead and create an application.cfc? I hope I explained myself, and sorry for all the text.
Confirm that your cfc is bound to either the session or application scope.
If it is, then you can rename the application in application.cfm and it will reset the object.
If your cfc is NOT bound to session or application scope, you have a cacheing issue. You need to go the the CF admin -> Server Settings -> Cache tab and uncheck component cache and possibly some others.
For further recommendations, ColdFusion Components Inheriting Functions Of Others
Sounds like you have been painted into a corner. Last option IF you have access the the server it self and can get into the C:\ or whatever drive that ColdFusion have been installed on, you can just manually delete the generated Java Class files that the server is using that has the old code. When ColdFusion sees there is no Class file it will recompile the newly changed file and whoa black betty go bam-a-lam your changes will be in production.
For more information here is an posting you can read up on: http://kalyan-coldfusion.blogspot.com/2010/08/how-coldfusion-works-and-its-key.html
Cheers
Would you please give a simple scenario where threading is necessary?
Thank you,
Nich
I used it in a situation where we needed to initiate some back end data processing to tabulate data prior to the user executing some reports. So after login we would fire off a task using cfthread to build the warehouse data for the user. Worked great!
So think of cfthread as a way to execute an asynchronous task on demand. Extremely useful in the right situation!
Use cfthread if it makes sense to execute certain code in parallel with the main request processing code.
Example: say you are uploading a directory of files and you need to do the same processing to each, perhaps to save the contents into the database. You could then use cfthread to run the processing on each file asynchronously. Consider this pseudocode:
<cfdirectory directory="x" action="read" name="allFiles" />
<cfloop query="allFiles">
<cfthread action="run" name="thread-#allFiles.name#>
<!--- Read your file in and do processing --->
</cfthread>
</cfloop>
Remember there is a setting CF Admin to set the number of threads you can spawn in this way! A lot will also depend on your system resources.
There are other examples around which describe other use cases in greater detail. Just do a Google search. I'd recommend Ben Nadal's cfthread primer as a good starting point.
One other warning: threads are a solution to all problems! I was using them to deal with queue processing before and ran into trouble.
In summary cfthread is a great feature of ColdFusion, enjoy it!
I have used cfthread in two situations.
As noted above, I've used it when I wanted to do asynchronous processing while my main thread was doing other things. For example, I used it to load RSS data while generating the rest of the page. Since the call to the RSS source took a couple of seconds, I started a thread before beginning any other processing. It ran while I was querying, drawing the layout, etc. Then I joined the thread and displayed the RSS data. This prevented me from having to pause the page load while the RSS was populating.
The second way I've used this is sort of an on-demand alternative to using the scheduler. We were generating complex PDF documents. The person generating them didn't need them immediately, so rather than have the user stuck while we generated the document, we created an unjoined thread to process the PDF. We then restricted the number of cfthreads being processed at any ppoint. Now, regardless of load, the cfthreads would simply queue, and be processed as resources were available.
<!--- store value into message varaible --->
<cfset variables.message = "It's orginal value.">
<!--- create new thread --->
<cfthread name="ThreadOne">
<!--- overwrite new value into existing variable. --->
<cfset variables.message = "It comes from thread.">
</cfthread>
<!--- join thread --->
<!---
If we leave this join, the code within thread will execute but won't display the value.
--->
<cfthread action="join" name="ThreadOne" />
<!--- Output --->
<cfoutput>#variables.message#</cfoutput>
Check above coding. It's kinda clear.