Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Florida web site design



Czech your Page Rank!
Check Page Rank of any web site pages instantly:
This free page rank checking tool is powered by Page Rank Checker service
Surf's Up!
Visit Egosurf.org and massage YOUR web ego!
My Score: 9,001
Doug's Books

Read (and recommend)

  • Men are from Mars, Women are from Venus
  • The Wisdom of Crowds: Why the Many Are Smarter Than the Few and How Collective Wisdom Shapes Business, Economies, Societies and Nations
  • Blink: The Power of Thinking Without Thinking
  • Head First Design Patterns
  • Transact-SQL Programming
  • What's So Amazing About Grace?
  • Just So Stories (Rudyard Kipling collection)

Reading

  • Prayer: Does it Make Any Difference?
  • Data Mining (Practical Machine Learning Tools and Techniques)
<< September, 2008 >>
SMTWTFS
123456
78910111213
14151617181920
21222324252627
282930
Search Blog

Recent Comments
Categories
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

04 January 2010
Finally Found a Use for CFTHREAD

You know how ColdFusion is so robust that oftentimes there are those tags and functions that exist, yet you've never once had an occasion to use them? Well, today I used a tag for which I've previously not had a need: cfthread. I figured I'd share my use case and implementation in case it piques the curiosity of other CFTHREAD virgins.

The Scenario

Our company has a client who requested that we automate the portion of the process whereby a document originating from them is returned to them by us after we're finished with it. They've built some kind of "folder watching" process on their end, and so asked if we could sFTP the final file to their server. Digging in to the legacy code that performs the final processing, I identified the place where I could surgically place the code to perform this work. But, I didn't want to make the user to encounter any additional delays in page load time.

The Solution
Enter CFTHREAD, a sweet little tag that will allow me to very simply execute a chunk of code asynchronously and unattached from the page it resides within. By simply encompassing the autonomous bit of code within cfthread tags, CF will run it in parallel to the page itself. But, though I did want the upload itself to occur without hindering the execution of the remainder of the page, I DID want to give my user a final message indicating whether or not the upload was successful. In other, more relevant words, i wanted this autonomous process to join back up with the original request at the end, and update a message div on the page appropriately.

Since my standalone process was for sFTP purposes, I'm going to use that snippet of code in my example. Here is the section I needed to run on its own:

<cfset ftpingfile = false />
<!--- if this is a targeted client AND the estimate was approved, FTP it to the target site --->
<cfif thisCarrier IS targCarrier AND (PDFMAccRjt IS "A" OR PDFCAccRjt IS "A")>
 <!--- fetch the ftp settings for client... --->
 <cfquery name="qryGetSettings" datasource="#dsn#">
  select ftpsite,ftpusername,ftppassword,ftpDestFolder
  from clientTable
  where carrier = <cfqueryparam value="#targCarrier#" cfsqltype="cf_sql_varchar" />
 </cfquery>
 <cfif qryGetSettings.recordcount eq 1 AND qryGetSettings.ftpsite IS NOT "">
   <!--- get path to the PDF file --->
   <cfset pathToPDF = "#expandpath("\PDF")#\#InvHolder#.pdf" />
   <cfif fileexists(pathToPDF)>
    <cfset ftpingfile = true /><!--- need this flag for evaluating things at the end of this template --->
    <!--- create new file name... --->
    <cfset newfilename = "#claimnum#-01--#dateformat(now(),"mmddyyyy")##timeformat(now(),"HHmmss")#.pdf" />
    <cfthread action="run" name="FTPit">
     <cfoutput>
      <cfset objFTPProperties = {
       Server = "#qryGetSettings.ftpsite#",
       Username = "#qryGetSettings.ftpusername#",
       Password = "#qryGetSettings.ftppassword#",
       Secure = true
      } />
     </cfoutput>
     <cfftp
      action="open"
      connection="objConnection"
      attributeCollection="#objFTPProperties#"
      />
      <cfftp
      action="putfile"
      connection="objConnection"
      localfile="#pathToPDF#"
      remotefile="#qryGetSettings.ftpDestFolder##newfilename#"
      transfermode="auto"
     />
     <cfftp
      action="close"
      connection="objConnection"
     />
    </cfthread>
   </cfif><!--- if the estimate pdf exists --->
 </cfif><!--- if we found this carrier's ftp info --->
