NO MORE CAREER
POLITICIANS!
Get Out Of Our House: Replacing congress with TRUE citizens!
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...
Web Hosting

best web hosting - top web hosting sites, thetop10bestwebhosting.com

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)
<< January, 2010 >>
SMTWTFS
12
3456789
10111213141516
17181920212223
24252627282930
31
Search Blog

Recent Comments
Re: Using Google as your CF Mail Server (by Mike at 9/07 4:02 PM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Nithin Chacko Ninan at 9/07 1:34 AM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Nithin Chacko Ninan at 9/07 1:33 AM)
Re: Configuring Apache To Use Multiple Versions of ColdFusion (by Lola LB at 9/06 6:28 AM)
Re: Configuring Apache To Use Multiple Versions of ColdFusion (by ComboFusion at 9/06 5:17 AM)
Re: Railo 3.1 on Windows Server 2008 and IIS7 - Part 3 of 3 (by Jon at 8/27 2:04 PM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Spacy at 8/24 3:46 PM)
Re: THE DAY CFUNITED DIED (by ComboFusion at 8/23 10:50 AM)
Re: My Grandpa (by Tasha at 8/10 4:29 PM)
Re: Just What IS a 'Service Layer', Anyway? (by dougboude at 8/02 10:10 AM)
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