</cfif> 

 

 

 

 

So, while the above code is executing (assuming we met our conditional criteria), the remainder of the page runs. At the end of the template, I use the following code to join the upload request back to the original request:

<!-- div to hold status message for parallel process... -->
<div id="uploading" name="uploading" style="color:red;">
 <cfif ftpingfile> 
  <br><br>Please wait. Uploading file to #targCarrier#... <img src="images/spinner.gif" align="absmiddle" /><br><br>
 <cfelse>
  <br><br>NO PDF UPLOAD ATTEMPTED. EITHER NO PDF WAS FOUND TO UPLOAD, OR THE CLIENT HAS NO FTP SETTINGS IN THE SYSTEM<br><br>
 </cfif>
</div>

<cfflush><!--- output the content of the page thus far to the browser so the user has something to see/do until our process finishes --->

<!--- if we attemptd to ftp a file... --->
<cfif ftpingfile>
 <cfthread action="join" name="FTPit" />
 <cfif cfthread.FTPit.status IS "Completed">
  <script>
   document.getElementById('uploading').innerHTML = "<br><br>Estimate Successfully Uploaded to <cfoutput>#targCarrier#</cfoutput>!<br><br>";
  </script>
 <cfelse>
  <script>
   document.getElementById('uploading').innerHTML = "<br><br><strong>There was a problem uploading the estimate. Here are the details:</strong><br><cfoutput>#JSStringFormat(cfthread.FTPit.error.detail)#</cfoutput><br><br>";
  </script>
  
  <!--- send details of failed attempt to Doug --->
  <cfsavecontent variable="failedFTP">
   <cfdump var="#cfthread#">
  </cfsavecontent>
  <cfmail to="
dboude@adomain.com" from="administrator@adomain.com" type="html" subject="failed FTP attempt for invoice #InvHolder#">
   FTP process failed. Here are the details:
   <br>
   <cfoutput>#failedFTP#</cfoutput>
  </cfmail>
 </cfif>
</cfif>

That's it! So while the user is looking at and potentially interacting with their page as usual, the status message div I placed will be updated appropriately as soon as the upload finishes. Just to clarify, the browser will still show its "loading" status until the threaded ftp process finishes, since we told CF to join it back to the original request. But, because we joined it at the end, and we cfflushed prior to that, the user will see their typical output in the meantime.




Posted by dougboude at 4:15 PM | PRINT THIS POST! |Link | 3 comments
Subscription Options

You are not logged in, so your subscription status for this entry is unknown. You can login or register here.

Re: Finally Found a Use for CFTHREAD
Just wondering, do you need to cfflush before the cfthread join?
Posted by Henry Ho on January 5, 2010 at 1:06 AM

Re: Finally Found a Use for CFTHREAD
@henry - you know Henry, I'm not sure on that. I just assumed I would need to since the request would still be running at that point and as far as I know, CF would have no reason to deliver some of the content before it was all ready. Good question though.
Posted by dougboude on January 5, 2010 at 6:40 AM

Re: Finally Found a Use for CFTHREAD
Thanks for sharing your code. I have never used the cfthread tag and always wondered how I could use it.
Posted by Don Blaire on January 5, 2010 at 5:29 PM

Name:   Required
Email:   Required your email address will not be publicly displayed.

Want to receive notifications when new comments are added? Login/Register for an account.

Time to take the Turing Test!!!

1 plus 5 equals
Type in the answer to the question you see above:

Your comment:

Sorry, no HTML allowed!