<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5824660313967021040</id><updated>2012-01-31T23:38:14.199-08:00</updated><category term='CFEclipse'/><category term='MySQL'/><category term='POI'/><category term='ColdFusion 9'/><category term='Web Services'/><category term='Misc'/><category term='SVG'/><category term='MS SQL'/><category term='Java'/><category term='JODConverter'/><category term='ZXing'/><category term='C#'/><category term='JQuery'/><category term='Tomcat'/><category term='CF9 Beta'/><category term='Firefox'/><category term='CFChart'/><category term='Barbecue'/><category term='Railo'/><category term='Eclipse'/><category term='Humor'/><category term='Rant'/><category term='iText'/><category term='Apache'/><category term='Databases'/><category term='Batik'/><category term='ColdFusion'/><category term='Getting Started'/><category term='.NET'/><title type='text'>cfSearching</title><subtitle type='html'>.. in the middle of the night</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default?start-index=101&amp;max-results=100'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>250</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3907938166218012050</id><published>2011-01-24T15:15:00.000-08:00</published><updated>2011-01-24T15:15:50.292-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Small Bug with SpreadSheetCreateSheet</title><content type='html'>I was running some comparisons with CF9's spreadsheet functions and noticed a small bug with &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SpreadSheetCreateSheet()&lt;/span&gt;. When you omit the sheet name argument, CF automatically generates the sheet's name for you, using the standard naming convention &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sheet1&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sheet2&lt;/span&gt;, etcetera). But apparently CF, or more accurately POI, does not verify the new name is not already in use. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; If you run the code below, it creates two sheets &lt;i&gt;both &lt;/i&gt;named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Sheet1&lt;/span&gt;.&amp;nbsp; Obviously if you saved the file to disk and tried to open it, Excel would complain about the duplicate sheet names. It is possible it may also cause problems with other spreadsheet functions that rely on sheet name, rather than index. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset sheet = SpreadSheetNew() /&amp;gt;&lt;br /&gt;&amp;lt;cfset SpreadSheetCreateSheet(sheet) /&amp;gt;&lt;br /&gt;&amp;lt;cfset info = SpreadSheetInfo(sheet)/&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#info#" label="Duplicate sheet names" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now I suspect most people prefer to provide their own (more descriptive) sheet names, in which case the issue does not apply. But in case you do choose to use this feature, just be aware of this "gotcha". &lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3907938166218012050?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3907938166218012050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3907938166218012050&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3907938166218012050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3907938166218012050'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2011/01/small-bug-with-spreadsheetcreatesheet.html' title='Small Bug with SpreadSheetCreateSheet'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-5161890328766646177</id><published>2011-01-09T21:04:00.000-08:00</published><updated>2011-01-09T21:04:06.604-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Converting Relative to Absolute URL's</title><content type='html'>The very first time I used the ExpandPath() function I remember wondering why there was not a similar function for expanding url's. At some point later, I did sit down and write a very rudimentary ExpandURL function. I have long since forgotten the code. But I do have a vague recollection of an ugly series of strings functions. Well the other day I came across &lt;a href="http://stackoverflow.com/questions/1389184/building-an-absolute-url-from-a-relative-url-in-java-servlet/1389468#1389468"&gt;a tip on stackoverflow.com&lt;/a&gt; that would have made it much easier: &lt;a href="http://download.oracle.com/javase/6/docs/api/java/net/URL.html"&gt;java.net.URL&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;You simply pass in an object representing the base url (ie &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;http://www.mysite.com/blog/archive/&lt;/span&gt;) and a string representing the relative path (ie &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"../../somePage.cfm"&lt;/span&gt;). The java.net.URL class normalizes the paths and returns an absolute url. In this example it would be: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;http://www.mysite.com/somePage.cfm&lt;/span&gt;. With a little effort it could be used to create a custom ExpandURL() function. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;   ... or using the base url of current request &lt;br /&gt;   &amp;lt;cfset theBaseURL = getPageContext().getRequest().getRequestURL()&amp;gt;&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset theBaseURL = "http://www.mysite.com/blog/archive/" /&amp;gt;&lt;br /&gt;&amp;lt;cfset theRelativeURL = "../../somePage.cfm" /&amp;gt;&lt;br /&gt;&amp;lt;cfset baseURL = createObject("java", "java.net.URL").init( theBaseURL ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset absURL = createObject("java", "java.net.URL").init( baseURL, theRelativeURL ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;   &amp;lt;p&amp;gt;theBaseURL = #theBaseURL#&amp;lt;/p&amp;gt;&lt;br /&gt;   &amp;lt;p&amp;gt;theRelativeURL = #theRelativeURL#&amp;lt;/p&amp;gt;&lt;br /&gt;   &amp;lt;p&amp;gt;absURL = #absURL.toString()#&amp;lt;/p&amp;gt; &lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now obviously I am glossing over a &lt;i&gt;lot&lt;/i&gt;.&amp;nbsp; There are definitely nuances to be aware of, but you can find a complete description of how the paths are resolved in the &lt;a href="http://download.oracle.com/javase/6/docs/api/java/net/URL.html"&gt;java api&lt;/a&gt; (and referenced specifications for url's and uri's). This method is not perfect, but overall it is a lot more robust and elegant than using string functions.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-5161890328766646177?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/5161890328766646177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=5161890328766646177&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/5161890328766646177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/5161890328766646177'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2011/01/converting-relative-to-absolute-urls.html' title='Converting Relative to Absolute URL&apos;s'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3962960334931632193</id><published>2011-01-08T21:36:00.000-08:00</published><updated>2011-01-08T21:45:05.682-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CF9.0.1 - Small Quirk: New XLS Spreadsheets are missing CreationDate property</title><content type='html'>Testing the new &lt;a href="http://www.andyjarrett.co.uk/blog/index.cfm/2011/1/2/cfspreadsheet-for-Railo"&gt;cfspreadsheet extension for Railo&lt;/a&gt; reminded me of an ACF spreadsheet quirk I saw in one of the forums a few weeks back. For some reason, the creation date property is not populated for new binary spreadsheets (ie *.xls). Nor is that property accessible via the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SpreadsheetAddInfo &lt;/span&gt;function. Granted it is just a metadata value. So it is hardly a major issue. But the omission does seem a bit odd. Especially since ACF does set the creation date for new .xlsx files. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4MgprHLfxvM/TSlKYiFEDpI/AAAAAAAAAns/48ExFetYSh4/s1600/MissingCreateDate.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="137" width="320" src="http://2.bp.blogspot.com/_4MgprHLfxvM/TSlKYiFEDpI/AAAAAAAAAns/48ExFetYSh4/s320/MissingCreateDate.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;It is easy enough to that property on an &lt;i&gt;existing &lt;/i&gt;spreadsheets. Just read in the file. Grab the SummaryInformation and set the property by invoking &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setCreateDateTime()&lt;/span&gt;. SummaryInformation is basically the same core document properties returned by the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;SpreadsheetInfo &lt;/span&gt;function.   Unfortunately, CF does not add SummaryInformation for &lt;i&gt;new &lt;/i&gt;spreadsheets until they are saved to disk. So if you tried the code below on a new spreadsheet object it would fail. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset sampleFile = ExpandPath("newSpreadsheet.xls") /&amp;gt;&lt;br /&gt;&amp;lt;cfset sheet = SpreadsheetRead( sampleFile ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset wb = sheet.getWorkBook() /&amp;gt;&lt;br /&gt;&amp;lt;cfset wb.getSummaryInformation().setCreateDateTime( now() ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset spreadsheetWrite( sheet, sampleFile, true ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As it turns out there is an easy way to add the creation date property under CF9.0.1, albeit undocumented. CF9.0.1 includes a slightly newer version of POI (3.6-beta1). The newer version includes a new convenience method called &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;createInformationProperties()&lt;/span&gt;. When used on a new workbook it creates and initializes the missing summary properties. Even before the new file is written to disk. Once the properties are intialized, you can easily set the creation date.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset sheet = SpreadsheetNew()&amp;gt;&lt;br /&gt;&amp;lt;cfset spreadsheetSetCellValue( sheet, "foo", 1, 1 )&amp;gt;&lt;br /&gt;&amp;lt;!--- get underlying workbook object ---&amp;gt;&lt;br /&gt;&amp;lt;cfset wb = sheet.getWorkBook()&amp;gt;&lt;br /&gt;&amp;lt;!--- initialize the summary information and set the creation date ---&amp;gt;&lt;br /&gt;&amp;lt;cfset wb.createInformationProperties()&amp;gt;&lt;br /&gt;&amp;lt;cfset wb.getSummaryInformation().setCreateDateTime( now() ) /&amp;gt;&lt;br /&gt;&amp;lt;!--- save the spreadsheet to disk ---&amp;gt;&lt;br /&gt;&amp;lt;cfset spreadsheetWrite( sheet, ExpandPath("newSpreadsheet.xls"), true )&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3962960334931632193?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3962960334931632193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3962960334931632193&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3962960334931632193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3962960334931632193'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2011/01/cf901-small-quirk-new-xls-spreadsheets.html' title='CF9.0.1 - Small Quirk: New XLS Spreadsheets are missing CreationDate property'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4MgprHLfxvM/TSlKYiFEDpI/AAAAAAAAAns/48ExFetYSh4/s72-c/MissingCreateDate.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3090418798355691196</id><published>2011-01-08T20:25:00.000-08:00</published><updated>2011-01-08T21:37:48.539-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Railo'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Running ACF Database Examples on Railo</title><content type='html'>I was excited to read there is an alpha &lt;a href="http://www.andyjarrett.co.uk/blog/index.cfm/2011/1/4/cfspreadsheet-for-Railo-update"&gt;cfspreadsheet extension available for Railo&lt;/a&gt; (Written by &lt;a href="http://www.andyjarrett.co.uk/"&gt;Andy Jarrett&lt;/a&gt; as a fork of the CFPOI project by &lt;a href="http://www.mattwoodward.com/"&gt;Matt Woodward&lt;/a&gt;.)&amp;nbsp; As a user of both ACF and Railo I was curious how the two versions of the tag compared.&amp;nbsp; Being lazy, I decided to use the &lt;a href="http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec17cba-7f87.html"&gt;cfspreadsheet examples&lt;/a&gt; from the ACF documentation for some basic tests. While they are convenient, they naturally make use of sample databases included only with ACF.&amp;nbsp; But it occurred to me, why not just copy the sample databases into Railo and set up a datasource? Then I could easily use the examples with both engines. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;  So first I located the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;cfcodexamples&lt;/span&gt; database and copied the entire directory beneath my Railo root. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;My Local Settings:&lt;/i&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;ACF&lt;/b&gt;:&amp;nbsp;&amp;nbsp; c:/dev/ColdFusion9/db/cfcodexamples/&lt;br /&gt;&lt;b&gt;Railo&lt;/b&gt;: c:/dev/railo321/db/cfcodeexamples/&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;Next I created the datasource. A quick search turned up these handy instructions for configuring an &lt;a href="http://www.blogger.com/"&gt;Apache Derby datasource on Railo&lt;/a&gt;, posted by &lt;a href="http://web-rat.com/blog/"&gt;Todd Rafferty&lt;/a&gt;.   &lt;br /&gt;&lt;br /&gt;1) First copy the derby.jar into {railo_server}\lib and restart Railo &lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;My Local Settings:&lt;/i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;c:/dev/railo321/lib/derby.jar&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;2) Create a new "Other" datasource in Railo. (As this was just for testing, I accepted all the default settings)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TSksmDSXc4I/AAAAAAAAAno/f9QSwazFeA0/s1600/railo_derby_dsn.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="197" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TSksmDSXc4I/AAAAAAAAAno/f9QSwazFeA0/s320/railo_derby_dsn.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;My Local Settings:&lt;/i&gt;&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Name&lt;/b&gt;:&amp;nbsp; cfdocexamples&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Class&lt;/b&gt;:      org.apache.derby.jdbc.EmbeddedDriver    &lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Dsn&lt;/b&gt;:&amp;nbsp;&amp;nbsp; jdbc:derby:&lt;span style="color: #0b5394;"&gt;db/cfdocexamples&lt;/span&gt;;create=true&lt;/div&gt;&lt;br /&gt;Note:&amp;nbsp;&amp;nbsp; The database path in the dsn is relative to the application root. I.e.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Root&lt;/b&gt;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c:/dev/railo321/&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &lt;b&gt;Database&lt;/b&gt;:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c:/dev/railo321/db/cfcodexamples&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;  &lt;b&gt;Relative Path&lt;/b&gt;: &lt;span style="color: #0b5394;"&gt;db/cfdocexamples&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Once I verified the datasource.&amp;nbsp; I was able to run the same cfspreadsheet examples under my Railo install too. Now obviously there &lt;i&gt;are&lt;/i&gt; differences between the two engines. So it would be silly to expect every tag example to work exactly the same. But I thought this was an easy way to run some quick comparisons between the two cfspreadsheet tags. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3090418798355691196?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3090418798355691196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3090418798355691196&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3090418798355691196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3090418798355691196'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2011/01/running-acf-database-examples-on-railo.html' title='Running ACF Database Examples on Railo'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/TSksmDSXc4I/AAAAAAAAAno/f9QSwazFeA0/s72-c/railo_derby_dsn.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7359705619157242664</id><published>2010-10-07T22:18:00.000-07:00</published><updated>2010-10-07T22:38:26.896-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 9.0.1:  Expand / Collapse All Groups in a CFGrid</title><content type='html'>Being late to the game, I just read about CF9's grouping feature with CFGrids. While it is a useful feature, I immediately noticed there was no option to expand or collapse all groups. After perusing the Ext forums, I discovered methods for expanding or &lt;a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.grid.GroupingView&amp;member=collapseAllGroups"&gt;collapsing all groups&lt;/a&gt; in the underlying GridView class. With the help of ajaxOnLoad(), I was able to create a grouped CFGrid, but this time with all groups collapsed by default.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;    function collapseGrid() {&lt;br /&gt;        var grid = ColdFusion.Grid.getGridObject('MyGrid');&lt;br /&gt;        grid.getView().collapseAllGroups();&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;... create the grouped cfgrid ...&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset ajaxOnLoad("collapseGrid")&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Giddy with my small success, I decided to try creating a button that would Expand/Collapse all groups. Fortunately &lt;a href="http://www.danvega.org/blog/index.cfm/2010/7/29/Creating-a-grid-toolbar-in-ColdFusion-901"&gt;a great entry on Dan Vega's blog&lt;/a&gt; saved me from hurting myself with my rudimentary Ext skills. In no time at all, I had a new toolbar with a button. &lt;br /&gt;&lt;br /&gt;Now since I wanted to pass the grid id into the handler function, I used createCallback() to bind the grid id as a function argument. Voila! A fully functional (albeit plain) toolbar button that toggles the expansion state of all groups. &lt;br /&gt;&lt;br /&gt;If you are interested in styling the button, check out &lt;a href="http://www.danvega.org/blog/index.cfm/2008/3/5/ColdFusion-8-Grid-Custom-Toolbars"&gt;ColdFusion 8 Grid Custom Toolbars&lt;/a&gt; for an example.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Full Code&lt;/b&gt; (Requires CF 9.0.1)&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;!--- sample data for grid ---&amp;gt;&lt;br /&gt;&amp;lt;cfset qGridData = queryNew("ID,Title,Area", "integer,varchar,varchar") /&amp;gt;&lt;br /&gt;&amp;lt;cfloop from="1" to="50" index="r"&amp;gt;&lt;br /&gt;    &amp;lt;cfset row = queryAddRow(qGridData, 1)&amp;gt;&lt;br /&gt;    &amp;lt;cfset qGridData.ID[row] = r&amp;gt;&lt;br /&gt;    &amp;lt;cfset qGridData.Title[row] = "Title "&amp; numberFormat(r, "000")&amp;gt;&lt;br /&gt;    &amp;lt;cfset qGridData.Area[row] = ceiling(r /10)&amp;gt;&lt;br /&gt;&amp;lt;/cfloop&amp;gt;    &lt;br /&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;    function init(){&lt;br /&gt;        // create a toolbar&lt;br /&gt;        var tbar = ColdFusion.Grid.getTopToolbar('MyGrid');&lt;br /&gt;        tbar.addButton({xtype: 'tbfill'});&lt;br /&gt;        // add a button that expands/collapses all groups&lt;br /&gt;        tbar.addButton({ text: "Expand/Collapse All", &lt;br /&gt;                tooltip: "Toggles the expansion state of all groups", &lt;br /&gt;                handler: toggleGridGroups.createCallback('MyGrid')&lt;br /&gt;            });&lt;br /&gt;        //show the toolbar &lt;br /&gt;        ColdFusion.Grid.showTopToolbar('MyGrid');&lt;br /&gt;&lt;br /&gt;        //collapse all groups by default &lt;br /&gt;        var grid = ColdFusion.Grid.getGridObject('MyGrid');&lt;br /&gt;        grid.getView().collapseAllGroups();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    function toggleGridGroups(gridId){&lt;br /&gt;        var grid = ColdFusion.Grid.getGridObject(gridId);&lt;br /&gt;        grid.getView().toggleAllGroups();&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;cfform format="html"&amp;gt;&lt;br /&gt;        &amp;lt;cfgrid name="MyGrid" format="html" query="qGridData" groupField="Area" width="500"&amp;gt;&lt;br /&gt;            &amp;lt;cfgridcolumn name="Title" header="Title" /&amp;gt;&lt;br /&gt;            &amp;lt;cfgridcolumn name="Area" header="Title Area" /&amp;gt;&lt;br /&gt;        &amp;lt;/cfgrid&amp;gt;&lt;br /&gt;    &amp;lt;/cfform&amp;gt;&lt;br /&gt;    &amp;lt;cfset ajaxOnLoad("init")&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7359705619157242664?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7359705619157242664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7359705619157242664&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7359705619157242664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7359705619157242664'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/10/coldfusion-901-expand-collapse-all.html' title='ColdFusion 9.0.1:  Expand / Collapse All Groups in a CFGrid'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2952427706511969763</id><published>2010-09-19T01:26:00.000-07:00</published><updated>2010-09-22T19:21:32.156-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CFHTTP + FILE + POST (Bug Byte ?)</title><content type='html'>A few years ago, I saw a post on the adobe forums about &lt;a href="http://forums.adobe.com/message/860303"&gt;a strange problem with cfhttp&lt;/a&gt;. Posting a simple .zip file with &amp;lt;cfhttp&amp;gt; somehow ended up corrupting the file. So the resulting archive file could not be read by some tools, in particular  &amp;lt;cfzip&amp;gt;. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; &lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;   With CF8 this code fails with the error:&lt;br /&gt;   Unsupported File Format&lt;br /&gt;   Ensure that the file is a valid zip file and it is accessible.&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfif structKeyExists(FORM, "myFile")&amp;gt;&lt;br /&gt;    &amp;lt;cffile action="upload" destination="#ExpandPath('.')#" nameconflict="overwrite" /&amp;gt;&lt;br /&gt;    &amp;lt;cfzip action="list" file="#cffile.serverDirectory#/#cffile.serverFile#" name="result" /&amp;gt;&lt;br /&gt;    &amp;lt;cfdump var="#result#" label="Zip File Contents" /&amp;gt;&lt;br /&gt;&amp;lt;cfelse&amp;gt;&lt;br /&gt;    &amp;lt;cfhttp url="http://127.0.0.1/cfhttpTest.cfm" method="post"&amp;gt;&lt;br /&gt;        &amp;lt;cfhttpparam name="myFile" type="file" file="c:/test/testFile.zip" mimetype="application/zip" /&amp;gt;&lt;br /&gt;    &amp;lt;/cfhttp&amp;gt;&lt;br /&gt;    &amp;lt;cfoutput&amp;gt;#cfhttp.fileContent#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/cfif&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;The Byte&lt;/b&gt;&lt;br /&gt;So I decided to have a look and noticed something strange about the received file. It always seemed to be two (2) bytes bigger than the original. After a bit more experimentation, I discovered the problem disappears if you add a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;formfield&lt;/span&gt; (any &lt;span style="font-family: inherit;"&gt;formfield&lt;/span&gt;) directly &lt;i&gt;after&lt;/i&gt; the file.&amp;nbsp; Placing it before the file does &lt;u&gt;not&lt;/u&gt; work.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;   This DOES work&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfif structKeyExists(FORM, "myFile")&amp;gt;&lt;br /&gt;    &amp;lt;cffile action="upload" destination="#ExpandPath('.')#" nameconflict="overwrite" /&amp;gt;&lt;br /&gt;    &amp;lt;cfzip action="list" file="#cffile.serverDirectory#/#cffile.serverFile#" name="result" /&amp;gt;&lt;br /&gt;    &amp;lt;cfdump var="#result#" label="Zip File Contents" /&amp;gt;&lt;br /&gt;&amp;lt;cfelse&amp;gt;&lt;br /&gt;    &amp;lt;cfhttp url="http://127.0.0.1/cfhttpTest.cfm" method="post"&amp;gt;&lt;br /&gt;        &amp;lt;cfhttpparam name="myFile" type="file" file="c:/test/testFile.zip" mimetype="application/zip" /&amp;gt;&lt;br /&gt;        &amp;lt;cfhttpparam name="BecauseTheFileIsCorruptedWithoutThisField" type="formfield" value="" /&amp;gt;&lt;br /&gt;    &amp;lt;/cfhttp&amp;gt;&lt;br /&gt;    &amp;lt;cfoutput&amp;gt;#cfhttp.fileContent#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/cfif&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now I just assumed it was an issue with cfhttp. As there was a work-around, I did not really explore it further. But a recent question on stackoverflow.com prompted me to revisit the issue and take a closer look. A poster named &lt;a href="http://stackoverflow.com/users/18511/kip%20"&gt;Kip&lt;/a&gt; mentioned something important I had missed the first time around. That extra two (2) bytes was a newline! So armed with that key piece of information, I decided to use &lt;a href="http://www.fiddler2.com/fiddler2/"&gt;Fiddler&lt;/a&gt; to see what was happening within the cfhttp request. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Pest&lt;/b&gt;&lt;br /&gt;If you are unfamiliar with multipart submissions, the w3c describes them as a "&lt;a href="http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2"&gt;.. message contain(ing) a series of parts, each representing a successful control&lt;/a&gt;." In loose terms, a successful control is just a form field. (There is a little more to it than that.&amp;nbsp; But the details are not relevant to this particular case.) When a multipart form is submitted, the names and values of the various fields are submitted as parts, delineated by &lt;a href="http://en.wikipedia.org/wiki/MIME#Multipart_messages"&gt;boundary markers&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Now in this case, there is only one (1) form field. But as you can see from the image below, the information is nested within boundary markers. Obviously the request contents are separated by a newline, at various points.  But notice there is an &lt;i&gt;extra &lt;/i&gt;newline just before the closing boundary marker? That is the extra two (2) bytes. Given that &amp;lt;cfhttp&amp;gt; is responsible for generating the request content, and the separating newlines, it certainly seemed like a problem &amp;lt;cfhttp&amp;gt; &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TJW-XY3fDhI/AAAAAAAAAnE/WnPdymiMgMo/s1600/cfhttp_rawContent.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="137" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TJW-XY3fDhI/AAAAAAAAAnE/WnPdymiMgMo/s400/cfhttp_rawContent.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Next I submitted the same file manually with a regular &amp;lt;form&amp;gt; post.&amp;nbsp; The results from Fiddler showed there was no extra newline in the content.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TJXARzWNQvI/AAAAAAAAAnU/PJxlNsQCkNo/s1600/cfhttp_regularFormPost.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="165" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TJXARzWNQvI/AAAAAAAAAnU/PJxlNsQCkNo/s400/cfhttp_regularFormPost.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So I went back and tested the extra &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;formfield &lt;/span&gt;hack and surprise, surprise.. that pesky newline was gone.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TJXAnPd0dLI/AAAAAAAAAnc/tIw8_1ygJOo/s1600/cfhttp_nomoreNewLine.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TJXAnPd0dLI/AAAAAAAAAnc/tIw8_1ygJOo/s400/cfhttp_nomoreNewLine.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Another poster, &lt;a href="http://stackoverflow.com/users/56604/sergii"&gt;Sergii&lt;/a&gt;, mentioned this issue does not occur with Railo 3.1.2. So I tested the same code under Railo. Sure enough the resulting archive was fine, no corruption. Fiddler confirmed there were no pesky newline problems when using Railo's &amp;lt;cfhttp&amp;gt;. That clinched it for me. I would say this is an ACF bug with &amp;lt;cfhttp&amp;gt; in CF8 and CF9. So if you ever experience something similar, now you know why.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(Note: I do not know if this issue applies to 9.0.1) &lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2952427706511969763?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2952427706511969763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2952427706511969763&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2952427706511969763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2952427706511969763'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/09/cfhttp-file-post-bug-byte.html' title='CFHTTP + FILE + POST (Bug Byte ?)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/TJW-XY3fDhI/AAAAAAAAAnE/WnPdymiMgMo/s72-c/cfhttp_rawContent.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1567213235510451697</id><published>2010-09-07T22:52:00.000-07:00</published><updated>2010-09-08T09:11:43.556-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>My First Look at Diffie-Hellman (Merkle) Key Exchange - Part 2</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4MgprHLfxvM/TIcd6ajUIRI/AAAAAAAAAmc/lPsRxbxLGZU/s1600/AlicesKeyValues.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;/a&gt;&lt;/div&gt;After working through &lt;a href="http://cfsearching.blogspot.com/2010/09/my-first-look-at-diffie-hellman-merkle.html"&gt;the basic formulas in Part 1&lt;/a&gt;, I felt I had a decent grasp of the overall process. So I decided to dive into a java example.&amp;nbsp; From what I have read, there are different implementations. So I looked over a few java examples before choosing what I felt was the simplest: the one from the &lt;a href="http://download.oracle.com/javase/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppF"&gt;(Sun) Java Cryptography Extension (JCE) Reference Guide&lt;/a&gt;. Make no mistake, there is definitely a &lt;b&gt;lot&lt;/b&gt; more involved in establishing secure exchanges than is covered in the example. But as with most things, understanding the concepts and what the code is doing is a good start.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;So when I first looked at the java code, I was a bit .. flummoxed. I honestly did not recognize much of anything, other than "DH". I suppose I naively expected I might see objects initialized with secret values, calculations of prime numbers and primitive roots. Ye-ah.  Needless to say, I did not find anything like that. At least not in the basic "intro" example. &lt;br /&gt;&lt;br /&gt;The more I thought about it, I realized how silly that would be. Remember I mentioned typical exchanges involve really, really big numbers? Well imagine having to calculate really large prime numbers or primitive roots (on your own) in order to use the library? Not fun. After reviewing the code more closely, I realized the SunJCE does indeed provide a class that does the grunt work for you.&lt;br /&gt;&lt;br /&gt;First an &lt;a href="http://download.oracle.com/javase/6/docs/api/java/security/AlgorithmParameterGenerator.html"&gt;AlgorithmParameterGenerator&lt;/a&gt; is used to generate the initial parameters. In other words the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;prime number&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;primitive root &lt;/span&gt;agreed upon by Alice and Bob. In this example it is initialized with a key size 512 bits.  A real exchange would probably use a larger key like 1024 bits.  &lt;br /&gt;&lt;br /&gt;As you can imagine, generating the values is an expensive operation and may take a few seconds.  But when finished, the generator will return a &lt;a href="http://download.oracle.com/javase/6/docs/api/javax/crypto/spec/DHParameterSpec.html"&gt;DHParameterSpec&lt;/a&gt; object. It is simply an object containing the settings used for the exchange: prime number (p), primitive root (g) and key size (l). To view the values, use the methods &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getG()&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getP() &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getL()&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset generator = createObject("java", "java.security.AlgorithmParameterGenerator").getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;!--- Intialize the generator to create a 512 bit key pair (Testing only) ---&amp;gt;&lt;br /&gt;&amp;lt;!--- This is an expensive operation and may take a while ---&amp;gt;&lt;br /&gt;&amp;lt;cfset generator.init( javacast("int", 512) ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset params = generator.generateParameters() /&amp;gt;&lt;br /&gt;&amp;lt;!--- Convert the parameters to the right type of object ---&amp;gt;&lt;br /&gt;&amp;lt;cfset DHParameterSpec = createObject("java", "javax.crypto.spec.DHParameterSpec")/&amp;gt;&lt;br /&gt;&amp;lt;cfset parameterSpec   = params.getParameterSpec(DHParameterSpec.getClass()) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next the code passes those parameters into a &lt;a href="http://download.oracle.com/javase/6/docs/api/java/security/KeyPairGenerator.html"&gt;KeyPairGenerator &lt;/a&gt;. The generator returns a &lt;a href="http://download.oracle.com/javase/6/docs/api/java/security/KeyPair.html"&gt;KeyPair&lt;/a&gt;object which contains Alice's private and public keys. While so far things may not seem very familiar, the generator is actually doing the same thing we did in &lt;a href="http://cfsearching.blogspot.com/2010/09/my-first-look-at-diffie-hellman-merkle.html"&gt;Part 1&lt;/a&gt;. Except it automatically selects Alice's secret number, and calculates her public number internally using the given parameters (ie prime number and primitive root).&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset KeyPairGenerator = createObject("java", "java.security.KeyPairGenerator") /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyPairGenerator = KeyPairGenerator.getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyPairGenerator.initialize( parameterSpec ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyPair     = alicesKeyPairGenerator.generateKeyPair() /&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;How do you know this? Well if you display Alice's keys, you will see several parameter names followed by a long string of hexadecimal. Those values are just very large numbers, encoded as hex. The "x" represents Alice's private number and the "y" her public number. The "p" and "g" are our prime number and primitive root values. Again, encoded as hex. &lt;br /&gt;&lt;br /&gt;Starting to seem familiar now?&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TIcg2qLYSHI/AAAAAAAAAm0/fJRWwtW6cew/s1600/AlicesKeyValues.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="255" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TIcg2qLYSHI/AAAAAAAAAm0/fJRWwtW6cew/s400/AlicesKeyValues.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Alice's Values&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;    Format    = #alicesKeyPair.getPublic().getFormat()#&lt;br /&gt;    Base (g)  = #alicesKeyPair.getPublic().getParams().getG()#&lt;br /&gt;    Prime (p) = #alicesKeyPair.getPublic().getParams().getP()#&lt;br /&gt;&amp;lt;/pre&amp;gt;    &lt;br /&gt;&lt;br /&gt;&amp;lt;pre&amp;gt;    &lt;br /&gt;#alicesKeyPair.getPrivate()#&lt;br /&gt;&amp;lt;/pre&amp;gt;    &lt;br /&gt;&amp;lt;pre&amp;gt;    &lt;br /&gt;#alicesKeyPair.getPublic()#&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Before Alice sends Bob her public number, she creates a KeyAgreement. Basically this object will be used to complete the final step: calculating the shared key. So it is first initialized with Alice's private key. Then Alice sends her public key off to Bob, and waits to receive his in return.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Alice creates and initializes her DH KeyAgreement object with her Private Key ---&amp;gt;&lt;br /&gt;&amp;lt;cfset KeyAgreement = createObject("java", "javax.crypto.KeyAgreement").getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyAgreement = KeyAgreement.getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyAgreement.init( alicesKeyPair.getPrivate() ) /&amp;gt;&lt;br /&gt;&amp;lt;!--- Alice encodes her public key, and sends it over to Bob ---&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesPublicKeyBytes = alicesKeyPair.getPublic().getEncoded() /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When Bob receives Alice's public key, it is encoded in x509 format. So it has to be decoded it first. Bob then uses that object to create his own keys. Finally, he encodes his public key and sends it back to Alice. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;    Bob gets the DH parameters associated with Alice's public key. &lt;br /&gt;    He must use the same parameters when he generates his own key pair.&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset dhParamSpec = publicKeyFromAlice.getParams() /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Bob creates his own DH key pair ---&amp;gt;&lt;br /&gt;&amp;lt;cfset KeyPairGenerator = createObject("java", "java.security.KeyPairGenerator") /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyPairGenerator = KeyPairGenerator.getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyPairGenerator.initialize( dhParamSpec ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyPair = bobsKeyPairGenerator.generateKeyPair() /&amp;gt;&lt;br /&gt;&amp;lt;!--- Bob encodes his public key, and sends it over to Alice ---&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsPublicKeyBytes = bobsKeyPair.getPublic().getEncoded() /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Just like Alice's values, Bob's keys will be encoded as hex.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Bob's Values&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;    Base (g)  = #dhParamSpec.getG()#&lt;br /&gt;    Prime (p) = #dhParamSpec.getP()#&lt;br /&gt;&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;#bobsKeyPair.getPrivate()#&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;#bobsKeyPair.getPublic()#&lt;br /&gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Bob is now ready to calculate the shared key. So he too creates a KeyAgreement, and initializes it with his private key. Finally he plugs in Alice's public key and calculates the shared value. Now internally this class is using the same formulas as we did in &lt;a href="http://cfsearching.blogspot.com/2010/09/my-first-look-at-diffie-hellman-merkle.html"&gt;Part 1&lt;/a&gt;. But it is all done for you auto-magically.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Bob creates his DH KeyAgreement and initializes it with his private key ---&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyAgreement = createObject("java", "javax.crypto.KeyAgreement").getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyAgreement.init( bobsKeyPair.getPrivate() ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyAgreement.doPhase(publicKeyFromAlice, true) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsSharedSecret = bobsKeyAgreement.generateSecret() /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsSharedSecretAsHex = binaryEncode(bobsSharedSecret, "hex") /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once Alice receives Bob's public key, she decodes it and plugs the value into her KeyAgreement object. Then calculates the shared value.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset alicesKeyFactory = createObject("java", "java.security.KeyFactory").getInstance("DH") /&amp;gt;&lt;br /&gt;&amp;lt;cfset X509EncodedKeySpec = createObject("java", "java.security.spec.X509EncodedKeySpec") /&amp;gt;&lt;br /&gt;&amp;lt;cfset x509KeySpec = X509EncodedKeySpec.init( bobsPublicKeyBytes ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset publicKeyFromBob = alicesKeyFactory.generatePublic(x509KeySpec) /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyAgreement.doPhase( publicKeyFromBob, true ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesSharedSecret = alicesKeyAgreement.generateSecret() /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesSharedSecretAsHex = binaryEncode(alicesSharedSecret, "hex") /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Thanks to the wonders of mathematics, Alice and Bob both arrive at the same shared value.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TIcgmXVdySI/AAAAAAAAAmk/n2gLGlIUuL8/s1600/SharedValues.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="78" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TIcgmXVdySI/AAAAAAAAAmk/n2gLGlIUuL8/s400/SharedValues.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset areSecretsTheSame = alicesSharedSecretAsHex eq bobsSharedSecretAsHex /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Are Alice and Bob's secrets the same?&amp;lt;/strong&amp;gt; #areSecretsTheSame#&lt;br /&gt;&lt;br /&gt;&amp;lt;p class="result"&amp;gt;alicesSharedSecretAsHex&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;#alicesSharedSecretAsHex#&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;p class="result"&amp;gt;bobsSharedSecretAsHex&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;#bobsSharedSecretAsHex#&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;By itself, the shared value cannot be used for encryption. However Alice and Bob can use the shared value to generate a secret key which &lt;b&gt;can&lt;/b&gt; be used for encryption. &lt;br /&gt;&lt;br /&gt;The java documentation includes a simple example using DES. Obviously outdated, but it does demonstrate that Alice and Bob can successfully can encrypt/decrypt each other's values, starting only with the shared key.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TIcgx8eDEPI/AAAAAAAAAms/ZoxDQyQXWd0/s1600/DESResults.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TIcgx8eDEPI/AAAAAAAAAms/ZoxDQyQXWd0/s320/DESResults.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Bob Encrypts&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;     The previous call to bobsKeyAgreement.generateSecret resets the key&lt;br /&gt;     agreement object, so we call doPhase again prior to another generateSecret call&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsKeyAgreement.doPhase(publicKeyFromAlice, true) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsDESKey         = bobsKeyAgreement.generateSecret("DES") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Encrypt the text with a simple encryption ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Cipher               = createObject("java", "javax.crypto.Cipher") /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsCipher          = Cipher.getInstance("DES/ECB/NoPadding") /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsCipher.init( Cipher.ENCRYPT_MODE, bobsDESKey ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset textToEncrypt      = "StandAndDeliver!" /&amp;gt;&lt;br /&gt;&amp;lt;cfset bytesToEncrypt       = CharsetDecode(textToEncrypt, "utf8") /&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptedBytes       = bobsCipher.doFinal(bytesToEncrypt) /&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptedText     = BinaryEncode(encryptedBytes, "hex")  /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- results ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Bob's Values:&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DES Key&amp;lt;/strong&amp;gt;  : #BinaryEncode(bobsDESKey.getEncoded(), "hex")# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Encrypted Text&amp;lt;/strong&amp;gt;  : #encryptedText# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Alice Decrypts&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;     The previous call to bobsKeyAgreement.generateSecret resets the key&lt;br /&gt;     agreement object, so we call doPhase again prior to another generateSecret call&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesKeyAgreement.doPhase(publicKeyFromBob, true) /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesDESKey = alicesKeyAgreement.generateSecret("DES") /&amp;gt;&lt;br /&gt;&amp;lt;cfset Cipher               = createObject("java", "javax.crypto.Cipher") /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesCipher         = Cipher.getInstance("DES/ECB/NoPadding") /&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesCipher.init( Cipher.DECRYPT_MODE, alicesDESKey ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bytesToDecrypt     = BinaryDecode(encryptedText, "hex") /&amp;gt;&lt;br /&gt;&amp;lt;cfset unencryptedBytes  = alicesCipher.doFinal( bytesToDecrypt ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- results ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Alice's Values:&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;DES Key&amp;lt;/strong&amp;gt;  : #BinaryEncode(alicesDESKey.getEncoded(), "hex")# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Unencrypted text&amp;lt;/strong&amp;gt;  : #CharsetEncode(unencryptedBytes, "utf8")# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;            &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Obviously there is a lot more to consider before entering into this type of exchange. Guarding against &lt;a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack%20"&gt;man-in-the-middle attacks&lt;/a&gt; is definitely one issue. So you will want to do a lot more reading first. But hopefully this entry helped de-mystify Diffie-Hellman key exchanges ... a little.&lt;br /&gt;&lt;br /&gt;As always, any comments or corrections are welcome!&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1567213235510451697?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1567213235510451697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1567213235510451697&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1567213235510451697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1567213235510451697'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/09/my-first-look-at-diffie-hellman-merkle_07.html' title='My First Look at Diffie-Hellman (Merkle) Key Exchange - Part 2'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/TIcg2qLYSHI/AAAAAAAAAm0/fJRWwtW6cew/s72-c/AlicesKeyValues.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-9215252518312964885</id><published>2010-09-07T15:09:00.000-07:00</published><updated>2010-09-07T22:53:07.373-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>My First Look at Diffie-Hellman (Merkle) Key Exchange - Part 1</title><content type='html'>While I have seen references to Diffie-Hellman before, I honestly knew very little about it until this week. After seeing it mentioned on &lt;a href="http://stackoverflow.com/questions/tagged/coldfusion"&gt;stackoverflow.com&lt;/a&gt;, I decided to do some research. Now I am pretty sure this protocol is not available in the standard edition of Adobe ColdFusion, and contrary to popular opinion, I have my doubts about its availability in Enterprise version as well. Though admittedly, I could not find any solid references one way or the other. So I could be wrong. Anyway, since there is a plethora of implementations in the java world, I decided to explore that route.  &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; &lt;br /&gt;&lt;b&gt;Disclaimers&lt;/b&gt;&lt;br /&gt;First let me say this entry is not intended to be a "how to guide". In the world of encryption, I am most definitely a novice. But I am a curious novice. So in an effort to better understand the Diffie-Hellman (Merkle) exchange, I decided to take one of the simpler java implementations, deconstruct it, and put the results in a CF context.&amp;nbsp; If you are already familiar with it, this beginner level entry will probably be one big yawn. But any corrections or clarifications are definitely welcome.&amp;nbsp; Just go easy lest my brain implode.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is it?&lt;/b&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange"&gt;Wikipedia&lt;/a&gt; describes Diffie-Hellman as a key exchange protocol&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"...that allows two parties that have no prior knowledge of each other to jointly establish a shared secret key over an insecure communications channel. This key can then be used to encrypt subsequent communications using a symmetric key cipher."&lt;/blockquote&gt;&lt;br /&gt;My novice interpretation would be that instead of exchanging a key, two parties exchange "other", transitory, pieces of information instead. Then use those "other" pieces of information to derive the key (independently) without actually sending the key itself over an open channel.&lt;br /&gt;&lt;br /&gt;What are those "other" pieces of information? In short, they are really, really large numbers. The protocol uses several numbers in a series of simple  mathematical formulas to eventually calculate the secret key. I will not go into details about &lt;i&gt;how&lt;/i&gt; and &lt;i&gt;why &lt;/i&gt;those numbers are selected. The wikipedia entry describes it far better than I ever could. But suffice it to say they are not arbitrary. Each has specific characteristics that directly affect both the results and the security of the exchange. So I would highly recommend you read the article.&amp;nbsp; But to paraphrase the salient points (without formulas):&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Two parties (Alice and Bob) agree upon two (2) numbers to be used in their calculations (a prime number and a primitive root) &lt;i&gt;Note: These are public values, known by both Alice and Bob&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Then Alice and Bob each pick a private number. &lt;i&gt;Note: Alice should not know Bob's value, and Bob should not know Alice's value.&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Using their private numbers (plus the prime and primitive root) Alice and Bob each calculate a public number. They then exchange public numbers with each other. &lt;i&gt;Note: These are public values, known to both Alice and Bob. &lt;/i&gt;&lt;/li&gt;&lt;li&gt;After exchanging public values, Alice and Bob now have enough information to calculate the shared secret key (using another formula) &lt;i&gt;Note: They both arrive at the same secret key value, independently, without ever sending that value over an open channel.&lt;/i&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/TIauLJi7TuI/AAAAAAAAAmE/Oid9gIBqJfY/s1600/DiffieHellman_Overview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/TIauLJi7TuI/AAAAAAAAAmE/Oid9gIBqJfY/s320/DiffieHellman_Overview.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Math 101&lt;/b&gt;&lt;br /&gt;Now jumping straight into a java example from here felt a bit like sending a student driver onto a five lane highway after receiving only five minutes of instruction. So I decided to test the basic formulas from the &lt;a href="http://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange#Description"&gt;wikipedia example&lt;/a&gt; first.&amp;nbsp; It gave me a better understanding of the overall process, and also provided a good basis of comparison for the java results.&lt;br /&gt;&lt;br /&gt;Now before someone corrects me, the overview below is conceptual only.&amp;nbsp; When I finally did run the simple java example, the actual steps were slightly different. But overall the process was the same.&lt;br /&gt;&lt;br /&gt;(On a side note, this whole thing felt a bit like something you would read about in a spy novel. But I suppose that cannot be helped...)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 1) Preparing for the Meeting&lt;/b&gt;&lt;br /&gt;First, a prime number and &lt;a href="http://homepage.smc.edu/morgan_david/vpn/assignments/assgt-primitive-roots.htm"&gt;primitive root&lt;/a&gt; are selected. These are considered &lt;b&gt;public&lt;/b&gt; values, known to both Alice and Bob.&amp;nbsp;&amp;nbsp; Now you may notice I am using java objects. That was necessary because the calculations involved produce very large numbers. Even using small test values like 23 and 5 the results exceeded the capacity of a basic CF integer.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset prime = createObject("java", "java.math.BigInteger").init( 23 ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset base = createObject("java", "java.math.BigInteger").init( 5 ) /&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Values known to both Alice and Bob&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt; ie prime  = #prime# AND  base   = #base# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Step 2) Secret Code Words &lt;/b&gt;&lt;br /&gt;Next, Alice and Bob each select a private number, which they do &lt;b&gt;not &lt;/b&gt;share with each other. &lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset alicesPrivateValue    = createObject("java", "java.math.BigInteger").init( 6 ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsPrivateValue        = createObject("java", "java.math.BigInteger").init( 15 ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Step 3) The Public Exchange&lt;/b&gt;&lt;br /&gt;Alice and Bob then use their private numbers to calculate a &lt;b&gt;public&lt;/b&gt; number using the formula: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;base ^ private MOD prime&lt;/span&gt;. They then exchange public numbers. Again, their&amp;nbsp;&lt;i&gt;&lt;span style="color: red;"&gt;&lt;/span&gt;private&lt;/i&gt; numbers are never exchanged.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset alicesPublicValue     = base.modPow( alicesPrivateValue, prime) /&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Alice's values: &amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;span class="code"&amp;gt;alicesPublicValue = base ^ alicesPrivateValue MOD prime &amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;ie #alicesPublicValue# = #base# ^ #alicesPrivateValue# MOD #prime# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset bobsPublicValue     = base.modPow( bobsPrivateValue, prime) /&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Bob's values: &amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;div class="code"&amp;gt;bobsPublicValue = base ^ bobsPrivateValue MOD prime &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;ie #bobsPublicValue# = #base# ^ #bobsPrivateValue# MOD #prime#&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Step 4) Finding the Key&lt;/b&gt;&lt;br /&gt;Alice an Bob now have enough information to derive the shared secret value, independently. Alice uses the formula: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;alicesSharedKey = bobsPublicValue ^ alicesPrivateValue MOD prime&lt;/span&gt; .&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;strong&amp;gt;Alice uses Bob's value to compute the shared key (B &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; MOD p)&amp;lt;/strong&amp;gt;&lt;br /&gt;&amp;lt;div class="code"&amp;gt;alicesSharedKey = bobsPublicValue ^ alicesPrivateValue MOD prime &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;cfset alicesSharedKey    = bobsPublicValue.modPow(alicesPrivateValue, prime ) /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p class="result"&amp;gt;Alice's shared key is &amp;lt;strong&amp;gt;#alicesSharedKey#&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;ie   #alicesSharedKey# = #bobsPublicValue# ^ #alicesPrivateValue# MOD #prime#&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Whereas Bob uses the formula: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;bobsSharedKey = alicesPublicValue ^ bobsPrivateValue MOD prime&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;strong&amp;gt;Bob uses Alice's value to compute the shared key (A&amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt; MOD p)&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;&amp;lt;div class="code"&amp;gt;bobsSharedKey = alicesPublicValue ^ bobsPrivateValue MOD prime &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;cfset bobsSharedKey    = alicesPublicValue.modPow( bobsPrivateValue, prime ) /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p class="result"&amp;gt;Bob's shared key: #bobsSharedKey#&amp;lt;/p&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;ie   #bobsSharedKey# = #alicesPublicValue# ^ #bobsPrivateValue# MOD #prime#&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If everything was done correctly, they will both calculate the &lt;b&gt;same&lt;/b&gt; value (ie 2). This value can then be used to create a secret key (DES, etcetera) with which to encrypt and decrypt data.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/TIbiQMBY0iI/AAAAAAAAAmU/P3qi-oLmjYY/s1600/DiffieHellman_CFResults.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4MgprHLfxvM/TIbiQMBY0iI/AAAAAAAAAmU/P3qi-oLmjYY/s320/DiffieHellman_CFResults.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;Next up in Part 2: &lt;a href="http://cfsearching.blogspot.com/2010/09/my-first-look-at-diffie-hellman-merkle_07.html"&gt;Working through a java example&lt;/a&gt;.&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-9215252518312964885?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/9215252518312964885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=9215252518312964885&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/9215252518312964885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/9215252518312964885'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/09/my-first-look-at-diffie-hellman-merkle.html' title='My First Look at Diffie-Hellman (Merkle) Key Exchange - Part 1'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/TIauLJi7TuI/AAAAAAAAAmE/Oid9gIBqJfY/s72-c/DiffieHellman_Overview.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1117290400848568906</id><published>2010-08-18T20:26:00.000-07:00</published><updated>2010-08-20T07:36:27.149-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><category scheme='http://www.blogger.com/atom/ns#' term='Humor'/><title type='text'>OT: Random Image from Flickr</title><content type='html'>I came across this image on flickr. It made me laugh for &lt;i&gt;some&lt;/i&gt; reason ...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.flickr.com/photos/kiuz/4486531501/" title="Typo Poster / Batman 02 by Domenico / Kiuz, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2751/4486531501_aaa8bb709f_z.jpg" width="496" height="640" alt="Typo Poster / Batman 02" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1117290400848568906?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1117290400848568906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1117290400848568906&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1117290400848568906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1117290400848568906'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/08/ot-random-image-from-flickr.html' title='OT: Random Image from Flickr'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2751/4486531501_aaa8bb709f_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-9004423382146825189</id><published>2010-05-27T22:47:00.000-07:00</published><updated>2010-05-27T23:01:55.445-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion 9'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CF9 Question: Do Spreadsheet Functions Support "Blank Cells"?</title><content type='html'>I saw a question about spreadsheets this week that had me scratching my head. When you create a new worksheet in Excel, all of the cells are blank. So if you enter a long string in any cell, the text will overflow into the adjacent cell. (If the adjacent cell is blank.)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S_9VY7eXjJI/AAAAAAAAAl0/9YyAHvl9Gbo/s1600/BlankCell_Excel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S_9VY7eXjJI/AAAAAAAAAl0/9YyAHvl9Gbo/s320/BlankCell_Excel.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;However, if you do something similar in ColdFusion 9, the text does not overflow into the next cell. Notice how the extra text in cell &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;A1&lt;/span&gt; is hidden, even though the adjacent cell is technically empty.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/S_9VcWLyL2I/AAAAAAAAAl8/8i1VYk7pkio/s1600/BlankCell_CF9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4MgprHLfxvM/S_9VcWLyL2I/AAAAAAAAAl8/8i1VYk7pkio/s320/BlankCell_CF9.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    cfSheet = SpreadsheetNew("foo");&lt;br /&gt;    SpreadsheetAddRow(cfSheet, "this text should overflow,,short text", 1);&lt;br /&gt;    SpreadsheetSetColumnWidth(cfSheet, 1, 15); &lt;br /&gt;    SpreadsheetSetColumnWidth(cfSheet, 2, 15); &lt;br /&gt;    SpreadsheetSetColumnWidth(cfSheet, 3, 15); &lt;br /&gt;    &lt;br /&gt;    saveToFile = ExpandPath("test.xls");&lt;br /&gt;    SpreadsheetWrite(cfsheet, saveToFile, true);&lt;br /&gt;    &lt;br /&gt;    // how about a WriteLine() function folks ... ;) ?&lt;br /&gt;    WriteOutput("Saved file: "&amp; saveToFile &amp;"&amp;lt;hr&amp;gt;");&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfheader name="Content-Disposition" value="inline; filename=#saveToFile#"&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/vnd.ms-excel" file="#saveToFile#" deleteFile="true" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the underlying POI library there is a special cell type for blank cells: &lt;a href="http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#CELL_TYPE_BLANK"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CELL_TYPE_BLANK&lt;/span&gt;&lt;/a&gt;. In loose terms, it represents a raw cell that has never had a value. This is different from a cell whose value is set to an empty string. The value may be an empty string, but the cell still has a value. So it has a type of &lt;a href="http://poi.apache.org/apidocs/org/apache/poi/ss/usermodel/Cell.html#CELL_TYPE_STRING"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CELL_TYPE_STRING&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you loop over the test file created earlier, you will see all of the cells are &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CELL_TYPE_STRING&lt;/span&gt;. Which at least explains why the first cell's text does not overflow into the next cell.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    // open the workbook&lt;br /&gt;    source = ExpandPath("test.xls");&lt;br /&gt;    input  = createObject("java", "java.io.FileInputStream").init( source );&lt;br /&gt;    wb     = createObject("java", "org.apache.poi.ss.usermodel.WorkbookFactory").create( input );&lt;br /&gt;    // get the first sheet&lt;br /&gt;    sheet  = wb.getSheetAt(0);&lt;br /&gt;&lt;br /&gt;    // loop over each row in the sheet&lt;br /&gt;    rows = sheet.rowIterator();&lt;br /&gt;    while(rows.hasNext()) {&lt;br /&gt;        // get the current row&lt;br /&gt;        r = rows.next();&lt;br /&gt;&lt;br /&gt;        // loop over each cell in the sheet&lt;br /&gt;        cells = r.cellIterator();&lt;br /&gt;        while (cells.hasNext()) {&lt;br /&gt;            // get the current cell&lt;br /&gt;            c = cells.next();&lt;br /&gt;&lt;br /&gt;            // check the cell type (ingore error handling for brevity)&lt;br /&gt;            if (c.getCellType() == c.CELL_TYPE_BLANK) {&lt;br /&gt;                type = "CELL_TYPE_BLANK";&lt;br /&gt;            }&lt;br /&gt;            else if (c.getCellType() == c.CELL_TYPE_STRING) {&lt;br /&gt;                type = "CELL_TYPE_STRING";&lt;br /&gt;            }&lt;br /&gt;            else {&lt;br /&gt;                type = "other";&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // display the position, cell type / value&lt;br /&gt;            // note: Adding +1 because POI indexes are 0-based&lt;br /&gt;            WriteOutput("["&amp; r.getRowNum()+1 &amp;"]["&amp; c.getColumnIndex()+1 &amp;"]=");&lt;br /&gt;            WriteOutput(type &amp;" / "&amp; c.toString() &amp;"&amp;lt;hr&amp;gt;");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    // clean up &lt;br /&gt;    input.close();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But this raises the question, does ColdFusion 9 support "blank" cells, and if so how do you create one? I am honestly not sure.  You could work around it by tapping into the &lt;i&gt;undocumented &lt;/i&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getWorkBook()&lt;/span&gt; method of ColdFusion spreadsheet objects. It returns a reference to the underlying POI workbook. Using the workbook, you can then grab the desired rows and cells and change the cell type to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;CELL_TYPE_BLANK&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    cfSheet = SpreadsheetNew("foo");&lt;br /&gt;    SpreadsheetAddRow(cfSheet, "this text should overflow,,short text", 1);&lt;br /&gt;    SpreadsheetSetColumnWidth(cfSheet, 1, 15); &lt;br /&gt;    SpreadsheetSetColumnWidth(cfSheet, 2, 15); &lt;br /&gt;    SpreadsheetSetColumnWidth(cfSheet, 3, 15); &lt;br /&gt;    &lt;br /&gt;    // work around to make cell B1 a "blank" cell   &lt;br /&gt;    // POI row/cell indexes are 0-based !!&lt;br /&gt;    poiSheet = cfSheet.getWorkBook().getSheet("foo");&lt;br /&gt;    poiCell = poiSheet.getRow( 0 ).getCell( 1 ); &lt;br /&gt;    poiCell.setCellType( poiCell.CELL_TYPE_BLANK );&lt;br /&gt;    &lt;br /&gt;       &lt;br /&gt;    saveToFile = ExpandPath("newTest.xls");&lt;br /&gt;    SpreadsheetWrite(cfsheet, saveToFile, true);&lt;br /&gt;    WriteOutput("Saved file: "&amp; saveToFile &amp;"&amp;lt;br&amp;gt;");&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;                 &lt;br /&gt;&amp;lt;cfheader name="Content-Disposition" value="inline; filename=#saveToFile#"&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/vnd.ms-excel" file="#saveToFile#" deleteFile="true" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However I have not found a &lt;i&gt;documented &lt;/i&gt;way to do this. So does anyone know the answer to the million dollar question: does ColdFusion 9 provide a documented method for creating blank cells? My guess would be no. But I would be very happy to be proven wrong. Any spreadsheet function gurus out there?&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-9004423382146825189?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/9004423382146825189/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=9004423382146825189&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/9004423382146825189'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/9004423382146825189'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/05/cf9-question-do-spreadsheet-functions.html' title='CF9 Question: Do Spreadsheet Functions Support &quot;Blank Cells&quot;?'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/S_9VY7eXjJI/AAAAAAAAAl0/9YyAHvl9Gbo/s72-c/BlankCell_Excel.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3275871336389359045</id><published>2010-05-26T23:08:00.000-07:00</published><updated>2010-05-26T23:31:20.787-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Experiment Extracting Windows Thumbnails (XP and Windows 2003 only)</title><content type='html'>Windows thumbnails have existed for eons. But in all that time I never really used the windows explorer thumbnail view. Yes, pictures are nice. But invariably I found myself needing the detail view with its listing of file types, sizes and dates. &lt;br /&gt;&lt;br /&gt;Well, this week I came across an &lt;a href="http://stackoverflow.com/questions/228304/is-there-any-c-lib-to-read-thumbnails-from-thumb-db-in-windows-folder"&gt;old stackoverflow thread&lt;/a&gt; which mentioned &lt;a href="http://www.petedavis.net/drupal//index.php?q=node/2"&gt;a C# tool&lt;/a&gt; for reading and extracting images from the windows thumbnail cache (ie thumbs.db). At least on older XP and Windows 2003 systems. (Vista and later use a slightly different format.) While there are tools galore in this category, the idea of a small DLL that could be called from CF was appealing. So I decided to give it a quick whirl with CF8, under XP.&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;After compiling the source with Visual C# Express, I changed my explorer settings so I actually had a thumbnails file to test. Next, I created an instance of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ThumbDB&lt;/span&gt; class and initialized it by passing in the path my thumbnails database. Once initialized, I used the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;GetThumbFiles()&lt;/span&gt; method to grab an array of all file names within that database.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset util = createObject(".net", "ThumbDBLib.ThumbDB", "c:/test/ThumbDBLib.dll")&amp;gt;&lt;br /&gt;&amp;lt;cfset util.init( "C:/docs/thumbs.db" )&amp;gt;&lt;br /&gt;&amp;lt;cfset fileNames = util.GetThumbFiles()&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#fileNames#" label="Top 25 Files in Thumbs.db" top="25"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, I selected one of the file names and used the GetThumbData() method to retrieve the image bytes. I was hoping to create a CF image object from the bytes and display it in my browser. But every time I called ImageNew(), ColdFusion kept complaining about my argument type.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- this does NOT work ---&amp;gt;&lt;br /&gt;&amp;lt;!---  grabbing an arbitrary file from the listing for testing ...---&amp;gt;&lt;br /&gt;&amp;lt;cfset thumbnailName = fileNames[1] /&amp;gt;&lt;br /&gt;&amp;lt;cfset bytes = util.GetThumbData( thumbnailName )&amp;gt;&lt;br /&gt;&amp;lt;cfset img = ImageNew(bytes) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;That is when it hit me. A &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;byte &lt;/span&gt;in C# is not the same as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;byte&lt;/span&gt; in Java. Unlike Java, C# has signed and unsigned types.  So where C# has two data types, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;sbyte &lt;/span&gt;(-128 to 127) and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;byte &lt;/span&gt;(0 to 255), java has only one, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;byte &lt;/span&gt;(range -128 to 127). So according to the &lt;a href="http://livedocs.adobe.com/coldfusion/8/dotNet_04.html"&gt;data type conversion matrix&lt;/a&gt;, the C# byte array was being converted to a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;short &lt;/span&gt;array. &lt;br /&gt;&lt;br /&gt;Thanks to a tip from &lt;a href="http://www.blackwasp.co.uk/ConvertArray.aspx"&gt;BlackWasp.com&lt;/a&gt;, I added a new method called &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;GetJavaThumbData()&lt;/span&gt;, which converts the C# byte array into one that is compatible with Java. Using the new method, I was then able to display the thumbnail perfectly.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C# Code:&lt;/b&gt;&lt;br /&gt;&lt;pre class="c-sharp" name="code"&gt;public sbyte[] GetJavaThumbData(string fileName)&lt;br /&gt;    {&lt;br /&gt;        byte[] data = GetThumbData(fileName);&lt;br /&gt;        if (data != null)&lt;br /&gt;        {&lt;br /&gt;        sbyte[] jvData  = Array.ConvertAll&lt;byte, sbyte&gt;(data, delegate(byte b) { return unchecked((sbyte)b); });&lt;br /&gt;        return jvData;&lt;br /&gt;        }&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;ColdFusion Code:&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---  grabbing an arbitrary file from the listing for testing ...---&amp;gt;&lt;br /&gt;&amp;lt;cfset thumbnailName = fileNames[1] /&amp;gt;&lt;br /&gt;&amp;lt;cfset bytes = util.GetJavaThumbData( thumbnailName )&amp;gt;&lt;br /&gt;&amp;lt;cfset img = ImageNew( bytes )&amp;gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#img#"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It is worth noting the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ThumbDB&lt;/span&gt; class also has a method named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;GetThumbnailImage()&lt;/span&gt;, which returns a C# image object. You can use its properties to display things like height, width, resolution.  The class also has several methods for saving the image to a file. Out of curiosity, I tried several of the overloaded save() methods. But I only had success with the simplest form: Image.save(filepath). I am not sure why. Though with CF's own image functions, they are not really needed anyway. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset img = util.GetThumbnailImage( thumbnailName ) /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;strong&amp;gt;Thumbnail: #thumbnailName#&amp;lt;/strong&amp;gt; &amp;lt;hr /&amp;gt;&lt;br /&gt;    Height      = #img.Get_Height()#&lt;br /&gt;    Width       = #img.Get_Width()# &lt;br /&gt;    PixelFormat = #img.Get_PixelFormat()#&lt;br /&gt;    Resolution  = #img.Get_HorizontalResolution()# /&lt;br /&gt;                  #img.Get_VerticalResolution()# &lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Supposedly the &lt;a href="http://code.msdn.microsoft.com/WindowsAPICodePack"&gt;Windows API Code pack&lt;/a&gt; can extract thumbnails on later systems like Windows 7. If anyone has used it, or something similar, on Windows 7, let me know. I would be interested in hearing your experiences with it.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3275871336389359045?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3275871336389359045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3275871336389359045&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3275871336389359045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3275871336389359045'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/05/experiment-extracting-windows.html' title='Experiment Extracting Windows Thumbnails (XP and Windows 2003 only)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-4645940959009132179</id><published>2010-05-20T18:19:00.000-07:00</published><updated>2010-05-24T12:49:44.227-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MS SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>MS SQL 2005 Tip: Display Estimated Sizes of All Tables in a Database</title><content type='html'>Today I needed to get a quick &lt;a href="http://msdn.microsoft.com/en-us/library/aa933068%28SQL.80%29.aspx"&gt;estimate of tables sizes&lt;/a&gt; in an MS SQL 2005 database. So I ended up using the &lt;a href="http://msdn.microsoft.com/en-us/library/ms188776.aspx"&gt;sp_spaceused&lt;/a&gt; stored procedure, which displays the space used for either a database or a single object (table, etcetera).&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;As I was interested in a more detailed listing, I threw together a quick cursor that pulls all table names from the information_schema views, and inserts the results for each item into a table variable.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Updated&lt;/b&gt;: Updated to incorporate improvements from comments &lt;br /&gt;&lt;pre name="code" class="sql"&gt;USE MyDatabaseName&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;--- suppress extraneous row counts&lt;br /&gt;SET NOCOUNT ON&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;---    Temporary table used to store results&lt;br /&gt;DECLARE @spaceUsed TABLE &lt;br /&gt;(&lt;br /&gt;    RecordID int IDENTITY(1,1),&lt;br /&gt;    TableName nvarchar(128),&lt;br /&gt;    Rows varchar(20),&lt;br /&gt;    Reserved varchar(20),&lt;br /&gt;    Data varchar(20),&lt;br /&gt;    Index_size varchar(20),&lt;br /&gt;    Unused varchar(20),&lt;br /&gt;    SchemaName nvarchar(128)&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;---  get the names of all tables in the current database &lt;br /&gt;DEClARE @id int&lt;br /&gt;DECLARE @tableName VARCHAR(260)&lt;br /&gt;DECLARE @tableSchema VARCHAR(128)&lt;br /&gt;DECLARE @tables CURSOR&lt;br /&gt;SET @tables = CURSOR FOR SELECT    TABLE_SCHEMA, TABLE_SCHEMA +'.'+ TABLE_NAME &lt;br /&gt;                         FROM      INFORMATION_SCHEMA.TABLES &lt;br /&gt;                         WHERE     TABLE_TYPE = 'Base Table'&lt;br /&gt;&lt;br /&gt;OPEN @tables &lt;br /&gt;FETCH NEXT FROM @tables INTO @TableSchema, @TableName&lt;br /&gt;--- For each table ...&lt;br /&gt;WHILE @@FETCH_STATUS = 0 -- lazy check&lt;br /&gt;BEGIN&lt;br /&gt;    BEGIN TRY&lt;br /&gt;        --- insert the estimated size into the work table&lt;br /&gt;        INSERT INTO @spaceUsed (TableName, Rows, Reserved, Data, Index_Size, Unused)&lt;br /&gt;        EXEC sp_spaceused @TableName&lt;br /&gt;        &lt;br /&gt;        --- update the schema information&lt;br /&gt;        UPDATE    @spaceUsed&lt;br /&gt;        SET       SchemaName = @TableSchema&lt;br /&gt;        WHERE     RecordID = SCOPE_IDENTITY()&lt;br /&gt;&lt;br /&gt;    END TRY&lt;br /&gt;    BEGIN CATCH&lt;br /&gt;        --- ignore any errors&lt;br /&gt;        PRINT 'Unable to calculate space for table ['+ @TableName +'] '+ char(10) + ERROR_MESSAGE()&lt;br /&gt;    END CATCH&lt;br /&gt;&lt;br /&gt;    FETCH NEXT FROM @tables INTO @TableSchema, @TableName&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;CLOSE @tables&lt;br /&gt;DEALLOCATE @tables&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since the resulting sizes are formatted as strings (ie xxx KB), I had to run a quick update to remove the non-numeric values. Then I was able to calculate the total size for each table, and sort the results numerically. So I could get an idea of which were the largest tables in my database.&lt;br /&gt;&lt;br /&gt;It is not at all pretty. But it did get the job done. &lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="sql"&gt;--- remove KB prefix so values can be cast to numeric type ...&lt;br /&gt;UPDATE @spaceUsed&lt;br /&gt;SET  Reserved  = REPLACE(Reserved, ' KB', '')&lt;br /&gt;    , Data   = REPLACE(Data, ' KB', '')&lt;br /&gt;    , Index_size = REPLACE(Index_size, ' KB', '')&lt;br /&gt;    , Unused  = REPLACE(Unused, ' KB', '')&lt;br /&gt;    , Rows   = REPLACE(Rows, ' KB', '')&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;--- display estimates for each table (order by largest amount used)&lt;br /&gt;SELECT SchemaName &lt;br /&gt;    ,  TableName &lt;br /&gt;    , CAST(Rows AS decimal) AS Rows&lt;br /&gt;    , CAST(Reserved AS decimal) AS ReservedKB&lt;br /&gt;    , CAST(Data AS decimal) AS DataKB&lt;br /&gt;    , CAST(Index_size AS decimal) AS IndexKB&lt;br /&gt;    , CAST(Data AS decimal) + CAST(Index_size AS decimal) AS TotalUsedKB&lt;br /&gt;    , CAST(Unused AS decimal) AS UnusedKB&lt;br /&gt;FROM @spaceUsed&lt;br /&gt;ORDER BY TotalUsedKB DESC&lt;br /&gt;&lt;br /&gt;--- display overall estimates for database&lt;br /&gt;EXEC sp_spaceused&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;SET NOCOUNT OFF&lt;br /&gt;GO&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you are interested in listing the overall sizes for a series of MS SQL datasources, there is good example in an &lt;a href="http://www.aliaspooryorik.com/blog/index.cfm/e/posts.details/post/getting-ms-sql-database-size-using-coldfusion-37"&gt;older entry&lt;/a&gt; on John Whish's blog.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-4645940959009132179?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/4645940959009132179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=4645940959009132179&amp;isPopup=true' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4645940959009132179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4645940959009132179'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/05/ms-sql-2005-tip-display-estimated-sizes.html' title='MS SQL 2005 Tip: Display Estimated Sizes of All Tables in a Database'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3276431765589795054</id><published>2010-05-18T20:07:00.000-07:00</published><updated>2010-05-20T13:43:00.217-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Databases'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Please do not use the database examples for CFGRID!</title><content type='html'>Looking at the documentation for CFGRID today, I was reminded of something that really bugs me. If you look over some of the &lt;a href="http://livedocs.adobe.com/coldfusion/8/htmldocs/ajaxui_5.html#1126812"&gt;CFGRID examples&lt;/a&gt; they use dynamic sql, which is totally unsafe and vulnerable to sql injection. If forum posts are any indication, that same code is being used in live applications (unfortunately). So in case you were tempted, do not be lazy and copy straight out of the examples. If you want safe sql, you have to put in some work. Validate, scrub, lather, rinse, repeat.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3276431765589795054?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3276431765589795054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3276431765589795054&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3276431765589795054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3276431765589795054'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/05/please-do-not-use-database-examples-for.html' title='Please do not use the database examples for CFGRID!'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3387547863683160059</id><published>2010-05-05T03:41:00.000-07:00</published><updated>2010-05-06T20:19:05.541-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>PING  with ColdFusion and .NET</title><content type='html'>I was curious if were possible to ping a server using something other than the usual cfexecute and ping.exe. method. My first thought was surely java can do it. Feeling quite confident, I found a neat method in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;InetAddress&lt;/span&gt; class called &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/net/InetAddress.html#isReachable%28int%29"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;isReachable()&lt;/span&gt;&lt;/a&gt; that seemed to fit the bill. I happily wrote up a small test, ran the code, and quickly realized something was wrong. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; &lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    InetAddress = createObject("java", "java.net.InetAddress");&lt;br /&gt;    address     = InetAddress.getByName("www.google.com");&lt;br /&gt;    isReachable = address.isReachable( 500 ); //timeout&lt;br /&gt;    WriteOutput(  address.getHostName() &amp;" ["&amp; address.getHostAddress() &amp;"] "&amp;&lt;br /&gt;                  "IsReachable = "&amp; isReachable&lt;br /&gt;                );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Apparently, google was unreachable. At least to java.&amp;nbsp; Of course it is technically possible, yes. Probable ... no. Especially when a command line ping reported google was alive and kicking just moments prior to that. &lt;br /&gt;&lt;br /&gt;After re-checking the API, I realized &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;isReachable()&lt;/span&gt; might not be as good as it sounded. Aside from the usual disclaimers about firewalls and blocking, the API states:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;A typical implementation will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will try to establish a TCP connection on port 7 (Echo) of the destination host. &lt;/blockquote&gt;&lt;br /&gt;Since I had no idea what a &lt;i&gt;typical&lt;/i&gt; implementation was, I fired up &lt;a href="http://www.wireshark.org/"&gt;Wireshark&lt;/a&gt; to see what was really happening. Sure enough, Wireshark showed isReachable() was using a TCP connection, not ICMP. Since TCP Echo is often disabled, that explained why isReachable() returned false.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;Command Line Ping&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/S-FGo1SedII/AAAAAAAAAls/Mj-WAEGgBOg/s1600/commandLinePing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4MgprHLfxvM/S-FGo1SedII/AAAAAAAAAls/Mj-WAEGgBOg/s320/commandLinePing.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;InetAddress.isReachable(..)&lt;/span&gt; &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S-FGlj7Wb9I/AAAAAAAAAlk/Z3Usy339ZBA/s1600/javaIsReachable.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S-FGlj7Wb9I/AAAAAAAAAlk/Z3Usy339ZBA/s320/javaIsReachable.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So I thought to myself, either I do not have a &lt;i&gt;typical&lt;/i&gt; implementation, or the API is wrong.  (My money is on the latter). Originally I thought the jvm might be able to use ICMP through JNI perhaps. But apparently not. So back to the drawing board I went.&lt;br /&gt;&lt;br /&gt;That is when I found .NET's simple &lt;a href="http://msdn.microsoft.com/en-us/library/system.net.networkinformation.pingreply%28v=VS.100%29.aspx"&gt;Ping&lt;/a&gt; class. Its &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Send(..)&lt;/span&gt; method has four parameters: target host, timeout, sample data packet and options (time to live and discard fragmented packets).&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Host &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;options&lt;/span&gt; are complex objects. So you have to create an instance of those classes first.&amp;nbsp; Once you have all of the necessary objects, simply call Send(..) to execute the ping and get the response.  &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    ping        = createObject(".net", "System.Net.NetworkInformation.Ping");&lt;br /&gt;    dns         = createObject(".net", "System.Net.Dns");&lt;br /&gt;    ips         = dns.GetHostAddresses( "www.google.com" );&lt;br /&gt;&lt;br /&gt;    // arbitrary data to be transmitted  &lt;br /&gt;    data        = listToArray(repeatString("1,", 32));&lt;br /&gt;    // set the ttl (time to live) = 64 and disable fragmenting  &lt;br /&gt;    options     = createObject(".net", "System.Net.NetworkInformation.PingOptions").init(64, true);&lt;br /&gt;    &lt;br /&gt;    reply       = ping.Send ( ips[1], 100, javacast("short[]", data), options);&lt;br /&gt;    status      = createObject(".net", "System.Net.NetworkInformation.IPStatus");&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Finally, check the response status to determine if the ping was successful. The example below displays all of the options used for debugging purposes. But all you really need to do is check the response status.&lt;br /&gt;&lt;br /&gt;One oddity you may notice. For whatever reason, I do not believe you can access the class properties by name alone, as you can in .NET (or with java objects). So you must use the method &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;reply.Get_Address()&lt;/span&gt; instead of the shorter form &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;reply.Address&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- using HR tags because of a blogger bug ---&amp;gt;&lt;br /&gt;&amp;lt;cfif reply.Get_Status() eq status.Success&amp;gt;&lt;br /&gt;    &amp;lt;cfoutput&amp;gt;&lt;br /&gt;    Get_Address = #reply.Get_Address().ToString()# &amp;lt;hr /&amp;gt;&lt;br /&gt;    Get_RoundTripTime = #reply.Get_RoundtripTime().ToString()# &amp;lt;hr /&amp;gt;&lt;br /&gt;    Get_Options.Ttl (Time to Live) = #reply.Get_Options().Get_Ttl()# &amp;lt;hr /&amp;gt;&lt;br /&gt;    Get_Options.DontFragment  = #reply.Get_Options().Get_DontFragment()# &amp;lt;hr /&amp;gt;&lt;br /&gt;    Get_Buffer (Length) = #ArrayLen(reply.Get_Buffer())# &amp;lt;hr /&amp;gt;&lt;br /&gt;    &amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;cfelse&amp;gt;&lt;br /&gt;    Drat. Something went wrong ...&lt;br /&gt;&amp;lt;/cfif&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Anyway, I thought this was an interesting alternative to ping.exe. Plus, it was a good opportunity to brush up on my CF / .NET skills ;)&lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;b&gt;Update&lt;/b&gt;: {Sigh} Darn, I do not know why this one did not came up &lt;br /&gt;in my searches. Usually anything from cflib.org is pretty highly ranked. &lt;br /&gt;Well, in any event, it was still a good learning experience about why not to use java for ping ;).  &lt;a href="http://www.cflib.org/udf/Ping"&gt;http://www.cflib.org/udf/Ping&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3387547863683160059?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3387547863683160059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3387547863683160059&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3387547863683160059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3387547863683160059'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/05/ping-with-coldfusion-and-net.html' title='PING  with ColdFusion and .NET'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/S-FGo1SedII/AAAAAAAAAls/Mj-WAEGgBOg/s72-c/commandLinePing.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6818204666174192632</id><published>2010-04-27T06:26:00.000-07:00</published><updated>2010-04-27T08:23:20.415-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: Verify SMTP, POP3 and IMAP Mail Server Connection</title><content type='html'>I saw an intriguing question about mail servers this week, on &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt;. The question was is it possible to verify an SMTP mail server connection programatically? Essentially duplicate the "Verify mail server connection" functionality that exists in the CF Administrator. Though I am certain this is old news to some of you, the answer is yes. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;Interestingly, both suggestions on stackoverflow.com utilized java libraries already built into all three engines: Adobe ColdFusion, Railo and OpenBlueDragon. Member &lt;a href="http://stackoverflow.com/users/163423/folone"&gt;folone&lt;/a&gt; suggested using the SMTPClient class in &lt;a href="http://commons.apache.org/net/"&gt;Apache Commons Net&lt;/a&gt; , while member &lt;a href="http://stackoverflow.com/users/178526/sfussenegger"&gt;sfussenegger&lt;/a&gt;  suggested using the core &lt;a href="http://java.sun.com/products/javamail/index.jsp"&gt;JavaMail&lt;/a&gt; library with an &lt;a href="http://java.sun.com/javase/6/docs/api/java/net/Authenticator.html"&gt;Authenticator&lt;/a&gt;. (Unfortunately, I do not know their full names).&lt;br /&gt;&lt;br /&gt;Having used JavaMail and Authenticators before, I was somewhat familiar with that option. Though a bit rusty. Being less familiar with Commons Net, I had to do some research. Apparently, Commons Net is the predecessor of JavaMail. So the two libraries serve similar purposes, but Commons Net is a lower level API.  However, both can be used to communicate with SMTP and POP3 servers. Though I do not think the Commons library supports IMAP.&lt;br /&gt;&lt;br /&gt;Anyway, I was curious about the Commons classes, so I played around with them a bit. Eventually I managed to force an SSL connection with POP3, courtesy of &lt;a href="http://www.antsight.com/perry/archives/000697.html"&gt;this tip&lt;/a&gt; and the convenience MailSSLSocketFactory class. However, the code only works in Adobe CF. Unfortunately, Railo and OpenBlueDragon do not seem to include the MailSSLSocketFactory class, and I did not want to create my own.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt; &lt;br /&gt;   isVerified = false;&lt;br /&gt;   try {&lt;br /&gt;      SSLFactory = createObject("java", "com.sun.mail.util.MailSSLSocketFactory").init("SSL");&lt;br /&gt;      POP3Client = createObject("java", "org.apache.commons.net.pop3.POP3Client").init();&lt;br /&gt;      POP3Client.setSocketFactory( SSLFactory );&lt;br /&gt;      POP3Client.connect("pop.gmail.com", 995);&lt;br /&gt;      isVerified = POP3Client.login("user@gmail.com", "user password");&lt;br /&gt;      WriteOutput("isVerified="&amp; isVerified &amp;"&amp;lt;br /&amp;gt;");&lt;br /&gt;      POP3Client.logout();&lt;br /&gt;   }&lt;br /&gt;   // error occurred during login or logout&lt;br /&gt;   catch(java.io.IOException e) {&lt;br /&gt;      WriteDump(e);&lt;br /&gt;   }&lt;br /&gt;&amp;lt;/cfscript&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since JavaMail works on all three engines, with no extra classes, it seemed the best choice. Plus I really liked the idea of an all-in-one validator, not just smtp.  So I put together a rough function that validates SMTP, POP3 and IMAP connections. It should be compatible with CF8, CF9, Railo and OpenBlueDragon. Tested against gmail and hMailServer. &lt;br /&gt;&lt;br /&gt;For those not familiar with JavaMail, the function is very simple. It first stores the properties you want to use for the connection (like TLS). Then creates a new mail Session using those properties. Next it attempts to open a connection to the given mail server and requests authentication. Finally the connection is closed. If an error occurs, the function checks the exception type to determine if the credentials were invalid or it was some other type failure. The function returns a structure with three keys: WasValidated, ErrorType and ErrorDetail.&lt;br /&gt;&lt;br /&gt;One last note about the function. When TLS is selected, it is made mandatory. So if the mail server on the other end does not support TLS, the verification will fail, for security reasons. But you can change that behavior if you wish.&lt;br /&gt;&lt;br /&gt;If you are interested in reading more about JavaMail, these two articles are very comprehensive: &lt;a href="http://java.sun.com/developer/onlineTraining/JavaMail/contents.html"&gt;jGuru: Fundamentals of the JavaMail API&lt;/a&gt; and &lt;a href="http://java.sun.com/products/javamail/FAQ.html"&gt;JavaMail FAQ's&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset response = verifyMailServer(    host     = "smtp.gmail.com",&lt;br /&gt;                                          protocol = "smtp",&lt;br /&gt;                                          port     = 587,    &lt;br /&gt;                                          user     = "username@gmail.com",&lt;br /&gt;                                          password = "user password",&lt;br /&gt;                                          useTLS     = true,&lt;br /&gt;                                          debug    = true,&lt;br /&gt;                                          overwrite = false,&lt;br /&gt;                                          logPath  = "c:\verifyMailServer_Test.log"&lt;br /&gt;                                   ) /&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#response#" label="Verfication Results"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Function&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cffunction name="verifyMailServer" returntype="struct" access="public" output="true"&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="protocol" type="string" required="true" hint="Mail protocol: SMTP, POP3 or IMAP" /&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="host" type="string" required="true" hint="Mail server name (Example: pop.gmail.com)"/&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="port" type="numeric" default="-1" hint="Mail server port number. Default is -1, meaning use the default port for this protocol)" /&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="user" type="string" required="true" hint="Mail account username" /&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="password" type="string" required="true" hint="Mail account password" /&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="useSSL" type="boolean" default="false" hint="If true, use SSL (Secure Sockets Layer)" &amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="useTLS" type="boolean" default="false" hint="If true, use TLS (Transport Level Security)" &amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="enforceTLS" type="boolean" default="false" hint="If true, require TLS support" &amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="timeout" type="numeric" default="0" hint="Maximum milliseconds to wait for connection. Default is 0 (wait forever)" /&amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="debug" type="boolean" default="false" hint="If true, enable debugging. By default information is sent to is sent to System.out." &amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="logPath" type="string" default="" hint="Send debugging output to this file. Absolute file path. Has no effect if debugging is disabled." &amp;gt;&lt;br /&gt;    &amp;lt;cfargument name="append" type="boolean" default="true" hint="If false, the existing log file will be overwritten" &amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;cfset var status         = structNew() /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var props         = "" /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var mailSession     = "" /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var store         = "" /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var transport    = "" /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var logFile        = "" /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var fos             = "" /&amp;gt;&lt;br /&gt;    &amp;lt;cfset var ps             = "" /&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;!--- validate protocol ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset arguments.protocol = lcase( trim(arguments.protocol) ) /&amp;gt;&lt;br /&gt;    &amp;lt;cfif not listFindNocase("pop3,smtp,imap", arguments.protocol)&amp;gt;&lt;br /&gt;        &amp;lt;cfthrow type="IllegalArgument" message="Invalid protocol. Allowed values: POP3, IMAP and SMTP" /&amp;gt;&lt;br /&gt;    &amp;lt;/cfif&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;cfscript&amp;gt;&lt;br /&gt;        // initialize status messages&lt;br /&gt;        status.wasVerified     = false;&lt;br /&gt;        status.errorType      = "";&lt;br /&gt;        status.errorDetail  = "";&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;               props = createObject("java", "java.util.Properties").init();&lt;br /&gt;&lt;br /&gt;               // enable securty settings&lt;br /&gt;               if (arguments.useSSL or arguments.useTLS) {&lt;br /&gt;&lt;br /&gt;                    // use the secure protocol&lt;br /&gt;                    // this will set the property mail.{protocol}.ssl.enable = true&lt;br /&gt;                    if (arguments.useSSL) {&lt;br /&gt;                         arguments.protocol = arguments.protocol &amp;"s";            &lt;br /&gt;                    }&lt;br /&gt;                &lt;br /&gt;                    // enable identity check&lt;br /&gt;                    props.put("mail."&amp; protocol &amp;".ssl.checkserveridentity", "true");&lt;br /&gt;&lt;br /&gt;                    // enable transport level security and make it mandatory&lt;br /&gt;                    // so the connection fails if TLS is not supported&lt;br /&gt;                    if (arguments.useTLS) {&lt;br /&gt;                         props.put("mail."&amp; protocol &amp;".starttls.required", "true");&lt;br /&gt;                         props.put("mail."&amp; protocol &amp;".starttls.enable", "true");&lt;br /&gt;                    }&lt;br /&gt;               }&lt;br /&gt;&lt;br /&gt;               // force authentication command&lt;br /&gt;               props.put("mail."&amp; protocol &amp;".auth", "true");&lt;br /&gt;            &lt;br /&gt;               // for simple verifications, apply timeout to both socket connection and I/O &lt;br /&gt;               if (structKeyExists(arguments, "timeout")) {&lt;br /&gt;                    props.put("mail."&amp; protocol &amp;".connectiontimeout", arguments.timeout);&lt;br /&gt;                    props.put("mail."&amp; protocol &amp;".timeout", arguments.timeout);&lt;br /&gt;               }&lt;br /&gt;&lt;br /&gt;               // create a new mail session &lt;br /&gt;               mailSession = createObject("java", "javax.mail.Session").getInstance( props );&lt;br /&gt;&lt;br /&gt;               // enable debugging&lt;br /&gt;               if (arguments.debug) {&lt;br /&gt;                   mailSession.setDebug( true );&lt;br /&gt;                   &lt;br /&gt;                   // redirect the output to the given log file&lt;br /&gt;                   if ( len(trim(arguments.logPath)) ) {&lt;br /&gt;                        logFile = createObject("java", "java.io.File").init( arguments.logPath );&lt;br /&gt;                        fos      = createObject("java", "java.io.FileOutputStream").init( logFile, arguments.overwrite );&lt;br /&gt;                        ps       = createObject("java", "java.io.PrintStream").init( fos ); &lt;br /&gt;                        mailSession.setDebugOut( ps );&lt;br /&gt;                   }&lt;br /&gt;               }&lt;br /&gt;            &lt;br /&gt;               // Connect to an SMTP server ... &lt;br /&gt;               if ( left(arguments.protocol, 4) eq "smtp") {&lt;br /&gt;&lt;br /&gt;                    transport = mailSession.getTransport( protocol );&lt;br /&gt;                    transport.connect(arguments.host, arguments.port, arguments.user, arguments.password);&lt;br /&gt;                    transport.close();&lt;br /&gt;                    // if we reached here, the credentials should be verified&lt;br /&gt;                    status.wasVerified     = true;&lt;br /&gt;&lt;br /&gt;               }&lt;br /&gt;               // Otherwise, it is a POP3 or IMAP server&lt;br /&gt;               else {&lt;br /&gt;&lt;br /&gt;                    store = mailSession.getStore( protocol );&lt;br /&gt;                    store.connect(arguments.host, arguments.port, arguments.user, arguments.password);&lt;br /&gt;                    store.close();&lt;br /&gt;                    // if we reached here, the credentials should be verified&lt;br /&gt;                    status.wasVerified     = true;&lt;br /&gt;&lt;br /&gt;               }         &lt;br /&gt;&lt;br /&gt;         }&lt;br /&gt;         //for authentication failures&lt;br /&gt;         catch(javax.mail.AuthenticationFailedException e) {&lt;br /&gt;                   status.errorType     = "Authentication";&lt;br /&gt;                 status.errorDetail     = e;&lt;br /&gt;            }&lt;br /&gt;         // some other failure occurred like a javax.mail.MessagingException&lt;br /&gt;         catch(Any e) {&lt;br /&gt;                 status.errorType     = "Other";&lt;br /&gt;                 status.errorDetail     = e;&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;         // always close the stream ( messy work-around for lack of finally clause prior to CF9...)&lt;br /&gt;         if ( not IsSimpleValue(ps) ) {&lt;br /&gt;               ps.close();&lt;br /&gt;         }&lt;br /&gt;&lt;br /&gt;         return status;&lt;br /&gt;    &amp;lt;/cfscript&amp;gt;&lt;br /&gt;&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6818204666174192632?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6818204666174192632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6818204666174192632&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6818204666174192632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6818204666174192632'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/coldfusion-verify-smtp-pop3-and-imap.html' title='ColdFusion: Verify SMTP, POP3 and IMAP Mail Server Connection'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7357257770556603336</id><published>2010-04-27T04:29:00.000-07:00</published><updated>2010-05-02T02:07:18.830-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Railo'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Railo: CFPOP + Gmail + SSL Experiment</title><content type='html'>An interesting question on &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt; this week prompted me to explore cfmail/cfpop settings in the three engines: Railo, OpenBD and Adobe CF. If you have used gmail from ColdFusion, no doubt you are aware of one of the &lt;a href="http://www.anujgakhar.com/2008/05/18/cfpop-and-gmail/"&gt;work-arounds for the lack of SSL support for CFPOP&lt;/a&gt;. Being new to Railo, I did not realize the work-around is only for Adobe CF.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; &lt;br /&gt;Apparently Adobe CF also checks the default &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;java.lang.System &lt;/span&gt;properties when creating mail connections. If certain mail settings like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail.pop3.socketFactory.class&lt;/span&gt; are present, it applies them to the new connection. However, Railo does not. It only uses the supplied tag attributes, which do not include "useSSL". At least as far as I know. So the work-around has no effect in Railo.&lt;br /&gt;&lt;br /&gt;After poking around the &lt;a href="http://java.sun.com/j2ee/1.4/docs/api/javax/mail/Session.html"&gt;API&lt;/a&gt;, I did manage to get CFPOP working with gmail under Railo.. with a catch. You can specify which provider to use &lt;strike&gt;for the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;pop3&lt;/span&gt; protocol&lt;/strike&gt; as the default provider for the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;pop3&lt;/span&gt; protocol by adding a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;javamail.providers&lt;/span&gt; file to your {java_home}\lib directory. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Display {Java_Home} Path:&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset javaHome = createObject("java", "java.lang.System").getProperty("java.home", "")&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    javaHome\lib = #javaHome#\lib&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Simply add the following line, and save the file as javamail.providers. (The ".providers" file extension is important). All CFPOP connections will now use SSL.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;javamail.providers&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;protocol=pop3; type=store; class=com.sun.mail.pop3.POP3SSLStore; vendor=Sun Microsystems, Inc;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, I mentioned a catch. Unlike the work-around for Adobe CF, this setting is all-or-nothing. If you enable it, all CFPOP connections will use SSL. If you connect to a server does not support SSL, the connection will fail. With the Adobe CF work-around both connection types are allowed by setting the property &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mail.pop3.socketFactory.fallback&lt;/span&gt;&amp;nbsp; equal to true. So SSL will be used if supported. Otherwise, CF will fall back to a regular socket connection.&amp;nbsp; Keep in mind both work-arounds are system wide. So the settings apply to the entire JVM.&lt;br /&gt;&lt;br /&gt;Now, the fix may be too broad for some. But if you only need SSL connections for CFPOP, it might do the trick. If not, there are other options like sTunnel and custom CFC's. I am sure Railo will implement official support for SSL with CFPOP one of these days. Hopefully, Adobe CF will too ;) &lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7357257770556603336?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7357257770556603336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7357257770556603336&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7357257770556603336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7357257770556603336'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/railo-cfpop-gmail-ssl-experiment.html' title='Railo: CFPOP + Gmail + SSL Experiment'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-93218527563212248</id><published>2010-04-21T05:10:00.000-07:00</published><updated>2010-04-22T21:35:36.028-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZXing'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: ZXing - Read / Write QRCode Barcode Example</title><content type='html'>I have been slowly working my way through more of the &lt;a href="http://code.google.com/p/zxing/"&gt;zxing library&lt;/a&gt;. Since I did not find any CF examples in my searches, I am posting some of my code snippets in case it helps someone else.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;b&gt;Generate Barcode&lt;/b&gt;&lt;br /&gt;To generate a barcode, I first created an instance of the QRCodeWriter. Then called its encode() method with four settings: the text to encode, barcode type and the desired width and height. The encode() method does it magic and returns a matrix of bytes. Next I used the MatrixToImageWriter class, and its toBufferedImage(), method to convert the matrix into something useful. Not surprisingly, it returns a BufferedImage which is easily converted to a CF image object.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Note: This example uses the JavaLoader.cfc &lt;/i&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;    Generate barcode&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cftry&amp;gt;&lt;br /&gt;    &amp;lt;cfset origText = "http://code.google.com/p/zxing/wiki/GettingStarted" /&amp;gt;&lt;br /&gt;    &amp;lt;!--- initialize writer and create a new barcode matrix ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset BarcodeFormat = loader.create("com.google.zxing.BarcodeFormat") /&amp;gt;&lt;br /&gt;    &amp;lt;cfset writer = loader.create("com.google.zxing.qrcode.QRCodeWriter").init() /&amp;gt;&lt;br /&gt;    &amp;lt;cfset bitMatrix = writer.encode( origText, BarcodeFormat.QR_CODE, 80, 80 )&amp;gt;&lt;br /&gt;    &amp;lt;!--- render the matrix as a bufferedimage ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset converter = loader.create("com.google.zxing.client.j2se.MatrixToImageWriter")&amp;gt;&lt;br /&gt;    &amp;lt;cfset buff = converter.toBufferedImage( bitMatrix ) /&amp;gt;&lt;br /&gt;    &amp;lt;!--- convert it to a CF compatible image ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset img = ImageNew( buff ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!--- display results ---&amp;gt;&lt;br /&gt;    &amp;lt;b&amp;gt;Original Text = &amp;lt;/b&amp;gt; &amp;lt;cfoutput&amp;gt;#origText#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;&lt;br /&gt;        &amp;lt;cfimage action="writeToBrowser" source="#img#" format="png"&amp;gt;&lt;br /&gt;    &amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;!--- add real exception handling here ...---&amp;gt;&lt;br /&gt;    &amp;lt;cfcatch&amp;gt;&lt;br /&gt;        ERROR: Unable to generate barcode &amp;lt;cfoutput&amp;gt;#cfcatch.message#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;/cfcatch&amp;gt;&lt;br /&gt;&amp;lt;/cftry&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Read Barcode&lt;/b&gt;&lt;br /&gt;Now to read / decode, I passed the BufferedImage into a series of classes that attempt to locate a barcode within an image and essentially extract it into matrix of bits. Finally, I passed the matrix into a QRCodeReader for decoding and voila - it returned the decoded text.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Result&lt;/b&gt;:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S87opbZeuXI/AAAAAAAAAlc/0cD9I7lOLA8/s1600/ColdFusion_ZXing_QR_Code_Example.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S87opbZeuXI/AAAAAAAAAlc/0cD9I7lOLA8/s320/ColdFusion_ZXing_QR_Code_Example.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;    Decode barcode&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cftry&amp;gt;&lt;br /&gt;    &amp;lt;!--- extract the BufferedImage of the current barcode ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset buff = ImageGetBufferedImage( img ) /&amp;gt;&lt;br /&gt;    &amp;lt;!--- prepare the image for decoding ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset source = loader.create("com.google.zxing.client.j2se.BufferedImageLuminanceSource").init( buff ) /&amp;gt;&lt;br /&gt;    &amp;lt;cfset binarizer = loader.create("com.google.zxing.common.GlobalHistogramBinarizer").init( source ) /&amp;gt;&lt;br /&gt;    &amp;lt;cfset bitmap = loader.create("com.google.zxing.BinaryBitmap").init( binarizer ) /&amp;gt;&lt;br /&gt;    &amp;lt;cfset reader = loader.create("com.google.zxing.qrcode.QRCodeReader").init() /&amp;gt;&lt;br /&gt;    &amp;lt;!--- decode the barcode. skipping "hints" just for simplicity ---&amp;gt;&lt;br /&gt;    &amp;lt;cfset decodedResult = reader.decode( bitmap, javacast("null", "")) /&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;!--- display results ---&amp;gt;&lt;br /&gt;    &amp;lt;b&amp;gt;Decoded Text = &amp;lt;/b&amp;gt; &amp;lt;cfoutput&amp;gt;#decodedResult.getText()#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!--- add real exception handling here ...---&amp;gt;&lt;br /&gt;    &amp;lt;cfcatch&amp;gt;&lt;br /&gt;        ERROR: Unable to generate barcode &amp;lt;cfoutput&amp;gt;#cfcatch.message#&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;/cfcatch&amp;gt;&lt;br /&gt;&amp;lt;/cftry&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Related Entries&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://cfsearching.blogspot.com/2009/11/seeing-stripes-experiment-with-zxing.html"&gt;Seeing Stripes: Experiment with ZXing&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-93218527563212248?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/93218527563212248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=93218527563212248&amp;isPopup=true' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/93218527563212248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/93218527563212248'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/coldfusion-zxing-read-write-qrcode.html' title='ColdFusion: ZXing - Read / Write QRCode Barcode Example'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/S87opbZeuXI/AAAAAAAAAlc/0cD9I7lOLA8/s72-c/ColdFusion_ZXing_QR_Code_Example.png' height='72' width='72'/><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2180658837886292640</id><published>2010-04-19T18:55:00.000-07:00</published><updated>2010-04-19T19:38:01.286-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iText'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: iText / Add JavaScript To Form Example</title><content type='html'>I occasionally see questions about adding javascript to existing pdf's. There are (of course) some &lt;a href="http://1t3xt.info/tutorials/keywords/?page=keyword&amp;id=535"&gt;great examples on the iText site&lt;/a&gt;. I thought this CF translation of the AddJavaScriptToForm example might be helpful. If you review the code and comments, it actually simpler than it looks. There are some minor differences to compensate for the older iText jars in CF9 and CF8. As well as some name changes to avoid reserved word conflicts. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Source:&lt;/b&gt; &lt;a href="http://1t3xt.info/examples/browse/?page=example&amp;amp;id=438"&gt;http://1t3xt.info/examples/browse/?page=example&amp;amp;id=438&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;b&gt;Javascript Code (CF8 + CF9)&lt;/b&gt; &lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfsavecontent variable="jsCode"&amp;gt;&lt;br /&gt;    function setReadOnly(readonly) {&lt;br /&gt;        var partner = this.getField('partner');&lt;br /&gt;        if(readonly) {&lt;br /&gt;            partner.value = '';&lt;br /&gt;        }&lt;br /&gt;        partner.readonly = readonly;&lt;br /&gt;    }&lt;br /&gt;    function validate() {&lt;br /&gt;        var married = this.getField('married');&lt;br /&gt;        var partner = this.getField('partner');&lt;br /&gt;        if (married.value == 'yes' &amp;&amp; partner.value == '') {&lt;br /&gt;            app.alert('please enter the name of your partner');&lt;br /&gt;        }&lt;br /&gt;        else {&lt;br /&gt;            var prop = new Object();&lt;br /&gt;            prop.cURL = "http://1t3xt.info/examples/request.php";&lt;br /&gt;            prop.cSubmitAs = "HTML";&lt;br /&gt;            this.submitForm( {  &lt;br /&gt;                                cURL: "http://1t3xt.info/examples/request.php",&lt;br /&gt;                                cSubmitAs: "HTML"&lt;br /&gt;                              } &lt;br /&gt;                            );            &lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;1) Create a Form (CF9 + CF8)&lt;/b&gt;&lt;br /&gt;Note: CF8 does not support "finally". So for compatibility, just change the try/finally clause to a try/catch.&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    outputPath     = ExpandPath("form_without_js.pdf");&lt;br /&gt;    document = createObject("java", "com.lowagie.text.Document").init();&lt;br /&gt;&lt;br /&gt;    try {&lt;br /&gt;        stream = createObject("java", "java.io.FileOutputStream").init( outputPath );&lt;br /&gt;        writer = createObject("java", "com.lowagie.text.pdf.PdfWriter").getInstance(document, stream);&lt;br /&gt;        document.open();&lt;br /&gt;         &lt;br /&gt;         Element = createObject("java", "com.lowagie.text.Element");&lt;br /&gt;        BaseFont = createObject("java", "com.lowagie.text.pdf.BaseFont");&lt;br /&gt;        //Note: CF8 + CF9 iText versions do not have a createFont() method with zero params&lt;br /&gt;        bf = BaseFont.createFont( BaseFont.HELVETICA, BaseFont.WINANSI, false );&lt;br /&gt;        directcontent = writer.getDirectContent();&lt;br /&gt;        directcontent.beginText();&lt;br /&gt;        directcontent.setFontAndSize(bf, 12);&lt;br /&gt;        directcontent.showTextAligned( Element.ALIGN_LEFT, "Married?", 36, 770, 0 );&lt;br /&gt;        directcontent.showTextAligned( Element.ALIGN_LEFT, "YES", 58, 750, 0);&lt;br /&gt;        directcontent.showTextAligned( Element.ALIGN_LEFT, "NO", 102, 750, 0);&lt;br /&gt;        directcontent.showTextAligned( Element.ALIGN_LEFT, "Name partner?", 36, 730, 0 );&lt;br /&gt;        directcontent.endText();&lt;br /&gt;&lt;br /&gt;        // initialize reusable objects&lt;br /&gt;         Rectangle = createObject("java", "com.lowagie.text.Rectangle");&lt;br /&gt;         PdfFormField = createObject("java", "com.lowagie.text.pdf.PdfFormField");&lt;br /&gt;         RadioCheckField = createObject("java", "com.lowagie.text.pdf.RadioCheckField");&lt;br /&gt;         TextField = createObject("java", "com.lowagie.text.pdf.TextField");&lt;br /&gt;         Color = createObject("java", "java.awt.Color");&lt;br /&gt;&lt;br /&gt;        married = PdfFormField.createRadioButton(writer, true);&lt;br /&gt;        married.setFieldName("married");&lt;br /&gt;        writer.addAnnotation( married );&lt;br /&gt;        &lt;br /&gt;        // Note: Field names changed to avoid CF reserved word conflicts (ie "yes", "no")&lt;br /&gt;        married.setValueAsName("yes");&lt;br /&gt;        rectYes = Rectangle.init( 40, 766, 56, 744 );&lt;br /&gt;        yesField = RadioCheckField.init(writer, rectYes, javacast("null", ""), "yes");&lt;br /&gt;        yesField.setChecked(true);&lt;br /&gt;        married.addKid( yesField.getRadioField() );&lt;br /&gt;        rectNo = Rectangle.init( 84, 766, 100, 744 );&lt;br /&gt;        noField = RadioCheckField.init(writer, rectNo, javacast("null", ""), "no");&lt;br /&gt;        noField.setChecked(false);&lt;br /&gt;        married.addKid( noField.getRadioField() );&lt;br /&gt;        writer.addAnnotation( married );&lt;br /&gt; &lt;br /&gt;         rect = Rectangle.init( 40, 710, 200, 726 );&lt;br /&gt;        partner = TextField.init( writer, rect, "partner" );&lt;br /&gt;        partner.setBorderColor( Color.BLACK );&lt;br /&gt;        partner.setBorderWidth( 0.5 );&lt;br /&gt;        writer.addAnnotation( partner.getTextField() );&lt;br /&gt;    &lt;br /&gt;        document.close();&lt;br /&gt;        WriteOutput("File created! "&amp; outputPath &amp;"&amp;lt;hr&amp;gt;");&lt;br /&gt;    }&lt;br /&gt;       // cleanup  &lt;br /&gt;    finally {&lt;br /&gt;        if (isDefined("document")) {&lt;br /&gt;            document.close();&lt;br /&gt;        }        &lt;br /&gt;        if (isDefined("stream")) {&lt;br /&gt;            stream.close();&lt;br /&gt;        }        &lt;br /&gt;    }&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;2) Add the Javascript (CF9 Only)&lt;/b&gt; &lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    inputPath     = ExpandPath("form_without_js.pdf");&lt;br /&gt;    outputPath     = ExpandPath("form_plus_js.pdf");&lt;br /&gt;    document = createObject("java", "com.lowagie.text.Document").init();&lt;br /&gt;    &lt;br /&gt;    try {&lt;br /&gt;        // read in the pdf form&lt;br /&gt;        reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputPath );&lt;br /&gt;        stream = createObject("java", "java.io.FileOutputStream").init( outputPath );&lt;br /&gt;        stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( reader, stream );&lt;br /&gt;&lt;br /&gt;        // add javascript functions to the document&lt;br /&gt;        stamper.getWriter().addJavaScript( jsCode );&lt;br /&gt;&lt;br /&gt;        // create reference objects&lt;br /&gt;        PdfName = createObject("java", "com.lowagie.text.pdf.PdfName");&lt;br /&gt;        PdfAction = createObject("java", "com.lowagie.text.pdf.PdfAction");&lt;br /&gt;        PdfDictionary = createObject("java", "com.lowagie.text.pdf.PdfDictionary");&lt;br /&gt;        PushbuttonField = createObject("java", "com.lowagie.text.pdf.PushbuttonField");&lt;br /&gt;        &lt;br /&gt;        // extract the parent option from the form &lt;br /&gt;        formObj = stamper.getAcroFields();&lt;br /&gt;        fd = formObj.getFieldItem("married");&lt;br /&gt;&lt;br /&gt;        // retrieve the dictionaries for "yes" radio button&lt;br /&gt;        // note: CF9 iText version does not have the getWidgetRef(index) method&lt;br /&gt;         dictYes = reader.getPdfObject( fd.widget_refs.get(0) );&lt;br /&gt;        yesAction = dictYes.getAsDict( PdfName.AA );&lt;br /&gt;        if (not IsDefined("yesAction")) {&lt;br /&gt;            yesAction = PdfDictionary.init();&lt;br /&gt;        }&lt;br /&gt;        // add an onFocus event to this field&lt;br /&gt;        yesAction.put( PdfName.init("Fo"), PdfAction.javaScript("setReadOnly(false);", stamper.getWriter()));&lt;br /&gt;        dictYes.put( PdfName.AA, yesAction );&lt;br /&gt;&lt;br /&gt;        // retrieve the dictionaries for "no" radio button&lt;br /&gt;        dictNo = reader.getPdfObject( fd.widget_refs.get(1));&lt;br /&gt;        noAction = dictNo.getAsDict( PdfName.AA );&lt;br /&gt;        if (not IsDefined("noAction")) {&lt;br /&gt;            noAction = PdfDictionary.init();&lt;br /&gt;        }    &lt;br /&gt;        // add an onFocus event to this field&lt;br /&gt;        noAction.put( PdfName.init("Fo"), PdfAction.javaScript("setReadOnly(true);", stamper.getWriter()));&lt;br /&gt;        dictNo.put(PdfName.AA, noAction);&lt;br /&gt; &lt;br /&gt;         // create a submit button&lt;br /&gt;        writer = stamper.getWriter();&lt;br /&gt;        button = PushbuttonField.init(    writer, Rectangle.init(40, 690, 200, 710), "submit" );&lt;br /&gt;        button.setText( "validate and submit" );&lt;br /&gt;        button.setOptions( PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT );&lt;br /&gt;        validateAndSubmit = button.getField();&lt;br /&gt;        // this will call the validate function when the button is clicked&lt;br /&gt;        validateAndSubmit.setAction( PdfAction.javaScript("validate();", stamper.getWriter()) );&lt;br /&gt;        // add the button to page 1&lt;br /&gt;        stamper.addAnnotation(validateAndSubmit, 1);&lt;br /&gt;&lt;br /&gt;        WriteOutput("File created! "&amp; outputPath &amp;"&amp;lt;hr&amp;gt;");&lt;br /&gt;    }&lt;br /&gt;    finally {&lt;br /&gt;        // cleanup&lt;br /&gt;        if (isDefined("stamper")) {&lt;br /&gt;            stamper.close();&lt;br /&gt;        }        &lt;br /&gt;        if (isDefined("stream")) {&lt;br /&gt;            stream.close();&lt;br /&gt;        }        &lt;br /&gt;    }&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;2) Add the Javascript (CF8 Only)&lt;/b&gt; &lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    inputPath     = ExpandPath("form_without_js.pdf");&lt;br /&gt;    outputPath     = ExpandPath("form_plus_js.pdf");&lt;br /&gt;    document = createObject("java", "com.lowagie.text.Document").init();&lt;br /&gt;    &lt;br /&gt;    try {&lt;br /&gt;        // read in the pdf form&lt;br /&gt;        reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputPath );&lt;br /&gt;        stream = createObject("java", "java.io.FileOutputStream").init( outputPath );&lt;br /&gt;        stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( reader, stream );&lt;br /&gt;&lt;br /&gt;        // add javascript functions to the document&lt;br /&gt;        stamper.getWriter().addJavaScript( jsCode );&lt;br /&gt;&lt;br /&gt;        // create reference objects&lt;br /&gt;        PdfName = createObject("java", "com.lowagie.text.pdf.PdfName");&lt;br /&gt;        PdfAction = createObject("java", "com.lowagie.text.pdf.PdfAction");&lt;br /&gt;        PdfDictionary = createObject("java", "com.lowagie.text.pdf.PdfDictionary");&lt;br /&gt;        PushbuttonField = createObject("java", "com.lowagie.text.pdf.PushbuttonField");&lt;br /&gt;        &lt;br /&gt;        // prepare to extract form field objects&lt;br /&gt;        formObj = stamper.getAcroFields();&lt;br /&gt;        &lt;br /&gt;        // get parent option&lt;br /&gt;        fd = formObj.getFieldItem("married");&lt;br /&gt;&lt;br /&gt;        // retrieve the dictionaries for "yes" radio button&lt;br /&gt;        // note: CF8 iText version does not have the getWidgetRef(index) method or getDirectObject()&lt;br /&gt;         dictYes = reader.getPdfObject( fd.widget_refs.get(0) );&lt;br /&gt;        yesAction = reader.getPdfObject(dictYes.get(PdfName.AA));&lt;br /&gt;        if (not IsDefined("yesAction") or not yesAction.isDictionary()) {&lt;br /&gt;            yesAction = PdfDictionary.init();&lt;br /&gt;        }&lt;br /&gt;        // add an onFocus event to this field&lt;br /&gt;        yesAction.put( PdfName.init("Fo"), PdfAction.javaScript("setReadOnly(false);", stamper.getWriter()));&lt;br /&gt;        dictYes.put( PdfName.AA, yesAction );&lt;br /&gt;&lt;br /&gt;        // retrieve the dictionaries for "no" radio button&lt;br /&gt;        dictNo = reader.getPdfObject( fd.widget_refs.get(1));&lt;br /&gt;        noAction = reader.getPdfObject( dictNo.get(PdfName.AA) );&lt;br /&gt;        if (not IsDefined("noAction") or not noAction.isDictionary()) {&lt;br /&gt;            noAction = PdfDictionary.init();&lt;br /&gt;        }    &lt;br /&gt;        // add an onFocus event to this field&lt;br /&gt;        noAction.put( PdfName.init("Fo"), PdfAction.javaScript("setReadOnly(true);", stamper.getWriter()));&lt;br /&gt;        dictNo.put(PdfName.AA, noAction);&lt;br /&gt; &lt;br /&gt;         // create a submit button&lt;br /&gt;        writer = stamper.getWriter();&lt;br /&gt;        button = PushbuttonField.init(    writer,&lt;br /&gt;                                        Rectangle.init(40, 690, 200, 710), &lt;br /&gt;                                        "submit"&lt;br /&gt;                                    );&lt;br /&gt;        button.setText( "validate and submit" );&lt;br /&gt;        button.setOptions( PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT );&lt;br /&gt;        validateAndSubmit = button.getField();&lt;br /&gt;        // this will cal the validate function when the button is clicked&lt;br /&gt;        validateAndSubmit.setAction( PdfAction.javaScript("validate();", stamper.getWriter()) );&lt;br /&gt;        // add the button to page 1&lt;br /&gt;        stamper.addAnnotation(validateAndSubmit, 1);&lt;br /&gt;&lt;br /&gt;        WriteOutput("File created! "&amp; outputPath &amp;"&amp;lt;hr&amp;gt;");&lt;br /&gt;    }&lt;br /&gt;    catch(Any e) {&lt;br /&gt;        WriteOutput("ERROR: "&amp; e.message);&lt;br /&gt;    }&lt;br /&gt;    if (isDefined("stamper")) {&lt;br /&gt;        stamper.close();&lt;br /&gt;    }        &lt;br /&gt;    if (isDefined("stream")) {&lt;br /&gt;        stream.close();&lt;br /&gt;    }        &lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2180658837886292640?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2180658837886292640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2180658837886292640&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2180658837886292640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2180658837886292640'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/coldfusion-itext-add-javascript-to-form.html' title='ColdFusion: iText / Add JavaScript To Form Example'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-854801158503128107</id><published>2010-04-17T13:19:00.000-07:00</published><updated>2010-04-17T13:19:20.488-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CFChart'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CFChart Tip (Multiple background colors)</title><content type='html'>A recent question on &lt;a href="http://www.houseoffusion.com/groups/cf-talk/"&gt;CF-Talk&lt;/a&gt; asked if it were possible to create multiple background colors with cfchart. I was excited to discover it &lt;i&gt;is &lt;/i&gt;possible using the Y-Axis "limits" attribute.&amp;nbsp; I should have known I was not the first one to figure this out.&amp;nbsp; Well, in case you too missed the original entry, here it is:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.coldfusionjedi.com/index.cfm/2008/10/23/Cool-CFCHART-Tip--Background-Ranges"&gt;Cool CFCHART Tip - Background Ranges  (Raymond Camden)&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;b&gt;&amp;nbsp;Example of multiple background colors using Y-Axis "limits"&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/S8oWc29NCYI/AAAAAAAAAlM/s6EM-oZO6NQ/s1600/chartIdeal1_viaCFChart.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4MgprHLfxvM/S8oWc29NCYI/AAAAAAAAAlM/s6EM-oZO6NQ/s320/chartIdeal1_viaCFChart.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-854801158503128107?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/854801158503128107/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=854801158503128107&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/854801158503128107'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/854801158503128107'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/cfchart-tip-multiple-background-colors.html' title='CFChart Tip (Multiple background colors)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/S8oWc29NCYI/AAAAAAAAAlM/s6EM-oZO6NQ/s72-c/chartIdeal1_viaCFChart.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3941959589004243291</id><published>2010-04-14T18:23:00.000-07:00</published><updated>2010-04-14T18:23:34.265-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JODConverter'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>How to Install JODConverter 3.0 under ColdFusion 8</title><content type='html'>&lt;b&gt;ColdFusion 8 Instructions&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. Download latest version of the &lt;a href="http://code.google.com/p/jodconverter/"&gt;JODConverter&lt;/a&gt; and unzip.&lt;br /&gt;&lt;br /&gt;2. Copy all jars from the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;jodconverter-core-3.0-beta-3\lib directory&lt;/span&gt; into the CF classpath. (Your version numbers may vary)&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Note: I am not sure if all of the jars are needed. But this is the configuration that I used.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Example: Into WEB-INF\lib &lt;br /&gt;&lt;pre&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\commons-cli-1.1.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\commons-io-1.4.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\jodconverter-core-3.0-beta-3.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\json-20080701.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\juh-3.1.0.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\jurt-3.1.0.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\ridl-3.1.0.jar&lt;br /&gt;C:\ColdFusion8\wwwroot\WEB-INF\lib\unoil-3.1.0.jar&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;3. Smart people will make a back-up copy of the&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; jvm.config&lt;/span&gt; file here. &lt;br /&gt;&lt;br /&gt;4. Open the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;jvm.config&lt;/span&gt; file and locate the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;java.library.path&lt;/span&gt; value. Append the appropriate OpenOffice directory, using a comma. The exact directory will depend on your O/S. See the &lt;a href="http://code.google.com/p/jodconverter/wiki/Configuration"&gt;configuration page&lt;/a&gt; for details.&lt;br /&gt;&lt;br /&gt;Example:   On windows the new value might be:&lt;br /&gt;&lt;pre&gt;java.library.path={application.home}/../lib,{application.home}/../jintegra/bin,{application.home}/../jintegra/bin/international,C:/Program Files/OpenOffice.org 3/URE/bin &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;4. Stop and restart the CF Server&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3941959589004243291?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3941959589004243291/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3941959589004243291&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3941959589004243291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3941959589004243291'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/how-to-install-jodconverter-30-under.html' title='How to Install JODConverter 3.0 under ColdFusion 8'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-4771786376427814151</id><published>2010-04-14T16:27:00.000-07:00</published><updated>2010-04-20T21:32:20.799-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JODConverter'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>JODConverter 3.0 + OpenOffice + CF8</title><content type='html'>I stumbled across a &lt;a href="http://code.google.com/p/jodconverter/"&gt;new version&lt;/a&gt; of the &lt;a href="http://cfsearching.blogspot.com/2009/04/coldfusion-in-search-of-wordrtf-to-pdf.html"&gt;JODConverter&lt;/a&gt; a few weeks ago, and finally got around to testing it. Version 3.0 has some interesting new features over the previous version. For one thing, it no longer requires running OpenOffice as a service. The JODConverter can start an instance of OpenOffice on demand, like CF9. Both socket and named pipe connections are supported on windows. There are also new features like pooling and automatic restart, geared towards "improving the reliability and scalability of working with an external OOo [OpenOffice] process.". So I thought it was definitely worth a look (for Word to HTML conversions)&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;b&gt;Basic Conversion Example &lt;/b&gt;&lt;br /&gt;I decided to test it under CF8 first. Since I was not running OpenOffice as a service, the first thing I needed to do was fire up a new instance of OpenOffice. Now to start or stop OpenOffice, you will need an OfficeManager object. The simplest way to create one is using the DefaultOfficeManagerConfiguration class. Just create a new configuration object, then call the buildOfficeManager() method. This will create and return a new OfficeManager object pre-configured with the default settings, which should work in most environments. Then call OfficeManager.start() to kick-off the OpenOffice process. &lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center"&gt;&lt;a href="http://cfsearching.blogspot.com/2010/04/how-to-install-jodconverter-30-under.html"&gt;How to Install JODConverter 3.0 under ColdFusion 8&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    Config  = createObject("java", "org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration").init();&lt;br /&gt;    Config.setOfficeHome("C:\Program Files\OpenOffice.org 3\");&lt;br /&gt;    Manager = Config.buildOfficeManager();&lt;br /&gt;    Manager.start();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To convert a document, you first need to create an OfficeDocumentConverter object by passing in your OfficeManager. Then simply call the convert() method with your two files (ie input and output). Finally, use the OfficeManager to stop the OpenOffice instance. That is it. &lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    inPath = "c:\docs\myTestDocument.docx";&lt;br /&gt;    outPath = "c:\docs\myTestDocument_Converted.html";&lt;br /&gt;&lt;br /&gt;    OfficeDocumentConverter = createObject("java", "org.artofsolving.jodconverter.OfficeDocumentConverter");&lt;br /&gt;    converter = OfficeDocumentConverter.init( Manager );&lt;br /&gt;    input = createObject("java", "java.io.File").init( inPath );&lt;br /&gt;    output = createObject("java", "java.io.File").init( outPath );&lt;br /&gt;    Converter.convert(input, output);&lt;br /&gt;    WriteOutput("Output file created: "&amp; output);&lt;br /&gt;&lt;br /&gt;    Manager.stop();&lt;br /&gt;&amp;lt;/cfscript&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Obviously it would be silly to start and stop OpenOffice every time you needed to do a conversion. So a better alternative might be to initialize the OfficeManager once in your Application.cfc, and reuse it. Perform the initialization code in onApplicationStart and add your OfficeManager to the application scope. Then do the cleanup code (ie stopping OpenOffice) in onApplicationEnd. Other than grabbing the OfficeManager from the application scope first, the conversion code is exactly the same.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Application.cfc (Not including error handling, logging, etcetera)&lt;/b&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfcomponent&amp;gt;&lt;br /&gt; &amp;lt;cfset this.name = "jodconverterSample" /&amp;gt;&lt;br /&gt; &amp;lt;cfset this.applicationTimeOut = createTimeSpan(0, 1, 0, 0) /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;cffunction name="onApplicationStart" returnType="void"&amp;gt;&lt;br /&gt;  &amp;lt;cfset var Manager = "" /&amp;gt;&lt;br /&gt;  &amp;lt;cfset var Config  = "" /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;!--- start an instance with the default settings ---&amp;gt;&lt;br /&gt;  &amp;lt;cfset Config  = createObject("java", "org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration").init() /&amp;gt;&lt;br /&gt;  &amp;lt;cfset Config.setOfficeHome( "C:\Program Files\OpenOffice.org 3\" ) /&amp;gt;&lt;br /&gt;   &amp;lt;cfset Manager = Config.buildOfficeManager() /&amp;gt;&lt;br /&gt;   &amp;lt;cfset Manager.start() /&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;cfset application.OfficeManager = Manager /&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;/cffunction&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;cffunction name="onApplicationEnd" returnType="void"&amp;gt;&lt;br /&gt;     &amp;lt;cfargument name="appScope" type="any" required="true" /&amp;gt;&lt;br /&gt;  &amp;lt;!--- stop the instance ---&amp;gt;&lt;br /&gt;  &amp;lt;cfset appScope.OfficeManager.stop() /&amp;gt;&lt;br /&gt; &amp;lt;/cffunction&amp;gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Settings&lt;/b&gt;&lt;br /&gt;Earlier, I mentioned there are different types of connections and managers. The DefaultOfficeManagerConfiguration creates a socket connection on port 2002 by default. But you can use the available methods to change the port number, connection type, and a bunch of other settings. For example, you could create a named pipe connection instead. Just set the appropriate configuration properties before creating the OfficeManager.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    Config  = createObject("java", "org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration").init() /&amp;gt;&lt;br /&gt;    Config.setOfficeHome( "C:\Program Files\OpenOffice.org 3\" ) /&amp;gt;&lt;br /&gt;    // use named pipe connection &lt;br /&gt;    Protocol = createObject("java", "org.artofsolving.jodconverter.office.OfficeConnectionProtocol");&lt;br /&gt;    Config.setConnectionProtocol( Protocol.PIPE );&lt;br /&gt;    Config.setPipeName( "myApp_jod_pipe"  );&lt;br /&gt;    // kill any task that takes longer than 2 minutes &lt;br /&gt;    Config.setTaskExecutionTimeout((2 * 60 * 1000));&lt;br /&gt;    Manager = Config.buildOfficeManager();&lt;br /&gt;    // ....&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You could also connect to an external instance that is already running using the ExternalOfficeManagerConfiguration class instead. Though when working with an external process (ie controlled elsewhere ), obviously you do not start() or stop() it. Just connect to it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Web Application / Servlet&lt;/b&gt;&lt;br /&gt;Though JODConverter can be used strictly as a java library, there is also a sample web application/servlet available. It is not currently part of the distribution jar, but you can find it under the project source tab. Just be aware the web application does not fully handle conversions to HTML out-of-the-box. The servlet will produce a single html file, minus any images. As &lt;a href="http://code.google.com/p/jodconverter/wiki/FAQ"&gt;mentioned in the FAQ's&lt;/a&gt;, that is by design. The best way to handle images really "..depends on your particular requirements".  So the implementation of image handling is deliberately left up to you. For more details see the FAQ's. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;OpenOffice Quirks&lt;/b&gt;&lt;br /&gt;Obviously, OpenOffice has some quirks of its own. Though it does a pretty good job with most documents, it is not perfect. It almost certainly will not be able to convert everything you throw at it. So any conversion code should definitely incorporate some solid error handling. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;CF9 Quirks&lt;/b&gt;&lt;br /&gt;I was very curious to see how well all of the pieces worked together under CF9. As I expected, there were a few quirks. &lt;br /&gt;&lt;br /&gt;For whatever reason, things only worked smoothly when the JODConverter's instance of OpenOffice was started &lt;i&gt;after &lt;/i&gt;CF9 started its instance. In other words, I had to run a small Word to Pdf conversion first, to force CF to start its OpenOffice process. Then afterward start the JODConverter's instance. When they were not started in that order, all sorts of errors ensued. Both from CF and the JODConverter. &lt;br /&gt;&lt;br /&gt;While I had success with socket and external connections, I had zero luck getting a separate named pipe connection to work alongside CF9's instance.  Initially I thought it should be possible. But I am not very well versed in UNO or named pipes. So that could just be ignorance on my part. If anyone does know the answer, one way or the other, let me know.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;br /&gt;All in all, I was pleased with my initial tests. Though I am still not completely comfortable with the automatic restart feature. I can definitely see its value. OpenOffice can, and on occasion, does crash. But anything that automatically revives itself after death, tends to make me think of zombies ;) So I think I will need to study it (and how to best manage OOO instances) further.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-4771786376427814151?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/4771786376427814151/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=4771786376427814151&amp;isPopup=true' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4771786376427814151'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4771786376427814151'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/jodconverter-30-openoffice-cf8.html' title='JODConverter 3.0 + OpenOffice + CF8'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3629327886053537072</id><published>2010-04-01T01:52:00.000-07:00</published><updated>2010-04-01T01:52:17.457-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>OT: April 1 (Take Your Marks ... Get Set ... Go)</title><content type='html'>I see the day is already off to a rousing start. &lt;br /&gt;&lt;a href="http://googleblog.blogspot.com/2010/04/different-kind-of-company-name.html"&gt;http://googleblog.blogspot.com/2010/04/different-kind-of-company-name.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Wake me when it is over ...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3629327886053537072?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3629327886053537072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3629327886053537072&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3629327886053537072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3629327886053537072'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/04/ot-april-1-take-your-marks-get-set-go.html' title='OT: April 1 (Take Your Marks ... Get Set ... Go)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2046718440095090254</id><published>2010-02-15T18:21:00.000-08:00</published><updated>2010-02-15T18:29:39.547-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion 9'/><title type='text'>ColdFusion 9: CFPDF - Adding Headers and Footers (and a Few Quirks) - Part 2</title><content type='html'>In &lt;a href="http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfpdf-adding-headers.html"&gt;Part 1&lt;/a&gt; I posted some examples of text and image headers. CF9 also introduced some new constants for working with page numbers and labels. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;b&gt;Page Numbers &lt;/b&gt;&lt;br /&gt;Though "Page X of Y" headers/footers are not exactly earth-shattering, it is a little easier to add them to existing pdf's with the new constants &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;_PAGENUMBER&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;_LASTPAGENUMBER&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Sample Document ---&amp;gt;&lt;br /&gt;&amp;lt;cfdocument format="pdf" name="pdfInput"&amp;gt;&lt;br /&gt;    &amp;lt;cfloop from="1" to="10" index="x"&amp;gt;&lt;br /&gt;        The Blank Page &lt;br /&gt;        &amp;lt;cfif x lt 10&amp;gt;&lt;br /&gt;            &amp;lt;cfdocumentitem type="pagebreak" /&amp;gt;&lt;br /&gt;        &amp;lt;/cfif&amp;gt;&lt;br /&gt;    &amp;lt;/cfloop&amp;gt;&lt;br /&gt;&amp;lt;/cfdocument&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Add Page X of Y Footers ---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="addFooter"&lt;br /&gt;   source="pdfInput"&lt;br /&gt;   name="pdfOutput"&lt;br /&gt;   text="Page _PAGENUMBER of _LASTPAGENUMBER" &lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;NumberFormat &lt;/b&gt;&lt;br /&gt;With the help of the neat numberFormat attribute, you can change boring decimal page numbers into Roman numeral format (both upper and lower case). The supported values are: &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;LOWERCASEROMAN&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;NUMERIC&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;UPPERCASEROMAN. &lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Sample Document ---&amp;gt;&lt;br /&gt;&amp;lt;cfdocument format="pdf" name="pdfInput"&amp;gt;&lt;br /&gt;    &amp;lt;cfloop from="1" to="10" index="x"&amp;gt;&lt;br /&gt;        The Blank Page &lt;br /&gt;        &amp;lt;cfif x lt 10&amp;gt;&lt;br /&gt;            &amp;lt;cfdocumentitem type="pagebreak" /&amp;gt;&lt;br /&gt;        &amp;lt;/cfif&amp;gt;&lt;br /&gt;    &amp;lt;/cfloop&amp;gt;&lt;br /&gt;&amp;lt;/cfdocument&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Add Page X of Y in Roman Numerals ---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="addFooter"&lt;br /&gt;    source="pdfInput"&lt;br /&gt;    name="pdfOutput"&lt;br /&gt;    numberFormat="UpperCaseRoman"&lt;br /&gt;    text="Page _PAGENUMBER of _LASTPAGENUMBER" &lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Page Labels&lt;/b&gt;&lt;br /&gt;If your pdf contains custom Page Labels, you can also add that text to headers/footers using the _PAGELABEL and/or _LASTPAGELABEL constants. Obviously if your pdf doesn't have custom page labels, you will probably just see the default decimal page numbers instead. But I am pretty sure you can add custom labels with ddx (or alternately with iText).&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S3oC_QcaHWI/AAAAAAAAAkc/4WdP3Oq6kPA/s1600-h/ColdFusion9_CFDPF_PageLabels.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S3oC_QcaHWI/AAAAAAAAAkc/4WdP3Oq6kPA/s320/ColdFusion9_CFDPF_PageLabels.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Add Page Label to Header ---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="addHeader"&lt;br /&gt;    source="testDocumentWithLabels.pdf"&lt;br /&gt;    name="pdfOutput"&lt;br /&gt;    text="&amp;lt;b&amp;gt;Label For Page (_PAGENUMBER):&amp;lt;/b&amp;gt; _PAGELABEL" &lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Things You Cannot Do ...&lt;/b&gt;&lt;br /&gt;Perhaps this is an obvious point, but these settings have no affect on information already embedded within the pdf. In other words, you cannot change existing pdfs with page numbers already embedded in the file. However, if you use cfpdf to generate the headers/footers you can certainly remove them and add new ones.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Printing Headers/Footers&lt;/b&gt;&lt;br /&gt;For cases when you do not always want headers/footers to be printed, you can use the showOnPrint option to control visibility when printing. For example, you could tweak some of the previous snippets to display both the graphic and text headers on screen, but use showOnPrint="false" to make only the text header "printable". Obviously you can also use the pages attribute to apply that behavior only to select pages.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;    Display the graphics header only on screen&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="addHeader" &lt;br /&gt;    source="inputFile.pdf" &lt;br /&gt;    destination="pdfWithImageHeader.pdf" &lt;br /&gt;    topMargin="2.6"&lt;br /&gt;    leftMargin="0"&lt;br /&gt;    rightMargin="0"&lt;br /&gt;    align="center"&lt;br /&gt;    image="http://www.google.com/logos/olympics10-prsskating-hp.png"&lt;br /&gt;    overwrite="true"&lt;br /&gt;    showonprint = "false"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- &lt;br /&gt;    Display the text header both on screen and when printed&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="addHeader" &lt;br /&gt;    source="pdfWithImageHeader.pdf" &lt;br /&gt;    name="pdfOutput" &lt;br /&gt;    topMargin="1.7"&lt;br /&gt;    leftMargin="0"&lt;br /&gt;    rightMargin="0"&lt;br /&gt;    align="center"&lt;br /&gt;    text="#headerText#"&lt;br /&gt;    showonprint = "true"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, it is not extremely complex. But hopefully these examples make a good addendum to the limited documentation on the addHeader / addFooters features.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2046718440095090254?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2046718440095090254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2046718440095090254&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2046718440095090254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2046718440095090254'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfpdf-adding-headers-and.html' title='ColdFusion 9: CFPDF - Adding Headers and Footers (and a Few Quirks) - Part 2'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/S3oC_QcaHWI/AAAAAAAAAkc/4WdP3Oq6kPA/s72-c/ColdFusion9_CFDPF_PageLabels.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3525944510266433346</id><published>2010-02-15T14:59:00.000-08:00</published><updated>2010-02-15T19:06:57.415-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion 9'/><title type='text'>ColdFusion 9: CFPDF - Adding Headers and Footers (and a Few Quirks) - Part 1</title><content type='html'>With the explosion of new features in CFPDF, there is a lot to cover in the documentation. So it is understandably a little lacking on extra examples that go beyond the very basics. While belatedly exploring some of the extended features, I ran into a few quirks with addHeader / addFooter. Probably not news to some of you. But I thought I would share my examples and results in case it saves someone else a little time.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;b&gt;Text Headers and Footers&lt;/b&gt;&lt;br /&gt;The basic concept of adding a textual headers and footers was simple enough. Just use the appropriate action, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;addHeader &lt;/span&gt;or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;addFooter&lt;/span&gt;, along with a simple &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;text &lt;/span&gt;value.&amp;nbsp; Setting the text alignment is equally simple, just provide an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;align&lt;/span&gt; value (left,center, right) with the desired margins.&amp;nbsp; It is worth noting that if you omit the margin, CF uses its default.&amp;nbsp; While I would not swear to it, the default seems to be 1 inch. At least for letter sized pages. &lt;br /&gt;&lt;br /&gt;&lt;i&gt;Note: If there is too much text to display with the margin bounds, it may flow right off the page. So if working with a lot of text, you may need to adjust it with some html/css.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Align plain text header ---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf  action="addHeader" &lt;br /&gt;    source="inputFile.pdf" &lt;br /&gt;    name="pdfOutput" &lt;br /&gt;    align="left"&lt;br /&gt;    leftMargin="0.5"&lt;br /&gt;    text="Left Aligned. One-half (0.5) inch from left side"&lt;br /&gt;/&amp;gt;  &lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;b&gt;Styling Text Headers and Footers&lt;/b&gt;&lt;br /&gt;Applying html/css styles to the text is very similar to using a text watermark (added in CF 8.0.1). I did encounter one peculiarity with fonts. The names seem to be case sensitive. So on windows the font name "castellar" did nothing, but "Castellar" (with an uppercase "C") did produce the desired font. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;Add Styled header &lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfsavecontent variable="headerText"&amp;gt;&lt;br /&gt;    &amp;lt;span style="font-size: 25pt; font-family: Castellar;"&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #0080ff;"&amp;gt;Vancouver&amp;lt;/b&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #0000ff;"&amp;gt;2010&amp;lt;/b&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #000080;"&amp;gt;Olympics&amp;lt;/b&amp;gt;&lt;br /&gt;    &amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfpdf action="addHeader" &lt;br /&gt;    source="inputFile.pdf" &lt;br /&gt;    name="pdfOutput" &lt;br /&gt;    topMargin="1"&lt;br /&gt;    text="#headerText#"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;HTML/CSS Limitations&lt;/b&gt;&lt;br /&gt;Not all html tags are supported, such as &amp;lt;div&amp;gt;, &amp;lt;a&amp;gt;, etcetera. I am assuming the same limitations apply to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;action="addWatermark"&lt;/span&gt;. So whatever quirks one has, the others probably do as well.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Now in case you see an error message complaining about an "Invalid Document..", check the stack trace for the real error. Most likely it will say something about either an invalid tag or syntax error in your html/css.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;An error occurred during the ADDHEADER operation in the cfpdf tag.  &lt;br /&gt;Error: Invalid Document C:\ColdFusion9\wwwroot\test\pdf\inputFile.pdf specified for source or directory.  &lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;Stack Trace:&lt;br /&gt;com.adobe.internal.pdftoolkit.core.exceptions.PDFInvalidDocumentException: Error during text formatting, internalProcessElement: InvalidInput: Illegal element tag "div".&lt;br /&gt;....&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Differences between Watermarks and Headers/Footers&lt;/b&gt;&lt;br /&gt;One difference I have noticed is &lt;i&gt;how&lt;/i&gt; text is sized. CF 8.0.1 added the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;width &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;height&lt;/span&gt; attributes to support text watermarks. From what I have observed, the width and height values seem to control the size of the watermark text, rather than any explicit font sizes in html/css.&amp;nbsp; Since the  width and height attributes are not allowed with actions &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;addHeader &lt;/span&gt;and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;addFooter&lt;/span&gt;,&amp;nbsp; that text can be controlled by css font sizes. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Text and Image Opacity&lt;/b&gt;&lt;br /&gt;As with watermarks, you can also use the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;opacity &lt;/span&gt;attribute to change transparency of the header/footer. Simply use a value between 0 (transparent) and 10 (fully opaque). This example creates a styled footer whose text is 50% transparent. Opacity applies to both text and images.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S3nPhRPDmMI/AAAAAAAAAkU/oJMNzYUhTWA/s1600-h/ColdFusion9_CFPDF_SemiOpaqueTextFooter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S3nPhRPDmMI/AAAAAAAAAkU/oJMNzYUhTWA/s320/ColdFusion9_CFPDF_SemiOpaqueTextFooter.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfsavecontent variable="text"&amp;gt;&lt;br /&gt;    &amp;lt;span style="font-size: 18pt; font-family: Century Gothic;"&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #0080ff;"&amp;gt;Vancouver&amp;lt;/b&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #0000ff;"&amp;gt;2010&amp;lt;/b&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #000080;"&amp;gt;Olympics&amp;lt;/b&amp;gt;&lt;br /&gt;    &amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfpdf action="addFooter" &lt;br /&gt;    source="inputFile.pdf" &lt;br /&gt;    name="pdfOutput" &lt;br /&gt;    bottomMargin="0.5"&lt;br /&gt;    text="#text#"&lt;br /&gt;    align="center"&lt;br /&gt;    opacity="5"&lt;br /&gt;/&amp;gt;    &lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Image Headers and Footers&lt;/b&gt;&lt;br /&gt;Using images for headers and footers is also supported. The image source can be a file path, url, CF image object, array of bytes, or a base64 string (using isBase64="true"). &lt;br /&gt;&lt;br /&gt;Figuring out image headers/footers took a little while. It is not that the syntax is particularly cryptic. But it was not really clear to me, from the documentation, what should happen in various cases, such as when using an over-sized or undersized image. &lt;br /&gt;&lt;br /&gt;Based on my tests, if an image is too large to fit within the given margin dimensions, it is automatically re-sized. So if the margin is too small, you can end up with a skewed or squished image. I also observed some strange alignment issues in a few of my tests. Though I am not yet sure why. In any case, you may want to ensure your images are correctly sized beforehand, to avoid unexpected resizing behavior by cfpdf.&lt;br /&gt;&lt;br /&gt;If you view the image url below, its size should be around 7.4 x 2.4 inches. To center align the image, I used the code below. The top margin is set to "2.6" (inches). Tall enough to fit the image without resizing, plus a small amount of padding at the top. Both the left and right margin are set to zero (0) so the image is centered across the entire page width. &lt;br /&gt;&lt;br /&gt;Now you may notice that visually this image does not appear completely centered. But that is due to the layout of the underlying graphic. But you can adjust the position by changing the alignment and leftMargin.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;    Sample Document&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfdocument format="pdf" fileName="inputFile.pdf" pageType="Letter" marginTop="2.6" overwrite="true"&amp;gt;&lt;br /&gt;    &amp;lt;style type="text/css" media="screen"&amp;gt;&lt;br /&gt;        div { font-family: Castellar; padding: 10px; color: 204a64; } &lt;br /&gt;    &amp;lt;/style&amp;gt;&lt;br /&gt;    &amp;lt;cfloop from="1" to="10" index="x"&amp;gt;&lt;br /&gt;        &amp;lt;div&amp;gt; &lt;br /&gt;            Alpine Skiing * Biathlon * BobSleigh * Cross-Country Skiing * Figure Skating * &lt;br /&gt;            Ice Hockey * Luge * Curling * Snowboard * Speed Skating&lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;        &amp;lt;cfif x lt 10&amp;gt;&lt;br /&gt;            &amp;lt;cfdocumentitem type="pagebreak" /&amp;gt;&lt;br /&gt;        &amp;lt;/cfif&amp;gt;&lt;br /&gt;    &amp;lt;/cfloop&amp;gt;&lt;br /&gt;&amp;lt;/cfdocument&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- &lt;br /&gt;    Add image header (Note: Using image URL just for demonstration purposes)&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="addHeader" &lt;br /&gt;    source="inputFile.pdf" &lt;br /&gt;    destination="pdfWithImageHeader.pdf" &lt;br /&gt;    topMargin="2.6"&lt;br /&gt;    leftMargin="0"&lt;br /&gt;    rightMargin="0"&lt;br /&gt;    align="center"&lt;br /&gt;    image="http://www.google.com/logos/olympics10-prsskating-hp.png"&lt;br /&gt;    overwrite="true"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Multiple Headers / Footers&lt;/b&gt;&lt;br /&gt;It is also possible to layer headers/footers by adding text on top of an existing image. To demonstrate, read in the file created in the previous code snippet and adjust the margin size so the text is placed in the desired position. The results should look something like this&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S3nPURT_4pI/AAAAAAAAAkM/DLxE_gQ0uvI/s1600-h/ColdFusion9_CFPDF_TextAndImageHeader.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="176" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S3nPURT_4pI/AAAAAAAAAkM/DLxE_gQ0uvI/s320/ColdFusion9_CFPDF_TextAndImageHeader.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;Add text header on top of existing image header&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfsavecontent variable="headerText"&amp;gt;&lt;br /&gt;    &amp;lt;span style="font-size: 25pt; font-family: Castellar;"&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #0080ff;"&amp;gt;Vancouver&amp;lt;/b&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #0000ff;"&amp;gt;2010&amp;lt;/b&amp;gt;&lt;br /&gt;       &amp;lt;b style="color: #000080;"&amp;gt;Olympics&amp;lt;/b&amp;gt;&lt;br /&gt;    &amp;lt;/span&amp;gt;&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfpdf action="addHeader" &lt;br /&gt;    source="pdfWithImageHeader.pdf" &lt;br /&gt;    name="pdfOutput" &lt;br /&gt;    topMargin="1.7"&lt;br /&gt;    leftMargin="0"&lt;br /&gt;    rightMargin="0"&lt;br /&gt;    align="center"&lt;br /&gt;    text="#headerText#"&lt;br /&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Remove Headers/Footers&lt;/b&gt;    &lt;br /&gt;In the process of running all of these tests, I discovered something worth noting about images.&amp;nbsp; Using an image obviously increases the file size. In some cases substantially (I have not gotten around to doing any size comparisons between cfpdf and iText yet).  Since adding a new header/footer does &lt;i&gt;not &lt;/i&gt;remove any existing ones, if you mistakenly add an image twice, it will increase the file size .. twice. But you can always use the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;action="removeHeaderFooter"&lt;/span&gt; first. (Yes, it does remove both headers and footers).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- &lt;br /&gt;    Remove headers and footers&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfpdf action="removeHeaderFooter" &lt;br /&gt;        source="pdfWithImageHeader.pdf" &lt;br /&gt;        name="pdfOutput" &lt;br /&gt;    /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Display results ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfOutput)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;On a side note, if you use cfdocument to generate header and footers, as opposed to the new cfpdf actions, be aware there is a "Known Issue" mentioned in the CF9 release notes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;b&gt;Bug 76078:&lt;/b&gt;&lt;br /&gt;Headers or footers added while generating PDF using cfdocument are not marked and are not recognized as headers or footers. Therefore, cfpdf action="removeheaderfooter" will not be able to remove them from source PDF.&lt;/blockquote&gt;&lt;br /&gt;&lt;a href="http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfpdf-adding-headers-and.html"&gt;ColdFusion 9: CFPDF - Adding Headers and Footers (and a Few Quirks) - Part 2&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3525944510266433346?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3525944510266433346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3525944510266433346&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3525944510266433346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3525944510266433346'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfpdf-adding-headers.html' title='ColdFusion 9: CFPDF - Adding Headers and Footers (and a Few Quirks) - Part 1'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/S3nPhRPDmMI/AAAAAAAAAkU/oJMNzYUhTWA/s72-c/ColdFusion9_CFPDF_SemiOpaqueTextFooter.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1583884424060400325</id><published>2010-02-11T22:57:00.000-08:00</published><updated>2010-02-12T00:46:09.057-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iText'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: Adding a Link to an Existing PDF with iText</title><content type='html'>A recent question on &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt; asked how to add a hyperlink to an existing pdf with iText. There is most definitely more than one way to do it, and quite possibly better methods than the one mentioned here. But as it uses a few interesting techniques I thought I would share it.&amp;nbsp; Of course any comments or improvements are always welcome. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;As usual, first open the source pdf with a reader object, and use a stamper to prepare the output file for writing. With that out of the way, you can move on to creating the hyperlink. &lt;br /&gt;&lt;br /&gt;Given that CF8 and CF9 use older versions of iText, I decided the simplest method would be to use a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Chunk&lt;/span&gt; object.&amp;nbsp; If you are not familiar with Chunks, they are a low level object used to represent a bunch of characters all having the same properties (font, color, etcetera). So first initialize a Chunk with whatever text you want to use for the link. Then use &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;setAnchor()&lt;/span&gt; to specify the link url.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   pdfReader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputPath );&lt;br /&gt;   outStream = createObject("java", "java.io.FileOutputStream").init( outputPath );&lt;br /&gt;   pdfStamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( pdfReader, outStream );&lt;br /&gt;&lt;br /&gt;   chunk = createObject("java", "com.lowagie.text.Chunk").init("Rage Against the Machine (on Wikipedia)");&lt;br /&gt;   chunk.setAnchor("http://en.wikipedia.org/wiki/Rage_Against_the_Machine");&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since the default font is pretty bland, you will probably want to select a different font for the link. There are several ways to work with fonts. But in this example I defined a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;BaseFont &lt;/span&gt;by passing in the path to the physical font file, the desired encoding and a flag to ensure the font is embedded. The BaseFont definition is then used to create a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Font &lt;/span&gt;object with the desired settings (such as size, color and style) and applied to the Chunk object. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(On a side note, I was going to use the basic &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;arial.ttf &lt;/span&gt;font. But while perusing the windows/font directory, I was amused to find an odd font named &lt;i&gt;Rage&lt;/i&gt; and promptly decided I had use it for this entry instead) &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   // define an embedded font &lt;br /&gt;   BaseFont = createObject("java", "com.lowagie.text.pdf.BaseFont");&lt;br /&gt;   Font = createObject("java", "com.lowagie.text.Font");&lt;br /&gt;   bf = BaseFont.createFont("c:/windows/fonts/rage.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);&lt;br /&gt;   // create the main font object&lt;br /&gt;   textColor = createObject("java", "java.awt.Color").decode("##084f5a");&lt;br /&gt;   textFont = Font.init(bf, 18, Font.UNDERLINE, textColor);   &lt;br /&gt;   chunk.setFont( textFont );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now to position the Chunk, I decided to use a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ColumnText &lt;/span&gt;object. As the name implies, it is used to layout text in column format. Though used quite simply here, the ColumnText class is capable of some pretty complex operations. &lt;br /&gt;&lt;br /&gt;To create a ColumnText object you must pass in a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;PdfContentByte &lt;/span&gt;object. In loose terms that is  the canvas where the text will be drawn.&amp;nbsp; In this example, the link is added to the foreground. So &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getOverContent()&lt;/span&gt; is used to grab the canvas of the target page from the stamper object and then passed into the ColumnText object.&amp;nbsp; Finally the Chunk is added to the ColumnText object for rendering. &lt;br /&gt;&lt;br /&gt;The next to last step is to define the dimensions of the column. Once the dimensions are defined, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;ColumnText.go()&lt;/span&gt; is used to draw the link onto the pdf.&amp;nbsp; (I will not go into the details of positioning here. But if you are unfamiliar with it, &lt;a href="http://cfsearching.blogspot.com/2009/07/coldfusion-basic-example-positioning.html"&gt;this entry on buttons&lt;/a&gt; describes the typical way in which objects are positioned in iText.) &lt;br /&gt;&lt;br /&gt;&lt;div style="color: red;"&gt;Note: This snippet uses deprecated methods for CF8 compatibility. For a CF9 compatible version, see the end of entry&lt;/div&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   cb = pdfStamper.getOverContent(1); &lt;br /&gt;   ct = createObject("java", "com.lowagie.text.pdf.ColumnText").init(cb);&lt;br /&gt;   ct.addElement( chunk );&lt;br /&gt;&lt;br /&gt;   // set the column dimensions&lt;br /&gt;   page = pdfReader.getPageSize(1);&lt;br /&gt;   llx =  page.right()- 325;   &lt;br /&gt;   lly = page.top() - 36;       &lt;br /&gt;   urx = page.right();                &lt;br /&gt;   ury = page.top() - 8;     &lt;br /&gt;   ct.setSimpleColumn(llx, lly, urx, ury);&lt;br /&gt;&lt;br /&gt;   // write the text&lt;br /&gt;   ct.go();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once you close the stamper, the resulting pdf should contain a cool looking link in the top right. Minus the thematic image of course ..&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4MgprHLfxvM/S3Tz3sktXkI/AAAAAAAAAkE/PqgjWEuuvz0/s1600-h/ColdFusion_AddLinkToExistingPdf_WithItext.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4MgprHLfxvM/S3Tz3sktXkI/AAAAAAAAAkE/PqgjWEuuvz0/s320/ColdFusion_AddLinkToExistingPdf_WithItext.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="color: #38761d;"&gt;&lt;b&gt;Complete Code (ColdFusion 8)&lt;/b&gt;&lt;/div&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;     inputPath = ExpandPath("./myDocument.pdf");&lt;br /&gt;     outputPath = ExpandPath("./myDocumentWithLink.pdf");&lt;br /&gt;&lt;br /&gt;     try {&lt;br /&gt;        // initialize objects&lt;br /&gt;        pdfReader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputPath );&lt;br /&gt;        outStream = createObject("java", "java.io.FileOutputStream").init( outputPath );&lt;br /&gt;        pdfStamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( pdfReader, outStream );&lt;br /&gt;&lt;br /&gt;        // create a chunk with a anchor (ie hyperlink)&lt;br /&gt;        chunk = createObject("java", "com.lowagie.text.Chunk").init("Rage Against the Machine (on Wikipedia)");&lt;br /&gt;        chunk.setAnchor("http://en.wikipedia.org/wiki/Rage_Against_the_Machine");&lt;br /&gt;&lt;br /&gt;        // define an embedded font &lt;br /&gt;        BaseFont = createObject("java", "com.lowagie.text.pdf.BaseFont");&lt;br /&gt;        Font = createObject("java", "com.lowagie.text.Font");&lt;br /&gt;        bf = BaseFont.createFont("c:/windows/fonts/rage.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);&lt;br /&gt;&lt;br /&gt;        // create the main font object&lt;br /&gt;        textColor = createObject("java", "java.awt.Color").decode("##084f5a");&lt;br /&gt;        textFont = Font.init(bf, 18, Font.UNDERLINE, textColor);   &lt;br /&gt;&lt;br /&gt;        // apply the font to the chunk &lt;br /&gt;        chunk.setFont( textFont );&lt;br /&gt;&lt;br /&gt;        // prepare to write the link onto the *first* page only        &lt;br /&gt;        cb = pdfStamper.getOverContent(1); // first page&lt;br /&gt;        ct = createObject("java", "com.lowagie.text.pdf.ColumnText").init(cb);&lt;br /&gt;        ct.addElement( chunk );&lt;br /&gt;&lt;br /&gt;        // position link near top right &lt;br /&gt;        // note: using deprecated versions of getRight() and getBottom()&lt;br /&gt;        page = pdfReader.getPageSize(1);&lt;br /&gt;        llx =  page.right()- 325;   &lt;br /&gt;        lly = page.top() - 36;       &lt;br /&gt;        urx = page.right();                &lt;br /&gt;        ury = page.top() - 8;     &lt;br /&gt;        // initialize column dimensions&lt;br /&gt;        ct.setSimpleColumn(llx, lly, urx, ury);&lt;br /&gt;&lt;br /&gt;        // write the text&lt;br /&gt;        ct.go();&lt;br /&gt;    }&lt;br /&gt;    catch (java.lang.Exception e) {&lt;br /&gt;       // Save the error object and use cfdump _outside_ &lt;br /&gt;       // the cfscript block to display the full error detail&lt;br /&gt;       WriteOutput("ERROR: "&amp;amp; e.message &amp;amp;"&amp;lt;hr /&amp;gt;");&lt;br /&gt;       WriteOutput("DETAIL: "&amp;amp; e.detail);&lt;br /&gt;    }        &lt;br /&gt;   &lt;br /&gt;   // closing the stamper generates the output file&lt;br /&gt;    if (IsDefined("pdfStamper")) {&lt;br /&gt;        WriteOutput("Closing pdfStamper ..&amp;lt;hr /&amp;gt;");&lt;br /&gt;       pdfStamper.close();&lt;br /&gt;   }&lt;br /&gt;   // also ensure the outstream is always closed&lt;br /&gt;   // to avoid locked files if an error occurs early on ..&lt;br /&gt;    if (IsDefined("outStream")) {&lt;br /&gt;        WriteOutput("Closing outStream  ..&amp;lt;hr /&amp;gt;");&lt;br /&gt;       outStream.close();&lt;br /&gt;   }&lt;br /&gt;   WriteOutput("Output file generated: "&amp;amp; outputPath );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="color: blue;"&gt;&lt;b&gt;Complete Code (ColdFusion 9)&lt;/b&gt;&lt;/div&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;     inputPath = ExpandPath("./myDocument.pdf");&lt;br /&gt;     outputPath = ExpandPath("./myDocumentWithLink.pdf");&lt;br /&gt;&lt;br /&gt;     try {&lt;br /&gt;        // initialize objects&lt;br /&gt;        pdfReader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputPath );&lt;br /&gt;        outStream = createObject("java", "java.io.FileOutputStream").init( outputPath );&lt;br /&gt;        pdfStamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( pdfReader, outStream );&lt;br /&gt;&lt;br /&gt;        // create a chunk with a anchor (ie hyperlink)&lt;br /&gt;        chunk = createObject("java", "com.lowagie.text.Chunk").init("Rage Against the Machine (on Wikipedia)");&lt;br /&gt;        chunk.setAnchor("http://en.wikipedia.org/wiki/Rage_Against_the_Machine");&lt;br /&gt;&lt;br /&gt;        // define an embedded font &lt;br /&gt;        BaseFont = createObject("java", "com.lowagie.text.pdf.BaseFont");&lt;br /&gt;        Font = createObject("java", "com.lowagie.text.Font");&lt;br /&gt;        bf = BaseFont.createFont("c:/windows/fonts/rage.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);&lt;br /&gt;&lt;br /&gt;        // create the main font object&lt;br /&gt;        textColor = createObject("java", "java.awt.Color").decode("##084f5a");&lt;br /&gt;        textFont = Font.init(bf, 18, Font.UNDERLINE, textColor);   &lt;br /&gt;&lt;br /&gt;        // apply the font to the chunk &lt;br /&gt;        chunk.setFont( textFont );&lt;br /&gt;&lt;br /&gt;        // prepare to write the link onto the *first* page only        &lt;br /&gt;        cb = pdfStamper.getOverContent(1); // first page&lt;br /&gt;        ct = createObject("java", "com.lowagie.text.pdf.ColumnText").init(cb);&lt;br /&gt;        ct.addElement( chunk );&lt;br /&gt;&lt;br /&gt;        // position link near top right &lt;br /&gt;        // note: using deprecated versions of getRight() and getBottom()&lt;br /&gt;        page = pdfReader.getPageSize(1);&lt;br /&gt;        llx =  page.getRight()- 325;   &lt;br /&gt;        lly = page.getTop() - 36;       &lt;br /&gt;        urx = page.getRight();                &lt;br /&gt;        ury = page.getTop() - 8;     &lt;br /&gt;        // initialize column dimensions&lt;br /&gt;        ct.setSimpleColumn(llx, lly, urx, ury);&lt;br /&gt;&lt;br /&gt;        // write the text&lt;br /&gt;        ct.go();&lt;br /&gt;    }&lt;br /&gt;    catch (java.lang.Exception e) {&lt;br /&gt;       // Save the error object and use cfdump _outside_ &lt;br /&gt;       // the cfscript block to display the full error detail&lt;br /&gt;       WriteOutput("ERROR: "&amp;amp; e.message &amp;amp;"&amp;lt;hr /&amp;gt;");&lt;br /&gt;       WriteOutput("DETAIL: "&amp;amp; e.detail);&lt;br /&gt;    }        &lt;br /&gt;   &lt;br /&gt;   // closing the stamper generates the output file&lt;br /&gt;    if (IsDefined("pdfStamper")) {&lt;br /&gt;        WriteOutput("Closing pdfStamper ..&amp;lt;hr /&amp;gt;");&lt;br /&gt;       pdfStamper.close();&lt;br /&gt;   }&lt;br /&gt;   // also ensure the outstream is always closed&lt;br /&gt;   // to avoid locked files if an error occurs early on ..&lt;br /&gt;    if (IsDefined("outStream")) {&lt;br /&gt;        WriteOutput("Closing outStream  ..&amp;lt;hr /&amp;gt;");&lt;br /&gt;       outStream.close();&lt;br /&gt;   }&lt;br /&gt;   WriteOutput("Output file generated: "&amp;amp; outputPath );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1583884424060400325?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1583884424060400325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1583884424060400325&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1583884424060400325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1583884424060400325'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-adding-link-to-existing-pdf.html' title='ColdFusion: Adding a Link to an Existing PDF with iText'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4MgprHLfxvM/S3Tz3sktXkI/AAAAAAAAAkE/PqgjWEuuvz0/s72-c/ColdFusion_AddLinkToExistingPdf_WithItext.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-5873411366634223681</id><published>2010-02-11T22:21:00.000-08:00</published><updated>2010-02-12T01:23:32.976-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>OT: Valentine's Day Humor</title><content type='html'>A recent link in twitter pointed out a &lt;a href="http://xkcd.com/701/"&gt;Science Valentine comic&lt;/a&gt;.  It got me to thinking about the strange rituals and spectacle of Valentine's Day. It has always seemed like a hokey, greeting-card holiday, more overtly commercial than all the others. Of course most holidays have become increasingly commercialized. But despite all that, I still love the magic of Christmas, the mystery of Halloween, and the inevitable laughter and tears that accompany most dysfunctional family "get-togethers" at Thanksgiving.  But to me, Valentine's Day only evokes a sense of curiosity and humor at the artificially induced drama of it all. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;As a young children we usually find the whole concept "icky" and want nothing to do with it. As we get a little older we must endure the angst of deciding whether or not to give a Valentine's Day card to someone we "like". (&lt;i&gt;But.. if I do that then they'll _know_ I like them!&lt;/i&gt;) The pins and needles of waiting to see if that person &lt;i&gt;you &lt;/i&gt;like gives you a card. The elation when they do. The crushing disappointment when they do not. Not to mention the awkwardness of receiving a card from someone you do not like. (&lt;i&gt;Mom, is there a nice way to say "Ewwww. Gross. No way."?&lt;/i&gt;) Oh the high drama of primary school. &lt;br /&gt;&lt;br /&gt;Even as adults, the day still evokes strong emotions in many of us. Those that are in relationships tend to "coo" and "gush" to a revolting degree. Those that are not, either piteously wallow in sorrow while tossing back copious amounts of beer or scarfing down chocolates, or they turn morose and bitter making scathing quips about the doomed nature of all relationships. &lt;br /&gt;&lt;br /&gt;Despite the ups and downs of many Valentine's Days past, I choose to view the day with a bit of my usual weird humor. It is best summed up by the following song requests I heard one year:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;span id="fullpost"&gt;&lt;li&gt;Love Stinks &lt;i&gt;(J. Geils Band) &lt;/i&gt;&lt;/li&gt;&lt;li&gt;Used To Love Her (&lt;i&gt;Guns N' Roses)&lt;/i&gt;&lt;/li&gt;&lt;li&gt;She Hates Me &lt;i&gt;(Puddle of Mud)&lt;/i&gt;&lt;/li&gt;&lt;/span&gt;&lt;/ul&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;br /&gt;Thinking of it still makes me laugh. If you have ever listened to the songs, and have a sense of humor about the day, you will know exactly why ;)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-5873411366634223681?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/5873411366634223681/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=5873411366634223681&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/5873411366634223681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/5873411366634223681'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/ot-valentines-day-humor.html' title='OT: Valentine&apos;s Day Humor'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7083682542437997089</id><published>2010-02-11T17:34:00.000-08:00</published><updated>2010-02-11T22:14:42.025-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iText'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 9: Adding Document Level Attachments to a PDF with iText</title><content type='html'>While cfpdf provides some nice features, like merging and deleting pages, it does not provide a way to attach files as far as I know. But this can be done with a small bit of iText magic. There are a few different ways to attach files to a pdf. If you are looking for examples, there are some excellent ones on the &lt;a href="http://itextpdf.com/"&gt;iText site&lt;/a&gt; you can easily adapt for ColdFusion. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;One way to attach a file is at the document level. So when viewing the pdf with a tool like Adobe Reader, the files appear only in the attachments pane. The iText version that ships with CF9 has a handy convenience method for creating attachments. Unfortunately, that method did not exist yet in iText 1.4. So if you are running CF8, you will need to use the &lt;a href="http://javaloader.riaforge.org/"&gt;JavaLoader.cfc&lt;/a&gt;, and a newer version of iText, to take advantage of it. (Though a quick glance at the source code suggests it is possible with CF8's version with a little extra CF code.) But back to the example.. &lt;br /&gt;&lt;br /&gt;In case you do not have a pdf handy, simply create one with cfdocument first. Though any pdf should work.  &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset inputFile = ExpandPath("myDocument.pdf") /&amp;gt;&lt;br /&gt;&amp;lt;cfdocument format="PDF" name="pdfContent"&amp;gt;&lt;br /&gt;    &amp;lt;cfdump var="#server.os#" label="Server O/S" /&amp;gt;&lt;br /&gt;&amp;lt;/cfdocument&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now if you have read any of my previous entries on iText, you will be very familiar with next few steps. Initialize a few variables with the paths of the files you wish to attach. (I went a little crazy and decided to attach three files: a Word document, an Excel file and a simple text file). Next, read in your source file with a PdfReader object. Then prepare a PdfStamper to generate the output file. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   // ...&lt;br /&gt;   inputFile = ExpandPath("myDocument.pdf");&lt;br /&gt;   outputFile = ExpandPath("myDocumentWithAttachments.pdf");&lt;br /&gt;   &lt;br /&gt;   attach1   = "c:/test/docs/NewsLetter-Feb-2010.doc";&lt;br /&gt;   attach2   = "c:/test/docs/Statistics-Jan-2010.xls";&lt;br /&gt;   attach3   = "c:/test/docs/test.txt";&lt;br /&gt;&lt;br /&gt;   reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputFile );&lt;br /&gt;   outStream = createObject("java", "java.io.FileOutputStream").init( outputFile );&lt;br /&gt;   stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( reader, outStream );&lt;br /&gt;   // ...&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It is worth noting this example actually embeds the content of each file within the pdf. So obviously final pdf will be larger than the original. To actually attach the files, simply use the stamper's addFileAttachment(..) method on each one. That method is overloaded, but the signature used in this example accepts four arguments: file description, data, file path and file name.&lt;br /&gt;&lt;br /&gt;The first argument is an optional description of the attachment. The second and third arguments pertain to &lt;i&gt;how &lt;/i&gt;you wish to attach the content. You can either supply content dynamically (via an array of bytes) or using a physical file path. Since it would not make sense to supply both, just provide a value for one of the arguments and use null for the other. If you accidentally supply both, the file path will probably be ignored. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The final argument of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;addFileAttachment(..)&lt;/span&gt; allows you to customize the file name displayed in the attachment pane. Obviously a handy feature if you are supplying dynamic content and do not necessarily have a file name. But you can use it in either scenario to just display a more user friendly file name. (On a side note, the file name is technically optional. But I do not see much point in leaving it blank.)&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   // ...&lt;br /&gt;   // create the first attachment from a file path&lt;br /&gt;   stamper.addFileAttachment("Newsletter for February", javacast("null", ""), attach1, "Newsletter.doc");&lt;br /&gt;&lt;br /&gt;   // ...&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once you have attached the files, you can get a little fancy and modify the viewer preferences to display the attachment pane when the pdf is first opened. It is a nice way to draw a user's attention to the fact that the pdf contains attachments. You should also adjust the pdf version to 1.6, since that is when this feature was added.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   // ...&lt;br /&gt;   // display the attachment pane when the pdf opens (Since 1.6)  &lt;br /&gt;   writer = stamper.getWriter();&lt;br /&gt;   writer.setPdfVersion( writer.VERSION_1_6 );&lt;br /&gt;   stamper.setViewerPreferences( writer.PageModeUseAttachments );    &lt;br /&gt;   // ...&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once you have properly closed the pdf, the final output should look like the image below in Acrobat Reader. Now whether or not you can open/save the attachments all depends on your security settings. I believe the default for Acrobat Reader 8 and 9 is to disable the opening of all &lt;i&gt;non-pdf&lt;/i&gt; attachments. So you may need to adjust your Trust Manager settings accordingly. Keep in mind that behavior has nothing to do with the pdf file itself. It is strictly how Acrobat chooses to handle attachments.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4MgprHLfxvM/S3SqMR9PZiI/AAAAAAAAAj8/WCHPa4-63WI/s1600-h/ColdFusion9_FileAttachments_iText.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4MgprHLfxvM/S3SqMR9PZiI/AAAAAAAAAj8/WCHPa4-63WI/s320/ColdFusion9_FileAttachments_iText.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;On a closing note, if you are not up to date on your patches, be aware there are some relatively recent &lt;a href="http://blogs.adobe.com/psirt/2009/10/pre-notification_-_quarterly_s.html"&gt;security updates for both Adobe Reader and Acrobat&lt;/a&gt;, involving the Trust Manager. So if you have not checked your version recently, now might be a good time to do so! &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Complete Code&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!---&lt;br /&gt;    Create test PDF&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset inputFile = ExpandPath("myDocument.pdf") /&amp;gt;&lt;br /&gt;&amp;lt;cfdocument format="PDF" name="pdfContent"&amp;gt;&lt;br /&gt;    &amp;lt;cfdump var="#server.os#" label="Server O/S" /&amp;gt;&lt;br /&gt;&amp;lt;/cfdocument&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;    Add attachments to existing pdf&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;    try {&lt;br /&gt;        // Source/destination file paths&lt;br /&gt;        inputFile = ExpandPath("myDocument.pdf");&lt;br /&gt;        outputFile = ExpandPath("myDocumentWithAttachments.pdf");&lt;br /&gt;        &lt;br /&gt;        // Sample files to attach to pdf&lt;br /&gt;        attach1     = "c:/test/docs/NewsLetter-Feb-2010.doc";&lt;br /&gt;        attach2        = "c:/test/docs/Statistics-Jan-2010.xls";&lt;br /&gt;        attach3        = "c:/test/docs/test.txt";&lt;br /&gt;&lt;br /&gt;        // open source file and prepare for modification&lt;br /&gt;        reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init( inputFile );&lt;br /&gt;        outStream = createObject("java", "java.io.FileOutputStream").init( outputFile );&lt;br /&gt;        stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init( reader, outStream );&lt;br /&gt;&lt;br /&gt;        // create the first attachment from a file path&lt;br /&gt;        stamper.addFileAttachment("Newsletter for February", javacast("null", ""), attach1, "Newsletter.doc");&lt;br /&gt;&lt;br /&gt;        // create the second "dynamically" (ie from an array of bytes). &lt;br /&gt;        // deliberately leave the description blank&lt;br /&gt;        bytes = FileReadBinary(attach2);&lt;br /&gt;        stamper.addFileAttachment(javacast("null", ""), bytes, javacast("null", ""), "Statistics.xls");&lt;br /&gt;&lt;br /&gt;        // create the last attachment from a file path&lt;br /&gt;        stamper.addFileAttachment("Meaningless text file", javacast("null", ""), attach3, "Stuff.txt");&lt;br /&gt;&lt;br /&gt;        // display the attachment pane when the pdf opens (Since 1.6)  &lt;br /&gt;        writer = stamper.getWriter();&lt;br /&gt;        writer.setPdfVersion( writer.VERSION_1_6 );&lt;br /&gt;        stamper.setViewerPreferences( writer.PageModeUseAttachments );    &lt;br /&gt;            &lt;br /&gt;    }&lt;br /&gt;    finally {&lt;br /&gt;        // always cleanup objects&lt;br /&gt;        if (IsDefined("stamper")) {&lt;br /&gt;               stamper.close();&lt;br /&gt;        }&lt;br /&gt;          if (IsDefined("outStream")) {&lt;br /&gt;              outStream.close();&lt;br /&gt;          }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    WriteOutput("Output saved to file "&amp; outputFile);&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7083682542437997089?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7083682542437997089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7083682542437997089&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7083682542437997089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7083682542437997089'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-9-adding-document-level.html' title='ColdFusion 9: Adding Document Level Attachments to a PDF with iText'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4MgprHLfxvM/S3SqMR9PZiI/AAAAAAAAAj8/WCHPa4-63WI/s72-c/ColdFusion9_FileAttachments_iText.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1197502256030459358</id><published>2010-02-10T03:21:00.000-08:00</published><updated>2010-02-10T10:38:52.257-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 9: Yet Another Way to Refresh a Bound CFSELECT</title><content type='html'>One of the really nice features of CF8 and CF9 is bindings. But there are a few noticeable gaps, such as refreshing a bound CFSELECT list. From what I can tell, this still is not supported. Though apparently CF9 did introduce &lt;a href="http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfselect-bind-selected.html"&gt;support for the selected attribute&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;I spent some time pouring over the cfajax.js file, and had little more than a headache to show for my troubles. Then I came across a &lt;a href="http://cfsilence.com/blog/client/index.cfm/2007/10/22/Refreshing-A-Bound-CFSelect"&gt;slick suggestion&lt;/a&gt; in an older entry on Todd Sharp's blog. It mentioned the undocumented ColdFusion.Bind.assignValue method could be used to refresh the list.&amp;nbsp; It was perfect.&amp;nbsp; Exactly what I needed. &lt;br /&gt;&lt;br /&gt;Well... then I got to wondering if there might be something even simpler. (I know, I know. People are never satisfied).&amp;nbsp; After further review of cfajax.js, and lots of experimentation, I came across a nice one-liner that seems to work. Still undocumented unfortunately. But still pretty neat:&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;script language="javascript"&amp;gt;&lt;br /&gt;    ColdFusion.bindHandlerCache['yourElementID'].call();&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;... and what does this function do?&lt;/b&gt;&lt;br /&gt;If you generate a cfselect with a CFC bind, and view the source, you will see a call to a function named register(). Not surprisingly, the register() function seems to do all the work of creating the bindings and invoking the CFC to populate the select list.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S3KTLaK2qhI/AAAAAAAAAjs/mo-AldEExmI/s1600-h/ColdFusion9_CFFORM_Source_Bindings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S3KTLaK2qhI/AAAAAAAAAjs/mo-AldEExmI/s320/ColdFusion9_CFFORM_Source_Bindings.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;After taking a peak inside cfajax.js, I noticed the register() function creates a parameter-less function which handles invoking the CFC. (You can open up cfajax.js yourself if you want to view all the gory details.) But the key part is that CF stores this handler function in one of its cache objects. So you can easily grab a reference to it function just by passing in the id (or name) of your form element. Then simply invoke it using &lt;a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Function/call"&gt;call()&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Pretty cool stuff! It goes a long way towards alleviating my headache..&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4MgprHLfxvM/S3KTxa89U9I/AAAAAAAAAj0/IDIJDHkFLVQ/s1600-h/ColdFusion9_CFAjax_Source_Bindings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4MgprHLfxvM/S3KTxa89U9I/AAAAAAAAAj0/IDIJDHkFLVQ/s320/ColdFusion9_CFAjax_Source_Bindings.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1197502256030459358?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1197502256030459358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1197502256030459358&amp;isPopup=true' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1197502256030459358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1197502256030459358'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-9-yet-another-way-to-refresh.html' title='ColdFusion 9: Yet Another Way to Refresh a Bound CFSELECT'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/S3KTLaK2qhI/AAAAAAAAAjs/mo-AldEExmI/s72-c/ColdFusion9_CFFORM_Source_Bindings.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6125841944892427184</id><published>2010-02-09T02:40:00.000-08:00</published><updated>2010-02-09T02:44:06.575-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 9: CFSELECT + BIND + Selected Attribute Work Together Now?</title><content type='html'>In case you have been living under a rock like me, it seems the selected attribute works with bound cfselect lists.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;b&gt;Form&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfparam name="form.foodID" default="0"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfform method="post" action="#CGI.SCRIPT_NAME#"&amp;gt;&lt;br /&gt;    Favorite Food: &lt;br /&gt;                &amp;lt;cfselect name="foodID"&lt;br /&gt;                    value="foodID"&lt;br /&gt;                    display="FoodName"&lt;br /&gt;                    selected="#form.foodID#"&lt;br /&gt;                    bind="cfc:Food.getFood()"&lt;br /&gt;                    bindOnLoad="true"&lt;br /&gt;                /&amp;gt;&lt;br /&gt;    &amp;lt;cfinput type="submit" name="submitMe" /&amp;gt;&lt;br /&gt;&amp;lt;/cfform&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Food.cfc&lt;/b&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfcomponent output="false"&amp;gt;&lt;br /&gt;   &lt;br /&gt;   &amp;lt;cffunction name="getFood" access="remote" output="false" returntype="query"&amp;gt;&lt;br /&gt;      &amp;lt;cfset var q    = QueryNew("") /&amp;gt;&lt;br /&gt;      &amp;lt;cfset queryAddColumn(q, "FoodID", "integer", listToArray("0,1,2,3")) /&amp;gt;&lt;br /&gt;      &amp;lt;cfset queryAddColumn(q, "FoodName", "varchar", listToArray("-Pick Something-,Burger,Pizza,Lasagna")) /&amp;gt;&lt;br /&gt;      &amp;lt;cfreturn q /&amp;gt;      &lt;br /&gt;   &amp;lt;/cffunction&amp;gt;&lt;br /&gt;   &lt;br /&gt;&amp;lt;/cfcomponent&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6125841944892427184?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6125841944892427184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6125841944892427184&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6125841944892427184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6125841944892427184'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfselect-bind-selected.html' title='ColdFusion 9: CFSELECT + BIND + Selected Attribute Work Together Now?'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-4390211954534186275</id><published>2010-02-07T23:52:00.000-08:00</published><updated>2010-02-07T23:53:54.699-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 9: CFPDFFORM (A Tag With No Name ?)</title><content type='html'>A question about saving the output of cfpdfform to a variable came up on the adobe forums recently. As I have been doing some testing with CF9 + CFPDF this week, I suggested using the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;name&lt;/span&gt; attribute. Well I was a bit surprised when someone casually mentioned that cfpdfform does not &lt;i&gt;have &lt;/i&gt;a documented name attribute. Huh? &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Scratching my head I checked the documentation and sure enough &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;name&lt;/span&gt; was not one of the listed attributes. It is documented for cfpdf, but not cfpdfform. So I re-checked my code and the name attribute &lt;i&gt;did &lt;/i&gt;work in simple tests. &lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfpdfform action="populate" source="c:\MyForm.pdf" name="pdfData"&amp;gt;&lt;br /&gt;    &amp;lt;cfpdfformparam name="name" value="Mark McCallan"&amp;gt;&lt;br /&gt;    &amp;lt;cfpdfformparam name="address" value="926 Data Avenue"&amp;gt;&lt;br /&gt;&amp;lt;/cfpdfform&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfcontent type="application/pdf" variable="#ToBinary(pdfData)#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So I started to wonder if maybe it was just an omission in the documentation. I decided to try the highly unscientific method of using invalid attribute combinations. Just to see if the error messages would shed any light on the expected attributes. Granted it is probably not the most reliable indicator. But worth a shot. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately the messages for some combinations suggest "name" is valid&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4MgprHLfxvM/S2_As1d5iaI/AAAAAAAAAjU/ujp_gSS0_qk/s1600-h/ColdFusion_CFPDFFORM_Populate_NameAttributeError.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4MgprHLfxvM/S2_As1d5iaI/AAAAAAAAAjU/ujp_gSS0_qk/s320/ColdFusion_CFPDFFORM_Populate_NameAttributeError.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;While others seemed to side with the documentation.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_4MgprHLfxvM/S2_AzAkE1tI/AAAAAAAAAjc/k-9QIqZiQkc/s1600-h/ColdFusion_CFPDFFORM_Read_NameAttributeError.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_4MgprHLfxvM/S2_AzAkE1tI/AAAAAAAAAjc/k-9QIqZiQkc/s320/ColdFusion_CFPDFFORM_Read_NameAttributeError.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;A dump of the tag's class certainly seems to suggest support for a "name" attribute.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S2_A_BpGw9I/AAAAAAAAAjk/Zu7vZxKItVw/s1600-h/ColdFusion9_PDFFormTagClass.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S2_A_BpGw9I/AAAAAAAAAjk/Zu7vZxKItVw/s320/ColdFusion9_PDFFormTagClass.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I was leaning towards a fluke in the documentation. But then I noticed a few issues with a LiveCycle form that had special rights enabled. When the pdf opened, Acrobat complained that the document was modified and disabled the special features. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_4MgprHLfxvM/S2_AFqODi_I/AAAAAAAAAio/Bg92kkw_Hz8/s1600-h/ColdFusion_CFPDFFORM_NameAttribute_ModifiedError.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_4MgprHLfxvM/S2_AFqODi_I/AAAAAAAAAio/Bg92kkw_Hz8/s320/ColdFusion_CFPDFFORM_NameAttribute_ModifiedError.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So now I am thinking maybe it was not an omission in the documentation.  Anyone have the real scoop on the "name" attribute?&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-4390211954534186275?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/4390211954534186275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=4390211954534186275&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4390211954534186275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4390211954534186275'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/coldfusion-9-cfpdfform-tag-with-no-name.html' title='ColdFusion 9: CFPDFFORM (A Tag With No Name ?)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4MgprHLfxvM/S2_As1d5iaI/AAAAAAAAAjU/ujp_gSS0_qk/s72-c/ColdFusion_CFPDFFORM_Populate_NameAttributeError.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1237968954238877755</id><published>2010-02-04T14:33:00.000-08:00</published><updated>2010-02-04T17:25:05.010-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Form Field Values, Multipart Forms and Servlets (... oh my)</title><content type='html'>I saw an &lt;a href="http://stackoverflow.com/questions/2194442/getpagecontext-getrequest-getparametermap-with-multipart-forms"&gt;intriguing question&lt;/a&gt; on stackoverflow yesterday, by &lt;a href="http://rip747.wordpress.com/"&gt;Tony Petruzzi&lt;/a&gt; .&amp;nbsp; It was about parsing form field values, but with a bit of twist. We all know that when multiple form fields have the same name, the field values are returned as a comma delimited list in CF. While that is a handy feature at times, what do you do when the field values contain commas? Well after a few false starts, I did come up with one option, but wanted to describe it in a little more detail than stackoverflow comments allow.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt; Stealing from Tony's example, take the simple form below. Each of the two fields contains a different number of letters separated by a comma. But once the form is submitted, the value is just one big csv string. So you really have no way of determining which values were actually entered into each of the fields. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/S2tHK3BYULI/AAAAAAAAAiA/ux6kgQsOwZ4/s1600-h/ColdFusion_Form_ValuesWithCommas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_4MgprHLfxvM/S2tHK3BYULI/AAAAAAAAAiA/ux6kgQsOwZ4/s320/ColdFusion_Form_ValuesWithCommas.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Tony's post described a slick method of extracting the field values as a string array, with the help of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getPageContext()&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getParameterMap()&lt;/span&gt;. The problem was it does not seem to work when the enctype is multipart/form-data. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfdump var="#getPageContext().getRequest().getParameterMap()#"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;From what little I have read so far, my understanding of the issue is that the standard request object (ie HttpServletRequest) does not handle multipart requests.&amp;nbsp; A special multipart handler is needed instead. So with that in mind, my next question was what handler does CF use?&lt;br /&gt;&lt;br /&gt;Well, while poking around in the CF libraries a while back, I noticed CF uses some of the &lt;a href="http://www.servlets.com/cos/"&gt;O'Reilly servlet classes&lt;/a&gt;. In particular, the ones for MultiPartRequest handling. If you look at the API you will notice the classes return all sorts of good information like input field names, values, etcetera. So I figured that is probably what CF was using for the form and that this information had to be exposed ...somewhere.&lt;br /&gt;&lt;br /&gt;On a whim I decided to get back to basics and dump the FORM scope class. That revealed a promising method named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getPartsArray()&lt;/span&gt;. Looping through the array confirmed my suspicion that results were indeed one of the O'Reilly classes: &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;com.oreilly.servlet.multipart.ParamPart&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset formClass = createObject("java", form.getClass().name)&amp;gt;&lt;br /&gt;   &amp;lt;cfdump var="#formClass#" label="FORM Scope Class" /&amp;gt;&lt;br /&gt;   &lt;br /&gt;   &amp;lt;cfloop array="#form.getPartsArray()#" index="part"&amp;gt;&lt;br /&gt;      &amp;lt;cfdump var="#part#" label="Part Element" /&amp;gt;&lt;br /&gt;   &amp;lt;/cfloop&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/S2tIY_Hb44I/AAAAAAAAAiI/-YiVgjLGvLQ/s1600-h/ColdFusion_FormScope_GetPartsArray.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S2tIY_Hb44I/AAAAAAAAAiI/-YiVgjLGvLQ/s320/ColdFusion_FormScope_GetPartsArray.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;All that was left was to use a few methods from the API to the retrieve the form field information. First the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;isParamPart()&lt;/span&gt; method is used to identify the input fields only.  Then &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getName()&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;getStringValue()&lt;/span&gt; are used to grab the field's name and value.&amp;nbsp; As you can see, there is not much to it.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- if this is a multipart request ...---&amp;gt;&lt;br /&gt;   &amp;lt;cfset variables.parts = form.getPartsArray()&amp;gt;&lt;br /&gt;   &amp;lt;cfif structKeyExists(variables, "parts")&amp;gt;&lt;br /&gt;      &amp;lt;cfoutput&amp;gt;   &lt;br /&gt;      &amp;lt;cfloop array="#variables.parts#" index="p"&amp;gt;&lt;br /&gt;         &amp;lt;cfif p.isParam()&amp;gt;&lt;br /&gt;            isParam() = #p.isParam()#&lt;br /&gt;            getName() = #p.getName()#&lt;br /&gt;            stringValue() = #p.getStringValue()#&lt;br /&gt;         &amp;lt;/cfif&amp;gt;&lt;br /&gt;      &amp;lt;/cfloop&amp;gt;&lt;br /&gt;      &amp;lt;/cfoutput&amp;gt;&lt;br /&gt;   &amp;lt;/cfif&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course this only applies to multipart requests. The part array will be null for other request types. So make sure the array exists before using it. Anyway, I thought this was an interesting approach to the old form field dilemma. But if anyone knows of any other techniques, I would love to hear them.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1237968954238877755?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1237968954238877755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1237968954238877755&amp;isPopup=true' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1237968954238877755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1237968954238877755'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/02/form-field-values-multipart-forms-and.html' title='Form Field Values, Multipart Forms and Servlets (... oh my)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/S2tHK3BYULI/AAAAAAAAAiA/ux6kgQsOwZ4/s72-c/ColdFusion_Form_ValuesWithCommas.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-8400439298305008162</id><published>2010-01-16T10:58:00.000-08:00</published><updated>2010-01-16T18:27:30.154-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iText'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion + iText 5.0.0 (Good things come in *new* packages)</title><content type='html'>In case you were unaware, &lt;a href="http://itextpdf.com/"&gt;iText 5.0.0&lt;/a&gt; was released a short while ago, and a new iText book scheduled for release in June. The new version of iText contains some significant changes, including &lt;a href="http://itextpdf.com/terms-of-use/index.php?page=AGPL"&gt;a new license&lt;/a&gt;. But to ColdFusion users, the most signficant change may be the new package name.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Most everyone knows ColdFusion uses an older version of iText internally. So upgrading to a newer version (without breaking ColdFusion) requires a little fancy foot-work, such as using a custom class loader like &lt;a href="http://javaloader.riaforge.org/"&gt;JavaLoader.cfc&lt;/a&gt;. But with the new package name, that has all changed.&lt;br /&gt;&lt;br /&gt;In previous versions, iText classes were packaged under &lt;span style="font-family:courier new;"&gt;com.lowagie.*&lt;/span&gt; . As of version 5.0.0, the classes are now packaged under a new name: &lt;span style="font-family:courier new;"&gt;com.itextpdf.*&lt;/span&gt;. This change is a huge benefit to ColdFusion users because it eliminates class path compatibility issues with MX7, CF8 and CF9. The new iText version should happily co-exist with the older iText versions shipped with MX7, CF8 and CF9.&lt;br /&gt;&lt;br /&gt;Now obviously using version 5.0.0 means changing code to use the new package name, and being careful not to mix old and new. But it is now easier than ever before to use the latest version of iText under ColdFusion.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-8400439298305008162?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/8400439298305008162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=8400439298305008162&amp;isPopup=true' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8400439298305008162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8400439298305008162'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/01/coldfusion-itext-500-good-things-come.html' title='ColdFusion + iText 5.0.0 (Good things come in *new* packages)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7191619072574052982</id><published>2010-01-15T01:24:00.000-08:00</published><updated>2010-11-21T12:13:42.873-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZXing'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>How to Install ZXing in Eclipse (JavaSE Component Only)</title><content type='html'>&lt;div class="update"&gt;&lt;b&gt;Update&lt;/b&gt;: Apparently I had a serious concussion when I wrote this, as I completely overlooked the obvious. &lt;i&gt;"Hello, McFly - svn? I hear Google code has it too."&lt;/i&gt;  So do not bother using these instructions. It is much simpler pull the project from SVN. &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;When I researched the &lt;a href="http://cfsearching.blogspot.com/2009/11/seeing-stripes-experiment-with-zxing.html"&gt;JavaSE component of ZXing&lt;/a&gt;, I compiled the jars I needed with Eclipse 3.4.1 . The set up was relatively simple. But there were several steps needed to get everything up and running properly. So I decided to write up a quick set of instructions. &lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note&lt;/span&gt;:   &lt;a href="http://code.google.com/p/zxing/"&gt;ZXing&lt;/a&gt; contains several components (javase, javame, servlet, android, etcetera). These instructions &lt;span style="font-weight: bold;"&gt;only &lt;/span&gt;cover the JavaSE component.  You may notice I imported the full source.  But to actually use the other components in the project, additional files are needed.  For further instructions see the project's &lt;a href="http://code.google.com/p/zxing/wiki/GettingStarted"&gt;Getting Started&lt;/a&gt; section&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Instructions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;1.     Download the latest source and extract the files.&lt;br /&gt;As of this entry, the current version is ZXing-1.4.zip. (Your version may differ.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2.   Create a new project in Eclipse.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Use whatever you project name you wish. Example: "ZXing"&lt;/li&gt;&lt;li&gt;  Make sure the project JVM is 1.5 or higher&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;3.     Import the source files into the project&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;       Select File =&amp;gt; Import =&amp;gt; File System =&amp;gt; Next&lt;/li&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/S1A3vK8FeAI/AAAAAAAAAhY/QEPnrBPpFOA/s1600-h/ZXing_Eclipse_Import_FileSystem.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 274px; height: 320px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S1A3vK8FeAI/AAAAAAAAAhY/QEPnrBPpFOA/s320/ZXing_Eclipse_Import_FileSystem.png" alt="" id="BLOGGER_PHOTO_ID_5426898834511198210" border="0" /&gt;&lt;/a&gt;&lt;li&gt; Supply the source and destination&lt;/li&gt;&lt;blockquote&gt;1. Navigate to the extracted files and select the ZXing-1.4 &lt;span style="font-style: italic;"&gt;subfolder&lt;/span&gt; . 2. In the main window,   check the ZXing-1.4 folder, so its contents are imported 3. Select the &lt;span style="font-style: italic;"&gt;top level&lt;/span&gt; folder of your project (&lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; "src")  for &lt;span style="font-family:courier new;"&gt;Into Folder&lt;/span&gt; &lt;/blockquote&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/S1A3vdk0p6I/AAAAAAAAAhg/KiRsgG7Zzqc/s1600-h/ZXing_Eclipse_ImportSourceFiles.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 296px; height: 320px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/S1A3vdk0p6I/AAAAAAAAAhg/KiRsgG7Zzqc/s320/ZXing_Eclipse_ImportSourceFiles.png" alt="" id="BLOGGER_PHOTO_ID_5426898839513900962" border="0" /&gt;&lt;/a&gt; &lt;/ul&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Make sure &lt;span style="font-family:courier new;"&gt;Create selected folders only&lt;/span&gt; is selected&lt;/li&gt;&lt;li&gt;Finally, click &lt;span style="font-family:courier new;"&gt;Finish&lt;/span&gt; to import the files into the project&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;4.       Next Configure the Build Path&lt;br /&gt;&lt;br /&gt;After the source files are imported, you need to configure the project build path. Each sub-component in ZXing has its own separate &lt;span style="font-family:courier new;"&gt;src&lt;/span&gt; folder. Each of them must be added to the build path.  ZXing also has a few jar dependencies. Those jars must be added to the project build path as well.&lt;br /&gt;&lt;br /&gt;You could modify the path using Eclipse's "Configure Build Path" option.  But a shortcut&lt;br /&gt;is to modify the project's .classpath file manually.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Find and open the project's .classpath file &lt;/li&gt;&lt;li&gt;Paste in the new class path entries below and save the file.&lt;/li&gt;&lt;li&gt;Close and re-open the project in Eclipse to apply the changes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;New Class Path Entries&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;classpathentry kind="src" path="android/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="bug/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="core/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="core/test/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="javame/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="javase/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="rim/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="src" path="zxingorg/src"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="bug/lib/osgi.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="core/lib/junit.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/BarcodeReader.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/basic/BarcodeReader.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/commons-codec-1.3.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/commons-fileupload-1.2.1.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/commons-io-1.4.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/commons-lang-2.4.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/commons-logging-api-1.1.1.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/httpclient-4.0.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/httpcore-4.0.1.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/httpcore-nio-4.0.1.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/httpmime-4.0.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/mailapi.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/pop3.jar"/&amp;gt;&lt;br /&gt;&amp;lt;classpathentry kind="lib" path="zxingorg/web/WEB-INF/lib/smtp.jar"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center; font-style: italic;"&gt;&lt;span style="font-size:85%;"&gt;.ClassPath File&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_4MgprHLfxvM/S1A3vnJVNzI/AAAAAAAAAho/CGLvtGElYn0/s1600-h/ZXing_Eclipse_ClasspathFile.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 196px;" src="http://2.bp.blogspot.com/_4MgprHLfxvM/S1A3vnJVNzI/AAAAAAAAAho/CGLvtGElYn0/s320/ZXing_Eclipse_ClasspathFile.png" alt="" id="BLOGGER_PHOTO_ID_5426898842082948914" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center; font-style: italic;"&gt;&lt;span style="font-size:85%;"&gt;.ClassPath File Contents&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_4MgprHLfxvM/S1A62aD_ObI/AAAAAAAAAh4/v8BWsablYeo/s1600-h/ZXing_Eclipse_Classpath.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 274px;" src="http://3.bp.blogspot.com/_4MgprHLfxvM/S1A62aD_ObI/AAAAAAAAAh4/v8BWsablYeo/s320/ZXing_Eclipse_Classpath.png" alt="" id="BLOGGER_PHOTO_ID_5426902257364842930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You should now be able to run both the &lt;span style="font-family:courier new;"&gt;core&lt;/span&gt; an &lt;span style="font-family:courier new;"&gt;javase&lt;/span&gt; components of the project from Eclipse&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Building Jars&lt;/span&gt;&lt;br /&gt;The project includes several &lt;a href="http://ant.apache.org/"&gt;ant&lt;/a&gt; build files to simplify the process of building jars.  Again, each component subfolder contains its own separate build file.  So you can easily build jars individually. Simply locate the build.xml file for the desired component. Then run the &lt;span style="font-family:courier new;"&gt;build&lt;/span&gt; task to generate the jar.&lt;br /&gt;&lt;br /&gt;Example: To build the JavaSE Jar&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Locate the javase/build.xml file&lt;/li&gt;&lt;li&gt;Run the &lt;span style="font-family:courier new;"&gt;build&lt;/span&gt; task in ant&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Ant will generate a &lt;span style="font-family:courier new;"&gt;javase.jar&lt;/span&gt; file inside the &lt;span style="font-family:courier new;"&gt;javase/&lt;/span&gt; folder&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7191619072574052982?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7191619072574052982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7191619072574052982&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7191619072574052982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7191619072574052982'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/01/how-to-install-zxing-in-eclipse-javase.html' title='How to Install ZXing in Eclipse (JavaSE Component Only)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/S1A3vK8FeAI/AAAAAAAAAhY/QEPnrBPpFOA/s72-c/ZXing_Eclipse_Import_FileSystem.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-4722412159377362219</id><published>2010-01-14T20:26:00.000-08:00</published><updated>2010-01-14T20:32:28.451-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Humor'/><title type='text'>OT:  Anguished English</title><content type='html'>I came across this book today and it gave me quite a chuckle.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://books.google.com/books?id=y2-YPs29zVwC&amp;amp;lpg=PP1&amp;amp;ots=3sjwgXCjdz&amp;amp;dq=Richard%20Lederer%27s%20Anguished%20English&amp;amp;pg=PA108#v=onepage&amp;amp;q=&amp;amp;f=false"&gt;&lt;span style="font-weight: bold;"&gt;Anguished English&lt;/span&gt;&lt;/a&gt;: &lt;span style="font-style: italic;"&gt;An Anthology of Accidental Assaults Upon the English Language&lt;/span&gt;&lt;br /&gt;&lt;iframe style="border: 0px none;" src="http://books.google.com/books?id=y2-YPs29zVwC&amp;amp;lpg=PP1&amp;amp;ots=3sjwgXCjdz&amp;amp;dq=Richard%20Lederer%27s%20Anguished%20English&amp;amp;pg=PA108&amp;amp;output=embed" frameborder="0" height="500" scrolling="no" width="500"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-4722412159377362219?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/4722412159377362219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=4722412159377362219&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4722412159377362219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/4722412159377362219'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/01/ot-anguished-english.html' title='OT:  Anguished English'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7652053584665739046</id><published>2010-01-13T22:12:00.000-08:00</published><updated>2010-01-13T22:17:33.252-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Dance of the Dueling Class Loaders Discussion</title><content type='html'>If you have ever had the misfortune of witnessing a performance of the highly un-entertaining Dance of the Dueling Class Loaders (a.k.a. Jar Hell), there is an interesting thread by Fred Roeber over at javaLoader-dev:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://groups.google.com/group/javaloader-dev/browse_thread/thread/1862f81118045726"&gt;Solving the "JAR hell" issue with different 3rd party JAR files&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7652053584665739046?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7652053584665739046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7652053584665739046&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7652053584665739046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7652053584665739046'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/01/dance-of-dueling-class-loaders.html' title='Dance of the Dueling Class Loaders Discussion'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1871475122958435033</id><published>2010-01-07T14:19:00.000-08:00</published><updated>2010-01-07T15:14:44.020-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>All I wanted for Christmas was a CFSCRIPT FOR .. IN LOOP (For Arrays)</title><content type='html'>Okay, so Christmas is past and CF9 is long out of the beta stage. But my tiny wish remains. The reasonable part of me says, "It is really not that hard to construct an alternative". Especially with all the enhancements in CF8 and CF9.  It comes much closer to perfection than in any previous versions. &lt;span id="fullpost"&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;for (x = 1; x &amp;lt;= arrayLen(myArray); x++)&lt;br /&gt;{&lt;br /&gt;  WriteOutput(myArray[x] &amp;amp;"&amp;lt;hr /&amp;gt;");&lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;But there is something classic and elegant about a &lt;span style="font-family:courier new;"&gt;for in&lt;/span&gt; loop. Simple, intuitive and just downright beautiful code.   If it were any more beautiful, I just might break down and cry.  {Sigh} If only it worked. If only ...&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;for (x in myArray)&lt;br /&gt;{&lt;br /&gt;    WriteOutput(x &amp;amp;"&amp;lt;hr /&amp;gt;");&lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;span id="fullpost"&gt;&amp;lt;childishWhine&amp;gt;&lt;br /&gt;&lt;/span&gt;&lt;span id="fullpost"&gt;       All the &lt;span style="font-weight: bold;"&gt;other &lt;/span&gt;languages have it? Why can't we? &lt;/span&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&amp;lt;/childishWhine&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span id="fullpost"&gt;;)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1871475122958435033?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1871475122958435033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1871475122958435033&amp;isPopup=true' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1871475122958435033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1871475122958435033'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/01/all-i-wanted-for-christmas-was-cfscript.html' title='All I wanted for Christmas was a CFSCRIPT FOR .. IN LOOP (For Arrays)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7113645887307026953</id><published>2010-01-03T20:19:00.000-08:00</published><updated>2010-01-09T20:15:42.564-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Databases'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CFQueryparam Matrix  for MySQL 5</title><content type='html'>&lt;div style="text-align: left;"&gt;As I predominately use MS SQL, I frequently end up having to search for the correct cfsqltypes when using cfqueryparam and MySQL. While I am sure there is an unofficial matrix out there somewhere, I never manage to find it when I need it.  So I decided to create my own as a point of reference. &lt;/div&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Not being an MySQL guru, I spent some time reviewing the MySQL 5.0 manual and the JDBC references to get a better understanding of the data types and limits, both in MySQL and Java. First the matrix and then I will explain some of the decisions behind it.  The matrix should be pretty accurate. But corrections are always welcome.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;Note: &lt;/span&gt;&lt;span style="font-size:85%;"&gt;The mappings are based on tests with CF9, MySQL 5.1.42 and Connector/J 5.1.7.  There are some &lt;span style="font-weight: bold;"&gt;significant differences&lt;/span&gt; in the various versions of MySQL and Connector/J drivers. So if you are using different versions, your mileage may vary.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;table class="summary"&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th class="summaryHead"&gt;ColdFusion 9&lt;br /&gt;&lt;/th&gt;&lt;th class="summaryHead"&gt;MySQL 5.1.42&lt;br /&gt;Connector/J 5.1.7&lt;br /&gt;&lt;/th&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_ARRAY&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_BIGINT&lt;/td&gt;&lt;td class="summary"&gt;bigint (signed), &lt;span class="note"&gt;int (unsigned)&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_BINARY&lt;/td&gt;&lt;td class="summary"&gt;binary,tinyblob&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_BIT&lt;/td&gt;&lt;td class="summary"&gt;bit, bool&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_BLOB&lt;/td&gt;&lt;td class="summary"&gt;blob&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_CHAR&lt;/td&gt;&lt;td class="summary"&gt;char&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_CLOB&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_DATE&lt;/td&gt;&lt;td class="summary"&gt;date&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_DECIMAL&lt;/td&gt;&lt;td class="summary"&gt;decimal&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_DISTINCT&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_DOUBLE&lt;/td&gt;&lt;td class="summary"&gt;double, double precision, real&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_FLOAT&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_IDSTAMP&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_INTEGER&lt;/td&gt;&lt;td class="summary"&gt;mediumint (signed and unsigned), int (signed)&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_LONGVARBINARY&lt;/td&gt;&lt;td class="summary"&gt;mediumblob,longblob,tinyblob&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_LONGVARCHAR&lt;/td&gt;&lt;td class="summary"&gt;text,mediumtext,longtext&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_MONEY&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_MONEY4&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_NULL&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_NUMERIC&lt;/td&gt;&lt;td class="summary"&gt;numeric, &lt;span class="iffy"&gt;bigint(unsigned)&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_OTHER&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_REAL&lt;/td&gt;&lt;td class="summary"&gt;float&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_REFCURSOR&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_SMALLINT&lt;/td&gt;&lt;td class="summary"&gt;smallint (signed or unsigned), &lt;span class="note"&gt;tinyint (signed)&lt;/span&gt; &lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_STRUCT&lt;/td&gt;&lt;td class="summary"&gt;-&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_TIME&lt;/td&gt;&lt;td class="summary"&gt;&lt;span class="iffy"&gt;**&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_TIMESTAMP&lt;/td&gt;&lt;td class="summary"&gt;datetime,timestamp&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_TINYINT&lt;/td&gt;&lt;td class="summary"&gt;tinyint (unsigned)&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_VARBINARY&lt;/td&gt;&lt;td class="summary"&gt;varbinary&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td class="summary"&gt;CF_SQL_VARCHAR&lt;/td&gt;&lt;td class="summary"&gt;varchar, tinytext, enum, set&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;Data Types 101&lt;/span&gt;&lt;br /&gt;Since cfsqltypes are essentially a wrapper of &lt;a href="http://java.sun.com/javase/6/docs/api/java/sql/Types.html"&gt;java.sql.Types&lt;/a&gt;, I started with the MySQL documentation on &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/connector-j-reference-type-conversions.html"&gt;Java, JDBC and MySQL Types&lt;/a&gt; and worked from there.  The mappings were not always as straight-forward as I expected. In particular the mappings of the numeric data types.&lt;br /&gt;&lt;br /&gt;In MySQL the range of allowed values can vary depending on whether the column is signed or unsigned. So unlike MS SQL,  more than one cfsqltype was required to represent all possible values for certain types.&lt;br /&gt;&lt;br /&gt;The MySQL &lt;span style="font-family:courier new;"&gt;INT&lt;/span&gt; type is a prime example.  If the &lt;span style="font-family:courier new;"&gt;INT &lt;/span&gt;is signed, the range of allowed values is -2147483648 through 2147483647. For an unsigned &lt;span style="font-family:courier new;"&gt;INT,&lt;/span&gt;the range is 0 through 4294967295.  Why does this matter? As with most things in CF, it relates back to java.&lt;br /&gt;&lt;br /&gt;When you use &lt;span style="font-family:courier new;"&gt;CF_SQL_INTEGER&lt;/span&gt; you are using the java sql type INTEGER which "represents a 32-bit signed integer value ranging between -2147483648 and 2147483647".  So obviously it does not have the capacity to represent the upper ranges of an unsigned &lt;span style="font-family:courier new;"&gt;INT.&lt;/span&gt; For values larger than 2147483647 you would need to use &lt;span style="font-family:courier new;"&gt;CF_SQL_BIGINT&lt;/span&gt; instead.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Decisions, Decisions ..&lt;/span&gt;&lt;br /&gt;So why not just use &lt;span style="font-family:courier new;"&gt;CF_SQL_BIGINT &lt;/span&gt; for both types? Well, technically you could. But then you lose out on cfqueryparam's built in validation for signed &lt;span style="font-family:courier new;"&gt;INT&lt;/span&gt;'s.   That is one of the reasons I decided to use separate cfsqltypes for signed and unsigned numbers.  Another reason is that the mappings are more intuitive this way, and more closely aligned with the standards (in my opinion).  So you get the benefits of as much validation as possible, while using the smallest sql type necessary.  Here is a quick breakdown of the various types and allowed ranges.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TINYINT&lt;/span&gt;&lt;br /&gt;ColdFusion enforces the standard range: 0 to 255&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_SMALLINT&lt;/span&gt;  - Signed columns (Min: -128 / Max: 127)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_TINYINT&lt;/span&gt; - UnSigned columns (Min: 0 / Max: 255)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;SMALLINT&lt;/span&gt;&lt;br /&gt;ColdFusion does not stricly enforce the standard range: -32768 to 32767.&lt;br /&gt;So you can use a single type for both signed and unsigned columns.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_SMALLINT&lt;/span&gt; -  Signed  (Min: -32768 / Max: 32767)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_SMALLINT&lt;/span&gt; -  Unsigned (Min: 0 / Max: 65535)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MEDIUMINT  &lt;/span&gt;&lt;br /&gt;This seems to be a non standard size.The closest mapping is INTEGER&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_INTEGER&lt;/span&gt; -  Signed  (Min: -8388608 / Max: 8388607)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_INTEGER &lt;/span&gt;-  Unsigned (Min: 0 / Max: 16777215)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;INT&lt;/span&gt;&lt;br /&gt;ColdFusion enforces the standard range: -2147483648 to 2147483647.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_INTEGER&lt;/span&gt; -  Signed  (Min: -2147483648 / Max: 2147483647)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_BIGINT&lt;/span&gt; -  Unsigned (Min: 0 / Max: 4294967295)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;BIGINT&lt;/span&gt;&lt;br /&gt;ColdFusion enforces the standard range: -9223372036854775808 to 9223372036854775807. I decided to use CF_SQL_NUMERIC (with a scale of 0), for unsigned values. Though CF_SQL_DECIMAL would probably work as well.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_BIGINT&lt;/span&gt; -  Signed  (Min: -9223372036854775808 / Max: 9223372036854775807)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_NUMERIC&lt;/span&gt; -  Unsigned (Min: 0 / Max: 18446744073709551615)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;" id="fullpost"&gt;Tonight at Comedy Central: &lt;/span&gt;&lt;span id="fullpost"&gt;&lt;span style="font-weight: bold;"&gt;Aproximate Numeric Types&lt;/span&gt;&lt;br /&gt;Suffice it to say the collective documentation on approximate numeric types is a bit like a &lt;a href="http://en.wikipedia.org/wiki/Who%27s_on_First%3F"&gt;Who's on First routine&lt;/a&gt;.  From everything I have read, the relationship between the java sql types and the MySQL data types is as follows:  A REAL is a MySQL FLOAT, a DOUBLE is a MySQL REAL, and a FLOAT is .. well none of the MySQL data types corresponds to a java FLOAT.  Are you with me so far? No? Good. Why should I be the only one with a headache.&lt;br /&gt;&lt;br /&gt;The confusion is due in part to what some of the older java api's charmingly call "&lt;span style="font-style: italic;"&gt;a possibly misguided attempt at consistency with previous database APIs&lt;/span&gt;" (in relation to the FLOAT type).  Now throw in the fact that same terms have different meanings, depending on the context, and things get even murkier.&lt;br /&gt;&lt;br /&gt;Conceptually, the easiest way to think of it is that approximate numbers fall into two categories:  single and double precision.  To trivialize the differences, both types can store large floating point numbers. But as the names imply, double precision can represent larger numbers than single precision.  Pretty simple, right?&lt;br /&gt;&lt;br /&gt;Unfortunately, from  everything I have read, the mappings between java.sql.Types and MySQL data types are not nearly that logical.  In fact they almost seem reversed.  The java.sql.Types use REAL to represent single precision and FLOAT/DOUBLE to represent double precision numbers. Whereas MySQL uses FLOAT for single precision and REAL/DOUBLE for double precision numbers.  See what I mean?&lt;br /&gt;&lt;br /&gt;So why am I explaining all this? (Just to torture you.)  But seriously, in part to explain why the cfqueryparam mappings for these types are likely different than what you expected. Also, to explain why I avoided any use of CF_SQL_FLOAT.   The java api's apologetically  mention the &lt;a href="http://java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/mapping.html"&gt;sql type FLOAT is often a  source of confusion&lt;/a&gt;.  The recommendation is that you &lt;span style="font-weight: bold;"&gt;not &lt;/span&gt;use  this type, but use DOUBLE instead. FLOAT and DOUBLE are equivalent.  (After reading the documentation, I wholeheartedly concur).&lt;br /&gt;&lt;br /&gt;So without further ado, here are the mappings for the approximate types:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;FLOAT    &lt;/span&gt;&lt;br /&gt;ColdFusion enforces the standard range: -3.40282347E+38F to 3.40282347E+38F. Note: All ranges are approximate and may not be exact.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_REAL&lt;/span&gt; - Signed (Min: -3.40282347E+38F / Max: 3.40282347E+38F)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_REAL&lt;/span&gt; - Unsigned (Min: 0 / Max: 3.40282347E+38F)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;DOUBLE, DOUBLE PRECISION, REAL (Synonyn for DOUBLE)&lt;/span&gt;&lt;br /&gt;ColdFusion enforces the standard range: -1.79E+308 to 1.79E+308. Note: All ranges are approximate and may not be exact.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_DOUBLE &lt;/span&gt;- Signed (Min: -1.79E+308 / Max: 1.79E+308)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CF_SQL_&lt;/span&gt;&lt;/span&gt;&lt;span id="fullpost"  style="font-family:courier new;"&gt;DOUBLE&lt;/span&gt;&lt;span id="fullpost"&gt; - Unsigned (Min: 0 / Max: 1.79E+308)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Open Questions&lt;br /&gt;&lt;/span&gt;The one data type I could not figure out how to properly map was &lt;span style="font-family:courier new;"&gt;time&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;.  &lt;/span&gt;At least not easily.  From a few cursory searches it seems problematic. As I do not make much use of this data type anyway, I decided not investigate it further. If anyone has figured out the correct mapping for this type, feel free to enlighten me.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final Conclusions:   Does the CFSQLType Really Matter?&lt;/span&gt;&lt;br /&gt;As you can see from the list of types and ranges above there is some definite overlapping. For example, the number 126 could be  submitted using &lt;span style="font-family:courier new;"&gt;CF_SQL_SMALLINT&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;CF_SQL_INTEGER&lt;/span&gt; or even &lt;span style="font-family:courier new;"&gt;CF_SQL_BIGINT&lt;/span&gt;.  Obviously the latter two would be overkill  for a &lt;span style="font-family:courier new;"&gt;TinyInt&lt;/span&gt; column. But since all of  them work, does the type really matter?&lt;br /&gt;&lt;br /&gt;Yes.  Obviously the type must have the capacity to store the  value you are submitting.  If it is too small, the query may fail or  the value may be truncated.  But even if you select a type that has  ample capacity to store your value, that value may be too large or  invalid for your target column. So selecting the correct cfsqltype gives  you an extra layer of validation in CF, before the SQL is ever  submitted to the database. Finally, the selected type should interpret  the value correctly according to the target column.  To use an ridiculous example, you could  insert the number zero (0)  into a VARCHAR column, using &lt;span style="font-family:courier new;"&gt;CF_SQL_DATE&lt;/span&gt;. Technically, it  will work. But the value actually inserted into the database would not be zero (0).  So selecting the proper cfsqltype for each column does matter.&lt;br /&gt;&lt;br /&gt;As always, comments and corrections are welcome.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7113645887307026953?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7113645887307026953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7113645887307026953&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7113645887307026953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7113645887307026953'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2010/01/cfqueryparam-matrix-for-mysql-5.html' title='CFQueryparam Matrix  for MySQL 5'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-8006813547942352836</id><published>2009-12-24T09:56:00.000-08:00</published><updated>2009-12-24T10:27:55.730-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CF9: One Difference Between the New Ternary Operator and IIF()</title><content type='html'>When I first saw the ternary operator in java, I confess I did not like it. To my way of thinking, it was odd and cryptic, and I did not see the advantage over a standard if/else statement. Well, I have come a long way.  For simple comparisons I now prefer its sleeker syntax over the more bulky if/else construct.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;So it was quite pleasing to see the ternary introduced in ColdFusion 9. I never much cared for the IIF() function. (Too reminiscent of MS Access I suppose)  But stylistic preferences aside, I just noticed the behavior of the ternary operator differs from IIF() in another sense. It uses delayed evaluation.&lt;br /&gt;&lt;br /&gt;Take this silly example. When &lt;span style="font-family: courier new;"&gt;someCondition &lt;/span&gt;is true, only the variable &lt;span style="font-family: courier new;"&gt;foo&lt;/span&gt; is defined. &lt;pre name="code" class="xhtml"&gt;   &amp;lt;cfset someCondition = true /&amp;gt;&lt;br /&gt;  &amp;lt;cfif someCondition&amp;gt;&lt;br /&gt;     &amp;lt;cfset foo = 123&amp;gt;&lt;br /&gt;  &amp;lt;cfelse&amp;gt;&lt;br /&gt;     &amp;lt;cfset foo = 321&amp;gt;&lt;br /&gt;     &amp;lt;cfset bar = 88&amp;gt;&lt;br /&gt;  &amp;lt;/cfif&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you are using the new ternary operator, a statement like the one below would succeed. It does not matter that the variable &lt;span style="font-family: courier new;"&gt;bar &lt;/span&gt;is not defined. Because the second variable is only evaluated when &lt;span style="font-family: courier new;"&gt;someCondition&lt;/span&gt; is &lt;span style="font-style: italic;"&gt;false&lt;/span&gt;.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt; &lt;br /&gt;  &amp;lt;cfset result = someCondition ? foo : bar /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, using IIF(), both variables are evaluated immediately, whether they are used or not.  So this code would result in an error: "variable BAR is undefined"&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt; &lt;br /&gt;  &amp;lt;cfset result = IIF(someCondition, foo, bar) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;To avoid the error you would need to use the DE() function, which just feels awkward to me.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt; &amp;lt;cfset result = IIF(someCondition, foo, DE("bar")) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So in this sense at least, the ternary operator is a bit smarter than the old IIF() function.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-8006813547942352836?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/8006813547942352836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=8006813547942352836&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8006813547942352836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8006813547942352836'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/cf9-one-difference-between-new-ternary.html' title='CF9: One Difference Between the New Ternary Operator and IIF()'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1984641420263482496</id><published>2009-12-23T13:22:00.000-08:00</published><updated>2009-12-23T16:58:12.841-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>Merry Christmas To All</title><content type='html'>I just wanted wish everyone in the CF community a Merry Christmas. I hope you all have a wonderful holiday. See you next year!&lt;br /&gt;&lt;br /&gt;(My favorite holiday tune)&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/OATi34PKNPw&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/OATi34PKNPw&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.noradsanta.org/en/whytrack.html"&gt;Why NORAD Tracks Santa&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1984641420263482496?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1984641420263482496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1984641420263482496&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1984641420263482496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1984641420263482496'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/merry-christmas-to-all.html' title='Merry Christmas To All'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7315964791656453866</id><published>2009-12-22T03:01:00.000-08:00</published><updated>2009-12-22T05:14:13.040-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Wrap and Scale Text (The Ghost of Code Past)</title><content type='html'>A long time ago, I wrote a cfc for wrapping and scaling image text to fit within a given set of dimensions. I always thought it was something better done in java. Well, I finally got around to creating a java version, and it is a lot simpler to use.  I also improved the algorithm used to auto-scale the text, and may write up an entry on that later. Plus I finally added support for line breaks (left-to-right text only).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_4MgprHLfxvM/SzCoR0DfApI/AAAAAAAAAeU/bKAgVSCX2z0/s1600-h/ColdFusion_WrapImageText.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 190px;" src="http://1.bp.blogspot.com/_4MgprHLfxvM/SzCoR0DfApI/AAAAAAAAAeU/bKAgVSCX2z0/s320/ColdFusion_WrapImageText.png" alt="" id="BLOGGER_PHOTO_ID_5418015375711208082" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:130%;" &gt;Options:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;b&gt;Alignment&lt;/b&gt;:  Supports left, right or center alignment&lt;br /&gt;&lt;b&gt;Antialiasing&lt;/b&gt;:  Enable or disable text anti-aliasing&lt;br /&gt;&lt;b&gt;AutoScale&lt;/b&gt;:  Enlarge or reduce text size to best fit the text within the given area&lt;br /&gt;&lt;b&gt;DrawText&lt;/b&gt;:  Enable or disable text drawing (Could be used for measuring only)&lt;br /&gt;&lt;b&gt;Font&lt;/b&gt;:  Supports custom font name, style or size&lt;br /&gt;&lt;b&gt;Color&lt;/b&gt;:  Supports custom text color&lt;br /&gt;&lt;b&gt;Ignore Margin&lt;/b&gt;: &lt;span style="font-style: italic;"&gt;(Experimental) &lt;/span&gt;Ignores top and bottom padding on first/last line of text for a better text fit&lt;br /&gt;&lt;b&gt;Increment&lt;/b&gt;:  Supports fractional font sizes and custom incrementing&lt;br /&gt;&lt;br /&gt;It works very well for small to moderate amounts of text.  Out of curiosity, I did test it with about 62,000 characters.  (Crazy, I know).  While it did work, it took a while.  So if you are thinking of trying to calculate the font size needed to print War and Peace on a matchbook cover, think again.  It is just not designed for that kind of volume.&lt;br /&gt;&lt;br /&gt;Anyway, I tried to make the library as flexible as possible.  So for example, you could wrap text without auto-scaling.  You could also get the measurements of the wrapped text without actually drawing it onto your image.  (I am not sure there is a need for this. But if you wanted to do it, you could!).&lt;br /&gt;&lt;br /&gt;Next up, I am thinking of wrapped text with mixed styles (...I do love a challenge)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="text-align: center;"&gt;&lt;span id="fullpost"&gt;&lt;a href="http://www.box.net/shared/1d9s3qsx9n"&gt;Source: wrapImageText-0.1a.zip&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;br /&gt;   &lt;b&gt;Update 2009-12-22:&lt;/b&gt; Fixed wrong file version in source&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7315964791656453866?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7315964791656453866/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7315964791656453866&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7315964791656453866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7315964791656453866'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/wrap-and-scale-text-ghost-of-code-past.html' title='Wrap and Scale Text (The Ghost of Code Past)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/SzCoR0DfApI/AAAAAAAAAeU/bKAgVSCX2z0/s72-c/ColdFusion_WrapImageText.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2914938287006075547</id><published>2009-12-16T21:45:00.000-08:00</published><updated>2009-12-17T14:41:10.801-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tomcat'/><category scheme='http://www.blogger.com/atom/ns#' term='Apache'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion + Tomcat + Apache + Windows (Take the plunge)</title><content type='html'>For a while now I have wanted to experiment with other CF engines. But kept putting it off for various reasons. Well, this weekend I decided to take the plunge. My first attempt was using CF9's multi-server install with JRUN which met with only partial success. For whatever reason I was never able to get the Open BlueDragon WAR file to deploy correctly under JRUN.&lt;br /&gt;&lt;br /&gt;Thanks to a suggestion from &lt;a href="http://blog.maestropublishing.com/"&gt;Peter J. Farrell&lt;/a&gt;, I decided to try using Tomcat instead. Surprisingly, it was very simple to setup. I followed some excellent posts by &lt;a href="http://www.web-rat.com/blog/post.cfm/installing-railo-on-tomcat-the-windows-edition"&gt;Todd Rafferty&lt;/a&gt; and &lt;a href="http://mattwoodward.com/blog/index.cfm?event=showEntry&amp;entryId=03233F6F-ED2C-43C7-AFF5FA2B3C3D845B"&gt;Matt Woodward&lt;/a&gt; and now have all three engines up and running with Tomcat + Apache on windows (.. and yes Todd, it is &lt;span style="font-style:italic;"&gt;very &lt;/span&gt;fast!).  Now be warned, Matt's entry is long. But it is very informative, so read it all. (Besides, if you read my blog I &lt;span style="font-style:italic;"&gt;know &lt;/span&gt;you are used to long entries.)&lt;br /&gt;&lt;br /&gt;Now I am busily reading up on Tomcat and Apache, wondering why I did not do this sooner...&lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;br /&gt;&lt;b&gt;Update&lt;/b&gt;: When I installed Tomcat I selected a different JVM than the one that ships with CF9. So the first time I tried to invoke a web service CF threw an error saying the "...class file has wrong version 49.0, should be 48.0". In case you run into this issue, it was easily solved after reading a handy post by Rupesh Kumar: &lt;a href="http://coldfused.blogspot.com/2007/08/coldfusion-and-webservice-file-has.html"&gt;ColdFusion and WebService : "class file has wrong version&lt;/a&gt;. Note, after updating the tools.jar, I did have to stop and restart Tomcat for the change to fully take effect.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2914938287006075547?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2914938287006075547/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2914938287006075547&amp;isPopup=true' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2914938287006075547'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2914938287006075547'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/coldfusion-tomcat-apache-windows-take.html' title='ColdFusion + Tomcat + Apache + Windows (Take the plunge)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1285098402759101677</id><published>2009-12-07T02:16:00.000-08:00</published><updated>2009-12-07T04:10:00.046-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>OT: Easter Eggs</title><content type='html'>In a &lt;a href="http://stackoverflow.com/questions/1853653/hidden-features-of-coldfusion"&gt;recent post&lt;/a&gt; on stackoverflow.com, member Sergii mentioned a ColdFusion easter egg. (Thanks Sergii!)  Go ahead and feel smug if you already knew about it. If not, check it out. It is ...  interesting.&lt;br /&gt;&lt;br /&gt;While searching for others, I came across a few other fun ones.  Not all CF-related of course. But there are definitely some strange and amusing ones out there.&lt;br /&gt;&lt;br /&gt;Various Programs (source: www.stackoverflow.com)&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/397576/whats-your-favorite-easter-egg"&gt;http://stackoverflow.com/questions/397576/whats-your-favorite-easter-egg&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;JQuery *This one rocks!*   (source: www.aliaspooryorik.com)&lt;br /&gt;&lt;a href="http://www.aliaspooryorik.com/blog/index.cfm/e/posts.details/post/136"&gt;http://www.aliaspooryorik.com/blog/index.cfm/e/posts.details/post/136&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Google (source: www.danvega.org)&lt;br /&gt;&lt;a href="http://www.danvega.org/blog/index.cfm?mode=cat&amp;amp;catid=CCF3C429-AE69-270C-3D2E62AA9CC59D70"&gt;http://www.danvega.org/blog/index.cfm?mode=cat&amp;amp;catid=CCF3C429-AE69-270C-3D2E62AA9CC59D70&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;RIA Unleashed : Boston Site (source: www.remotesynthesis.com)&lt;br /&gt;&lt;a href="http://www.remotesynthesis.com/post.cfm/announcing-ria-unleashed-boston"&gt;http://www.remotesynthesis.com/post.cfm/announcing-ria-unleashed-boston&lt;/a&gt;&lt;br /&gt;*  See the P.S. at the bottom&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1285098402759101677?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1285098402759101677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1285098402759101677&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1285098402759101677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1285098402759101677'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/ot-easter-eggs.html' title='OT: Easter Eggs'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-5916034706251243101</id><published>2009-12-04T18:06:00.000-08:00</published><updated>2010-05-04T20:41:49.051-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Web Services'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Fedex Web Services + createObject("webservice") == Migraine</title><content type='html'>A very long time ago, I wrote an entry on &lt;a href="http://cfsearching.blogspot.com/2007/12/how-heck-do-you-use-fedex-rate-web.html"&gt;my novice struggles using the Fedex web services with createObject()&lt;/a&gt;. Though the entry shows I still had a lot to learn about web services, I still get occasional questions about it. In particular, about working with the Fedex web services and createObject(). So I will offer this advice to anyone looking to do the same -  &lt;span style="font-weight: bold;"&gt;don't&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;While ColdFusion definitely simplifies the process of working with web  services, it is also not the best tool for every web service.  Especially the more complex ones.  If you have ever tried using the FedEx web services with createObject("webservice"), you know how painful it can be. They are extremely complex and deeply nested.  So unless you miraculously hit on the right code the first time around, you are likely to waste a LOT of time trying to troubleshoot cryptic Axis error messages .. and the time you spend will not be fun.&lt;br /&gt;&lt;br /&gt;So my recommendation is to try using SOAP + CFHTTP instead. The Fedex WSDL developer files include working SOAP samples.  They will get you up and running much faster than trying to translate the java examples into CF code.  An &lt;a href="http://russ.michaels.me.uk/index.cfm/2007/5/18/ColdFusion-Web-Services-and-SOAP"&gt;old entry&lt;/a&gt; on Russ Michaels blog has some good tips on working with SOAP.  There is also a current project using the SOAP approach with the Fedex Rates Web Service, under the project name &lt;a href="http://code.google.com/p/cffedexrates/"&gt;CFFedexRates&lt;/a&gt;. You could easily use it as a base for some of the other web services.&lt;br /&gt;&lt;br /&gt;Take my word for it, you will be glad you did.&lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;strike&gt;&lt;b&gt;Update December 9, 2009:&lt;/b&gt;&lt;br /&gt;For a version of CFFedexRates that is compatible with the Rate Service v7, see issue #2 &lt;a href="http://code.google.com/p/cffedexrates/issues/detail?id=2"&gt;http://code.google.com/p/cffedexrates/issues/detail?id=2&lt;/a&gt;&lt;/strike&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update January 21, 2010:&lt;/b&gt;&lt;br /&gt;The &lt;a href="http://code.google.com/p/cffedexrates/"&gt;featured downloads section&lt;/a&gt; was updated to include a version compatible with Rate Service v7.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Update May 4, 2010: &lt;/b&gt;&lt;br /&gt;For a version of CFFedexRates that is compatible with the Rate Service v8, see issue #4 &lt;a href="http://code.google.com/p/cffedexrates/issues/detail?id=4"&gt;http://code.google.com/p/cffedexrates/issues/detail?id=4&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-5916034706251243101?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/5916034706251243101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=5916034706251243101&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/5916034706251243101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/5916034706251243101'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/fedex-web-services-createobjectwebservi.html' title='Fedex Web Services + createObject(&quot;webservice&quot;) == Migraine'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6123249867613133275</id><published>2009-12-03T05:03:00.000-08:00</published><updated>2009-12-16T12:16:47.050-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: Encryption Interoperability Issues (Beginner)</title><content type='html'>Recently, I have seen a few questions about encryption interoperability. The libraries used by ColdFusion (Sun JCE) are pretty standard. So for the most part, compatibility should not be issue. But it got me to thinking about some of the common pitfalls when trading encrypted data with external tools.  While they may seem obvious to some of you, many of them were not at all obvious to me.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;While I am certainly no expert on the subject, most of the issues I have encountered, or seen in various forums, tend to involve two things:  cipher settings and encoding. Now I know that seems like a blatantly obvious statement. But it is the source of more problems than you might think.&lt;br /&gt;&lt;br /&gt;Unfortunately, the ColdFusion documentation on the &lt;a href="http://livedocs.adobe.com/coldfusion/8/htmldocs/functions_e-g_01.html"&gt;encrypt/decrypt functions&lt;/a&gt; is a bit sketchy in places. Now to a degree, the minimal documentation is understandable. Realistically it would require whole &lt;span style="font-style: italic;"&gt;volumes &lt;/span&gt;to provide a comprehensive explanation of encryption. But there are a few key aspects of the encrypt/decrypt functions that I feel could really use some illumination.  If only to help developers avoid some of the more common interoperability problems.&lt;br /&gt;&lt;br /&gt;A prime example is the &lt;span style="font-family:courier new;"&gt;algorithm&lt;/span&gt; argument. Most examples you will see use simple names like &lt;span style="font-family:courier new;"&gt;AES &lt;/span&gt;or &lt;span style="font-family:courier new;"&gt;DESEDE&lt;/span&gt;. What is &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; immediately obvious is that those simple names are short-hand for several settings:  the algorithm, cipher mode and padding scheme.  When you use the short-hand name, ColdFusion applies the default cipher mode and padding scheme automatically.   The defaults may vary depending on which algorithm you select. But in the case of &lt;span style="font-family:courier new;"&gt;AES&lt;/span&gt; the defaults are ECB and PKCS5Padding. (At least from what I can tell).   So in other words, the algorithm values &lt;span style="font-family:courier new;"&gt;AES&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;AES/ECB/PKCS5Padding&lt;/span&gt; are equivalent. To specify a different mode or padding just change the algorithm value.&lt;br /&gt;&lt;br /&gt;Now chances are the external tool you are working with probably does not use exactly the same defaults as ColdFusion. But once you are aware of the additional settings for the various algorithms, it is much easier to figure out how to align the results. You just need to ensure the settings on both ends match up.&lt;br /&gt;&lt;br /&gt;Take C# for example. The defaults for the &lt;a href="http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;ved=0CAgQFjAA&amp;amp;url=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fsystem.security.cryptography.rijndaelmanaged.aspx&amp;amp;rct=j&amp;amp;q=RijndaelManaged+&amp;amp;ei=aLkXS7KrK4e6lAeEuYHuAg&amp;amp;usg=AFQjCNH3oqbASqISVRjBYYlbOIUuKJ5YFA"&gt;RijndaelManaged&lt;/a&gt; class are a bit different than ColdFusion's. For example, the default mode is CBC rather than ECB and the default key size is 256 bit.  So exchanging values between the two may not work right off the bat.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;                    ColdFusion            C# (RijndaelManaged)&lt;br /&gt;Mode:                ECB                   CBC&lt;br /&gt;Padding:             PKCS5Padding          PKCS7&lt;br /&gt;Key Size:            128 bit               256 bit&lt;br /&gt;Block Size:          128 bit               128 bit&lt;br /&gt;Allowed Key Lengths  128, *192, *256 bit   128, 192, 256 bit&lt;br /&gt;&lt;br /&gt;* Note: Unlimited encryption is required in CF for keys larger than 128 bit&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:85%;"&gt;See also &lt;a href="http://kb2.adobe.com/cps/546/e546373d.html"&gt;Strong  encryption in ColdFusion MX 7&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Once you have aligned the cipher settings, double check the encoding used on the various values.  In ColdFusion the string to be encrypted/decrypted "is always interpreted as a UTF-8 string".   From what I observed, the key value seems to be interpreted as base64.  So using this collective information you can now easily adjust the settings of ColdFusion and C# to produce the same results.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;!---&lt;br /&gt;Encrypt/Decrypt&lt;br /&gt;----&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;ColdFusion (AES/CBC/PKCS5Padding) + iv&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset thePlainData  = "Nothing to see here folks" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset theKey    = generateSecretKey("AES", 128) /&amp;gt;&lt;br /&gt;&amp;lt;cfset theAlgorithm  = "AES/CBC/PKCS5Padding" /&amp;gt;&lt;br /&gt;&amp;lt;cfset theEncoding  = "base64" /&amp;gt;&lt;br /&gt;&amp;lt;cfset theIV    = BinaryDecode("7fe8585328e9ac7b7fe8585328e9ac7b", "hex") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset encryptedString = encrypt(thePlainData, theKey, theAlgorithm, theEncoding, theIV) /&amp;gt;&lt;br /&gt;&amp;lt;cfset decryptedString = decrypt(encryptedString, theKey, theAlgorithm, theEncoding, theIV) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;Display results&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset keyLengthInBits  = arrayLen(BinaryDecode(theKey, "base64")) * 8 /&amp;gt;&lt;br /&gt;&amp;lt;cfset ivLengthInBits  = arrayLen(theIV) * 8 /&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#variables#" label="AES/CBC/PKCS5Padding Results" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Security.Cryptography;&lt;br /&gt;&lt;br /&gt;namespace AESTest&lt;br /&gt;{&lt;br /&gt;public class AESCBC&lt;br /&gt;{&lt;br /&gt;    public static void Main()&lt;br /&gt;    {&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            // Just hard coded values for testing ...&lt;br /&gt;            // MUST change them to match the values used in the CF code&lt;br /&gt;            String thePlainData = "Nothing to see here folks";&lt;br /&gt;            String theKey = "oRJUjgbx9SGGR6v3T8JGJg==";&lt;br /&gt;            String theIV = "f+hYUyjprHt/6FhTKOmsew==";&lt;br /&gt;            String encryptedText = EncryptText(thePlainData, theKey, theIV);&lt;br /&gt;            String decryptedText = DecryptText(encryptedText, theKey, theIV);&lt;br /&gt;&lt;br /&gt;            Console.WriteLine("Encrypted String: {0}", encryptedText);&lt;br /&gt;            Console.WriteLine("Decrypted String: {0}", decryptedText);&lt;br /&gt;        }&lt;br /&gt;        catch (Exception e)&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine(e.Message);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        Console.ReadLine();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public static String EncryptText(String Data, String Key, String IV)&lt;br /&gt;    {&lt;br /&gt;        // Extract the bytes of each of the values&lt;br /&gt;        byte[] input = Encoding.UTF8.GetBytes(Data);&lt;br /&gt;        byte[] key = Convert.FromBase64String(Key);&lt;br /&gt;        byte[] iv = Convert.FromBase64String(IV);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        // Create a new instance of the algorithm with the desired settings&lt;br /&gt;        RijndaelManaged algorithm = new RijndaelManaged();&lt;br /&gt;        algorithm.Mode = CipherMode.CBC;&lt;br /&gt;        algorithm.Padding = PaddingMode.PKCS7;&lt;br /&gt;        algorithm.BlockSize = 128;&lt;br /&gt;        algorithm.KeySize = 128;&lt;br /&gt;        algorithm.Key = key;&lt;br /&gt;        algorithm.IV = iv;&lt;br /&gt;&lt;br /&gt;        // Create a new encryptor and encrypt the given value&lt;br /&gt;        ICryptoTransform cipher = algorithm.CreateEncryptor();&lt;br /&gt;        byte[] output = cipher.TransformFinalBlock(input, 0, input.Length);&lt;br /&gt;&lt;br /&gt;        // Finally, return the encrypted value in base64 format&lt;br /&gt;        String encrypted = Convert.ToBase64String(output);&lt;br /&gt;&lt;br /&gt;        return encrypted;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public static String DecryptText(String Data, String Key, String IV)&lt;br /&gt;    {&lt;br /&gt;        // Extract the bytes of each of the values&lt;br /&gt;        byte[] input = Convert.FromBase64String(Data);&lt;br /&gt;        byte[] key = Convert.FromBase64String(Key);&lt;br /&gt;        byte[] iv = Convert.FromBase64String(IV);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        // Create a new instance of the algorithm with the desired settings&lt;br /&gt;        RijndaelManaged algorithm = new RijndaelManaged();&lt;br /&gt;        algorithm.Mode = CipherMode.CBC;&lt;br /&gt;        algorithm.Padding = PaddingMode.PKCS7;&lt;br /&gt;        algorithm.BlockSize = 128;&lt;br /&gt;        algorithm.KeySize = 128;&lt;br /&gt;        algorithm.Key = key;&lt;br /&gt;        algorithm.IV = iv;&lt;br /&gt;&lt;br /&gt;        //FromBase64String&lt;br /&gt;        // Create a new encryptor and encrypt the given value&lt;br /&gt;        ICryptoTransform cipher = algorithm.CreateDecryptor();&lt;br /&gt;        byte[] output = cipher.TransformFinalBlock(input, 0, input.Length);&lt;br /&gt;&lt;br /&gt;        // Finally, convert the decrypted value to UTF8 format&lt;br /&gt;        String decrypted = Encoding.UTF8.GetString(output);&lt;br /&gt;&lt;br /&gt;        return decrypted;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Hopefully these small tips will help someone else or at least keep them from pulling out their hair trying to coerce ColdFusion and some other tool into producing the same results.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6123249867613133275?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6123249867613133275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6123249867613133275&amp;isPopup=true' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6123249867613133275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6123249867613133275'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/coldfusion-encryption-interoperability.html' title='ColdFusion: Encryption Interoperability Issues (Beginner)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-1850058331804582670</id><published>2009-12-02T12:43:00.000-08:00</published><updated>2009-12-02T12:54:49.312-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>How to Move A Directory</title><content type='html'>The round-a-bout way to move a directory always slips through my brain like it is a sieve. So this one is a reminder to myself. Use &amp;lt;cfdirectory action="rename"..&amp;gt;, or in ColdFusion 9 use the sleeker DirectoryRename() function. Note, an error will occur if the destination directory already exists. &lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfset sourceDirec ="C:\docs\images\20091202"&amp;gt;&lt;br /&gt;&amp;lt;cfset destDirec ="C:\20091202"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfdirectory action="rename"&lt;br /&gt;       directory="#sourceDirec#"&lt;br /&gt;       newDirectory="#destDirec#" /&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-1850058331804582670?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/1850058331804582670/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=1850058331804582670&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1850058331804582670'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/1850058331804582670'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/12/how-to-move-directory.html' title='How to Move A Directory'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2445657844280168273</id><published>2009-11-28T19:47:00.000-08:00</published><updated>2009-11-29T19:23:42.698-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>OT: This is Unicode ?</title><content type='html'>While visiting the &lt;a href="http://www.unicode.org/press/articles.html"&gt;unicode.org&lt;/a&gt; site, I came across this &lt;span style="font-style: italic;"&gt;unexpected&lt;/span&gt; title from 1992.  (Yes, it really is about unicode. Who says unicode is a dry topic ;).&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Kiss Your ASCII Goodbye &lt;/span&gt; (John Dvorak, PC Magazine/1992)&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2445657844280168273?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2445657844280168273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2445657844280168273&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2445657844280168273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2445657844280168273'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/ot-unicode.html' title='OT: This is Unicode ?'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-9018650377917356593</id><published>2009-11-27T02:46:00.000-08:00</published><updated>2009-11-27T08:35:23.556-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>SOT: Heads or Tails?  (Windows Resource Kit - Tail.exe Gotcha)</title><content type='html'>So I was comparing two windows implementations of &lt;a href="http://en.wikipedia.org/wiki/Tail_%28Unix%29"&gt;tail&lt;/a&gt;, and came across something unexpected. While I was checking one of my tests, I noticed the results contained less lines than I requested. The base files definitely contained more than enough lines. So I knew that was not problem. After digging deeper, I discovered the lines returned were not even from the end of the file! They were from the middle.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;Well, come to find out the file I was testing contained some funky characters. One of them being ascii character 26. Apparently the Windows Resource Kit version of tail.exe interprets ascii 26 as some sort of EOF (end of file) marker. Consequently tail.exe uses that marker as its starting point. Well, naturally that skews the results because that position is not necessarily the &lt;span style="font-style:italic;"&gt;actual&lt;/span&gt; end of the file.&lt;br /&gt;&lt;br /&gt;To see it for yourself, create a simple file containing 50 lines, with the ascii character 26 inserted every ten (10) lines.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfset specialChar  = chr(26)  /&amp;gt;&lt;br /&gt;&amp;lt;cfset newLine   = chr(10)  /&amp;gt;&lt;br /&gt;&amp;lt;cfsavecontent variable="data"&amp;gt;&lt;br /&gt;  &amp;lt;cfoutput&amp;gt;&lt;br /&gt;      &amp;lt;cfloop from="1" to="50" index="x"&amp;gt;Log file line #x# &amp;lt;cfif not x mod 10&amp;gt;#specialChar#&amp;lt;/cfif&amp;gt;#newLine#&amp;lt;/cfloop&amp;gt;&lt;br /&gt;  &amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset filePath = ExpandPath("./testLogFile.log") /&amp;gt;&lt;br /&gt;&amp;lt;cfset FileWrite( filePath, trim(data) ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now use tail.exe to grab the last twenty (20) lines of the file. Due to the placement of the special characters, what you will end up with is the &lt;span style="font-style: italic;"&gt;first &lt;/span&gt;10 lines of the file, not the last twenty.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/Sw-wRXDJPBI/AAAAAAAAAeE/tSYH6yHuwhE/s1600/ColdFusion_WindowsResourceKit_HeadsOrTails.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 212px; height: 320px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/Sw-wRXDJPBI/AAAAAAAAAeE/tSYH6yHuwhE/s320/ColdFusion_WindowsResourceKit_HeadsOrTails.png" alt="" id="BLOGGER_PHOTO_ID_5408735489786723346" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfset grabLines = 20 /&amp;gt;&lt;br /&gt;&amp;lt;cfexecute name='"c:\program files\Windows Resource Kits\tools\tail.exe"'&lt;br /&gt;      arguments='-#grabLines# #filePath#'&lt;br /&gt;      variable='output'&lt;br /&gt;      timeout='20' /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- convert lines to array ---&amp;gt;&lt;br /&gt;&amp;lt;cfset linesFound = listToArray(output, chr(10), true) /&amp;gt;&lt;br /&gt;&amp;lt;cfset actualLines = listToArray( FileRead( filePath ), chr(10), true) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Log File:&amp;lt;/strong&amp;gt; #filePath# &amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Requested Lines:&amp;lt;/strong&amp;gt; #grabLines# &amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Lines Found:&amp;lt;/strong&amp;gt; #arrayLen(linesFound)#&amp;lt;/p&amp;gt;&lt;br /&gt;  &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Actual Lines:&amp;lt;/strong&amp;gt; #arrayLen(actualLines)#&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Fortunately, the &lt;a href="http://sourceforge.net/projects/gnuwin32/"&gt;GNUWin32 version&lt;/a&gt; does not suffer from this "problem" and returns the expected results. (Thank goodness someone knows basic subtraction)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_4MgprHLfxvM/Sw-wRML3gdI/AAAAAAAAAd8/hlJvmonKHFQ/s1600/ColdFusion_GNUWin32_Tail.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 127px; height: 320px;" src="http://1.bp.blogspot.com/_4MgprHLfxvM/Sw-wRML3gdI/AAAAAAAAAd8/hlJvmonKHFQ/s320/ColdFusion_GNUWin32_Tail.png" alt="" id="BLOGGER_PHOTO_ID_5408735486870520274" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As for the Windows Resource Kit version, well.. if we were flipping a coin, this time it was definitely "heads" -  as in "head on over to sourceforge.net and get a yourself a working copy of tail.exe".&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-9018650377917356593?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/9018650377917356593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=9018650377917356593&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/9018650377917356593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/9018650377917356593'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/sot-heads-or-tails-windows-resource-kit.html' title='SOT: Heads or Tails?  (Windows Resource Kit - Tail.exe Gotcha)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/Sw-wRXDJPBI/AAAAAAAAAeE/tSYH6yHuwhE/s72-c/ColdFusion_WindowsResourceKit_HeadsOrTails.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3993788906484773577</id><published>2009-11-25T01:26:00.000-08:00</published><updated>2009-11-25T01:30:46.296-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>OT: JAI Resources?</title><content type='html'>Does anyone know of any good resources (online, books, etcetera) on JAI? Frankly the sun docs leave a lot to be desired. If anyone can recommend a good book on the topic it would be greatly appreciated.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3993788906484773577?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3993788906484773577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3993788906484773577&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3993788906484773577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3993788906484773577'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/ot-jai-resources.html' title='OT: JAI Resources?'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7797841732987904653</id><published>2009-11-24T23:28:00.000-08:00</published><updated>2010-07-30T15:16:28.945-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 8: Blowfish Encryption (Something smells fishy .. and it is not the algorithm)</title><content type='html'>A while back I saw a thread on the adobe forums about an &lt;a href="http://forums.adobe.com/thread/496142"&gt;issue with Blowfish encryption&lt;/a&gt;. The issue being the results from ColdFusion's encrypt function seemed to differ from other languages.  Hardly uncommon given the "delicate" nature of encryption. What grabbed my attention was that the results from ColdFusion and Java were also different.  Not what I would have expected.&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Take the simple example below. It sure seems like the same text and key are used for both CF and Java encryption.   Yet the results are different.   However, if you compare the java results with those from the online tools (mentioned in the adobe thread) they are all the same. The odd one out here is ColdFusion.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note: These examples were chosen for simplicity. They are &lt;span style="font-weight: bold;"&gt;NOT&lt;/span&gt; a good example of strong encryption&lt;/span&gt; (&lt;a href="http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29"&gt;usage of ECB&lt;/a&gt;, etcetera ...)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;ColdFusion&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfset myText        = "guess this!1 2 3" /&amp;gt;&lt;br /&gt;&amp;lt;cfset myKey         = generateSecretKey("Blowfish", 32) /&amp;gt;&lt;br /&gt;&amp;lt;cfset cfEncrypted   = Encrypt(myText, myKey, "Blowfish/ECB/NoPadding", "Hex") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- results (using &lt;p&gt;tags because the blogger eats line breaks!) ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;ColdFusion:&amp;lt;/strong&amp;gt;&amp;lt;hr /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;MyText&amp;lt;/strong&amp;gt; : #myText#&amp;lt;/p&amp;gt; &lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;MyKey&amp;lt;/strong&amp;gt; : #myKey#&amp;lt;/p&amp;gt;  &lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;CF Encrypted&amp;lt;/strong&amp;gt; : #cfEncrypted#&amp;lt;/p&gt; &lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Java&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;!---  generate a secret key ---&amp;gt;&lt;br /&gt;&amp;lt;cfset SecretKeySpec     = createObject("java", "javax.crypto.spec.SecretKeySpec") /&amp;gt;&lt;br /&gt;&amp;lt;cfset myKeyBytes         = CharsetDecode(myKey, "utf8") /&amp;gt;&lt;br /&gt;&amp;lt;cfset keySpec             = SecretKeySpec.init(myKeyBytes, "Blowfish") /&amp;gt;&lt;br /&gt;&amp;lt;!--- get a cipher instance for encrypting ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Cipher             = createObject("java", "javax.crypto.Cipher") /&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptor         = Cipher.getInstance("Blowfish/ECB/NoPadding") /&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptor.init(Cipher.ENCRYPT_MODE, keySpec) /&amp;gt;&lt;br /&gt;&amp;lt;!--- do the encryption ---&amp;gt;&lt;br /&gt;&amp;lt;cfset myTextBytes         = CharsetDecode(myText, "utf8") /&amp;gt;&lt;br /&gt;&amp;lt;cfset javaEncrypted     = encryptor.doFinal(myTextBytes) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- results ---&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Java Encrypted&amp;lt;/strong&amp;gt;  : #BinaryEncode(javaEncrypted, "hex")# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Sample Results:&lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/SwzgT1C2VhI/AAAAAAAAAds/JAk3DWloem0/s1600/ColdFusion_Blowfish_vs_Java.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 96px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/SwzgT1C2VhI/AAAAAAAAAds/JAk3DWloem0/s320/ColdFusion_Blowfish_vs_Java.png" alt="" id="BLOGGER_PHOTO_ID_5407943883826288146" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Since I am definitely &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; an expert on encryption, I just figured I was missing something. Eventually I did get the CF and java results to match by converting the secret key to binary and then back to base64.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfset myText        = "guess this!1 2 3" /&amp;gt;&lt;br /&gt;&amp;lt;cfset myKey         = generateSecretKey("Blowfish", 32) /&amp;gt;&lt;br /&gt;&amp;lt;cfset magicKey      = BinaryEncode(CharsetDecode(myKey, "utf8"), "base64") /&amp;gt;&lt;br /&gt;&amp;lt;cfset cfEncrypted   = Encrypt(myText, magicKey, "Blowfish/ECB/NoPadding", "Hex") /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The new results clearly showed my &lt;span style="font-family:courier new;"&gt;magicKey&lt;/span&gt; now matched the java &lt;span style="font-family:courier new;"&gt;keySpec&lt;/span&gt; value. So of course the encrypted strings also matched.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_4MgprHLfxvM/Swzu_7-tAVI/AAAAAAAAAd0/1v5NSAAX33A/s1600/ColdFusion_Blowfish_vs_Java_Fixed.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 96px;" src="http://3.bp.blogspot.com/_4MgprHLfxvM/Swzu_7-tAVI/AAAAAAAAAd0/1v5NSAAX33A/s320/ColdFusion_Blowfish_vs_Java_Fixed.png" alt="" id="BLOGGER_PHOTO_ID_5407960034764980562" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;But I am not sure why that the extra step necessary. Supposedly the value returned from &lt;span style="font-family:courier new;"&gt;GenerateSecretKey() &lt;/span&gt;&lt;a href="http://kb2.adobe.com/cps/546/e546373d.html"&gt;is already base64 encoded&lt;/a&gt;. Also, it seems to work correctly in reverse (ie when the secret key is generated from the &lt;a href="http://java.sun.com/javase/6/docs/api/javax/crypto/KeyGenerator.html"&gt;javax.crypto.KeyGenerator&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;So am I missing something here, or is this a "feature"? &lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;br /&gt;&lt;b&gt;Update&lt;/b&gt;:  Yep! I was obviously staring at this for too long. I missed something obvious. I should have used BinaryDecode(myKey, "base64") to get the java key bytes and vice versa. Now it make sense! ;) &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;As mentioned in the comments, using CBC mode is a bit different. As it requires an IV (Initialization Vector). Here is a basic example using CBC mode. Though in practice, you probably would not use the same IV each time as I am doing here. I also included a lot of extra debugging output. So you can verify the values used by both ColdFusion and Java are the same.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;!---&lt;br /&gt;    ENCRYPT WITH COLDFUSION&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset algorithm      = "Blowfish/CBC/PKCS5Padding"&amp;gt;&lt;br /&gt;&amp;lt;cfset myText        = "can you guess this?" /&amp;gt;&lt;br /&gt;&amp;lt;cfset myKey         = generateSecretKey("Blowfish", 32) &amp;gt;&lt;br /&gt;&amp;lt;cfset myIV             = CharsetDecode("12345678", "utf8")&amp;gt;&lt;br /&gt;&amp;lt;cfset cfEncrypted   = Encrypt(myText, myKey, algorithm, "base64", myIV) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- results (using &amp;lt;p&amp;gt; tags because the blogger eats line breaks!) ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;ColdFusion (Encrypted):&amp;lt;/strong&amp;gt;&amp;lt;hr /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;MyText&amp;lt;/strong&amp;gt; : #myText#&amp;lt;/p&amp;gt; &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;MyKey&amp;lt;/strong&amp;gt; : #myKey#&amp;lt;/p&amp;gt;  &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;MyIV&amp;lt;/strong&amp;gt; : &amp;lt;cfdump var="#myIV#"&amp;gt;&amp;lt;/p&amp;gt;  &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;CF Encrypted&amp;lt;/strong&amp;gt; : #cfEncrypted#&amp;lt;/p&amp;gt; &lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;    ENCRYPT WITH JAVA&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset SecretKeySpec       = createObject("java", "javax.crypto.spec.SecretKeySpec") /&amp;gt;&lt;br /&gt;&amp;lt;cfset myKeyBytes          = BinaryDecode(myKey, "base64") /&amp;gt;&lt;br /&gt;&amp;lt;cfset keySpec             = SecretKeySpec.init(myKeyBytes, "Blowfish") /&amp;gt;&lt;br /&gt;&amp;lt;cfset ivSpec               = createObject("java", "javax.crypto.spec.IvParameterSpec").init( myIV )&amp;gt;&lt;br /&gt;&amp;lt;cfset Cipher              = createObject("java", "javax.crypto.Cipher") /&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptor           = Cipher.getInstance( algorithm ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptor.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec) /&amp;gt;&lt;br /&gt;&amp;lt;cfset myTextBytes         = CharsetDecode(myText, "utf8") /&amp;gt;&lt;br /&gt;&amp;lt;!--- convert encrypted byte array to base64 string ---&amp;gt;&lt;br /&gt;&amp;lt;cfset javaEncrypted       = BinaryEncode( encryptor.doFinal(myTextBytes), "base64") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- results (using &amp;lt;p&amp;gt; tags because the blogger eats line breaks!) ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Java Encrypted:&amp;lt;/strong&amp;gt;&amp;lt;hr /&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;myTextBytes (utf8)&amp;lt;/strong&amp;gt; : #CharsetEncode(myTextBytes, "utf8")#&amp;lt;/p&amp;gt;  &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;keySpec&amp;lt;/strong&amp;gt; : #BinaryEncode(keySpec.getEncoded(), "base64")#&amp;lt;/p&amp;gt; &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ivSpec (raw)&amp;lt;/strong&amp;gt; : &amp;lt;cfdump var="#ivSpec.getIV()#"&amp;gt;&amp;lt;/p&amp;gt;  &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ivSpec (utf8)&amp;lt;/strong&amp;gt; : #CharsetEncode(ivSpec.getIV(), "utf8")#&amp;lt;/p&amp;gt;  &lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Java Encrypted&amp;lt;/strong&amp;gt;  : #javaEncrypted# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now just to prove the results are compatible, you can decrypt the ColdFusion results with Java (and vice versa).&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;!---&lt;br /&gt;    DECRYPT *COLDFUSION* RESULT WITH JAVA&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfset SecretKeySpec     = createObject("java", "javax.crypto.spec.SecretKeySpec") /&amp;gt;&lt;br /&gt;&amp;lt;cfset myKeyBytes        = BinaryDecode(myKey, "base64") /&amp;gt;&lt;br /&gt;&amp;lt;cfset keySpec           = SecretKeySpec.init(myKeyBytes, "Blowfish") /&amp;gt;&lt;br /&gt;&amp;lt;cfset ivSpec             = createObject("java", "javax.crypto.spec.IvParameterSpec").init( myIV )&amp;gt;&lt;br /&gt;&amp;lt;cfset Cipher            = createObject("java", "javax.crypto.Cipher") /&amp;gt;&lt;br /&gt;&amp;lt;cfset decryptor         = Cipher.getInstance( algorithm ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset decryptor.init(Cipher.DECRYPT_MODE, keySpec, ivSpec) /&amp;gt;&lt;br /&gt;&amp;lt;!--- convert our encrypted (base64 encoded) string to a byte array ---&amp;gt;&lt;br /&gt;&amp;lt;cfset encryptedBytes     = BinaryDecode( cfEncrypted , "base64") /&amp;gt;&lt;br /&gt;&amp;lt;!--- the decrypted bytes will be in UTF8 ---&amp;gt;&lt;br /&gt;&amp;lt;cfset javaDecrypted      = CharsetEncode( decryptor.doFinal( encryptedBytes ), "utf8") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Java Decrypted&amp;lt;/strong&amp;gt;  : #javaDecrypted# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;    DECRYPT *JAVA* RESULT WITH COLDFUSION&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;!--- decrypt (base64 encoded) encrypted string ---&amp;gt;&lt;br /&gt;&amp;lt;cfset cfDecrypted   = Decrypt(javaEncrypted, myKey, algorithm, "base64", myIV) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;    &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;ColdFusion Decrypted&amp;lt;/strong&amp;gt;  : #cfDecrypted# &amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7797841732987904653?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7797841732987904653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7797841732987904653&amp;isPopup=true' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7797841732987904653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7797841732987904653'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/coldfusion-8-blowfish-encryption.html' title='ColdFusion 8: Blowfish Encryption (Something smells fishy .. and it is not the algorithm)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/SwzgT1C2VhI/AAAAAAAAAds/JAk3DWloem0/s72-c/ColdFusion_Blowfish_vs_Java.png' height='72' width='72'/><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6967144745647087497</id><published>2009-11-19T22:53:00.000-08:00</published><updated>2010-04-21T05:13:17.807-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ZXing'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Seeing Stripes: Experiment with ZXing</title><content type='html'>I recently took a look at the &lt;a href="http://code.google.com/p/zxing/"&gt;ZXing Project&lt;/a&gt; which is described as "&lt;span style="font-family: courier new;"&gt;an open-source, multi-format 1D/2D barcode image processing library implemented in Java&lt;/span&gt;.". While its primary focus is mobile phones, I decided to look at the &lt;span style="font-family: courier new;"&gt;javase&lt;/span&gt; component of the project.  ZXing also comes with a servlet. But I first wanted to see how the lower level components worked.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Setup&lt;/span&gt;&lt;br /&gt;Not seeing any pre-compiled jars, I downloaded the &lt;a href="http://code.google.com/p/zxing/downloads/list"&gt;latest sources&lt;/a&gt; (ZXing-1.4.zip). After loading it into Eclipse, and poked around a bit to figure out how to decode barcode images of different types. Finally, I used the pre-made &lt;a href="http://code.google.com/p/zxing/wiki/GettingStarted"&gt;ant files&lt;/a&gt; to create the two jars I needed: &lt;span style="font-family: courier new;"&gt;core.jar&lt;/span&gt; and &lt;span style="font-family: courier new;"&gt;javase.jar&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Decoding barcode images&lt;/span&gt;&lt;br /&gt;While the project has some decent documentation, the developer notes seem to be outdated in a few places.  But examining some of the javase classes turned up a convenience class called &lt;span style="font-family: courier new;"&gt;MultiFormatReader&lt;/span&gt;.  From what I could tell it provides a simple way to decode barcodes when you may not know the type ahead of time.   Obviously if you know the barcode type ahead of time, it is more efficient to use the specific reader for that type.  But since I wanted to test all supported types the MultiFormatReader was perfect for my needs.&lt;br /&gt;&lt;br /&gt;Now before I could test ZXing, I needed some barcode images. So I used &lt;a href="http://cfsearching.blogspot.com/2009/11/cfbarbecuecfc-just-because.html"&gt;CFBarbecue.cfc&lt;/a&gt; to generate a sample of all of the barcodes supported by the Barbecue library.  Now ZXing does not support all of them.  But there is a good intersection between the two.   Once I had my images, I created an instance of MultiFormatReader, using the ever-handy &lt;a href="http://javaloader.riaforge.org/"&gt;JavaLoader.cfc&lt;/a&gt;. I also passed the reader some hints to increase accuracy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note:  This code is for demonstration purposes only. Normally, the javaLoader should be stored in the server scope to &lt;/span&gt;&lt;a href="http://www.transfer-orm.com/?action=displayPost&amp;amp;ID=212" style="font-style: italic;"&gt;avoid memory leaks&lt;/a&gt;&lt;span style="font-style: italic;"&gt;. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset paths = [] /&amp;gt;&lt;br /&gt;&amp;lt;cfset arrayAppend(paths, expandPath('zxing-1.4/core/core.jar')) /&amp;gt;&lt;br /&gt;&amp;lt;cfset arrayAppend(paths, expandPath('zxing-1.4/javase/javase.jar')) /&amp;gt;&lt;br /&gt;&amp;lt;cfset loader = createObject("component", "javaloader.JavaLoader").init( paths ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Create hints for the reader. TRY_HARDER increases accuracy ---&amp;gt;&lt;br /&gt;&amp;lt;cfset DecodeHintType = loader.create("com.google.zxing.DecodeHintType") /&amp;gt;&lt;br /&gt;&amp;lt;cfset hints = loader.create("java.util.Hashtable").init() /&amp;gt;&lt;br /&gt;&amp;lt;cfset hints.put(DecodeHintType.TRY_HARDER, javacast("boolean", true)) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Since we will be reading multiple images, create one reader and reuse it  ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Reader = loader.create("com.google.zxing.MultiFormatReader").init() /&amp;gt;&lt;br /&gt;&amp;lt;cfset Reader.setHints(hints) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, I used cfdirectory to grab a list of all of my barcode images. Then looped through the images and attempted to decode each one.    Now in order to use the reader's decode method, I needed to convert my image to a compatible format:  BinaryBitmap.   So I read in each image, extracted the underlying BufferedImage and passed it through a few of the ZXing classes designed to prepare images for decoding.&lt;br /&gt;&lt;br /&gt;Finally, I called the reader's decode method to decode the image. If the image was successfully decoded it returns a &lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;a href="http://zxing.org/w/docs/javadoc/index.html"&gt;Result&lt;/a&gt; object containing some useful properties like the raw text and barcode type.&lt;br /&gt;&lt;br /&gt;One thing to be aware of is that error handling is unlikely to yield any useful information, beyond the fact that an error occurred.  From the notes in the current source code,  the way in which decoding errors are handled is undergoing a transformation, to increase performance. So for now do not expect much exception information beyond name, rank and serial number.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- read all barcode images in my subdirectory ---&amp;gt;&lt;br /&gt;&amp;lt;cfdirectory action="list" directory="#ExpandPath('images')#"&lt;br /&gt;            filter="*.gif"&lt;br /&gt;            name="barcodeImages" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!---&lt;br /&gt;    Try and decode each barcode with z-xing.&lt;br /&gt;    Note: Not all codes are supported by z-xing!!!&lt;br /&gt;---&amp;gt;&lt;br /&gt;&amp;lt;cfoutput query="barcodeImages"&amp;gt;&lt;br /&gt;    &amp;lt;cfset imagePath = Directory &amp;amp;"/"&amp;amp; name /&amp;gt;&lt;br /&gt;    &amp;lt;cftry&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!--- display the original image ---&amp;gt;&lt;br /&gt;        &amp;lt;strong&amp;gt;Barcode Image&amp;lt;/strong&amp;gt; #name# &amp;lt;br /&amp;gt;&lt;br /&gt;        &amp;lt;cfimage action="writeToBrowser" source="#imagePath#"&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!--- extract the BufferedImage of the current barcode ---&amp;gt;&lt;br /&gt;        &amp;lt;cfset img = ImageGetBufferedImage(ImageRead(imagePath)) /&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!--- prepare the image for decoding ---&amp;gt;&lt;br /&gt;        &amp;lt;cfset source = loader.create("com.google.zxing.client.j2se.BufferedImageLuminanceSource").init(img) /&amp;gt;&lt;br /&gt;        &amp;lt;cfset binarizer = loader.create("com.google.zxing.common.GlobalHistogramBinarizer").init(source) /&amp;gt;&lt;br /&gt;        &amp;lt;cfset bitmap = loader.create("com.google.zxing.BinaryBitmap").init(binarizer) /&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!--- This method reuses the existing settings for decoding multiple images ---&amp;gt;&lt;br /&gt;        &amp;lt;cfset decodedResult = Reader.decodeWithState(bitmap) /&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;!--- display the results ---&amp;gt;&lt;br /&gt;        &amp;lt;strong&amp;gt;Decoded Text&amp;lt;/strong&amp;gt; #decodedResult.getText()# &amp;lt;br /&amp;gt;&lt;br /&gt;        &amp;lt;strong&amp;gt;Decoded Format&amp;lt;/strong&amp;gt; #decodedResult.getBarcodeFormat()# &amp;lt;br /&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;cfcatch&amp;gt;&lt;br /&gt;            Not supported or unable to decode: #cfcatch.type# #cfcatch.message#&lt;br /&gt;        &amp;lt;/cfcatch&amp;gt;&lt;br /&gt;    &amp;lt;/cftry&amp;gt;&lt;br /&gt;    &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;hr /&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_4MgprHLfxvM/SwZpi4GTWiI/AAAAAAAAAdk/VgW-Guq_KEY/s1600/ColdFusion_ZXing_Results.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5406124450600147490" src="http://3.bp.blogspot.com/_4MgprHLfxvM/SwZpi4GTWiI/AAAAAAAAAdk/VgW-Guq_KEY/s320/ColdFusion_ZXing_Results.png" style="cursor: pointer; display: block; height: 320px; margin: 0px auto 10px; text-align: center; width: 258px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;All of my sample images were decoded except:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;2of7  &lt;/li&gt;&lt;li&gt;Codabar&lt;/li&gt;&lt;li&gt;Int2of5&lt;/li&gt;&lt;li&gt;Monarch&lt;/li&gt;&lt;li&gt;NW7&lt;/li&gt;&lt;li style="color: black;"&gt;PDF417&lt;/li&gt;&lt;li&gt;PostNet&lt;/li&gt;&lt;li&gt;Std2of5&lt;/li&gt;&lt;li&gt;USD4&lt;/li&gt;&lt;/span&gt;&lt;/ul&gt;While I knew some of them are not supported, but I was surprised that the PD417 and  Interleaved 2 of 5 samples failed.   I am not yet sure why.  For now I will assume it was an error on my part. I will have to investigate the individual readers further.&lt;br /&gt;&lt;br /&gt;However, I was able to decode a DataMatrix barcode using the DataMatrixReader. (Created using the &lt;a href="http://www.idautomation.com/java/dmservlet.html"&gt;free servlet at IDAutomation.com&lt;/a&gt;).  Just be aware the current project documentation  lists DataMatrix decoding as "alpha quality".  So do not expect miracles.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/SwZo1-d9xdI/AAAAAAAAAdc/muBh2I4N7vk/s1600/ColdFusion_XZing_dataMatrix_Decoded.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5406123679215896018" src="http://1.bp.blogspot.com/_4MgprHLfxvM/SwZo1-d9xdI/AAAAAAAAAdc/muBh2I4N7vk/s320/ColdFusion_XZing_dataMatrix_Decoded.png" style="cursor: pointer; display: block; height: 146px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset imagePath = "c:\barCode_loremIpsum_idAutomation.gif" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset DecodeHintType = loader.create("com.google.zxing.DecodeHintType") /&amp;gt;&lt;br /&gt;&amp;lt;cfset hints = loader.create("java.util.Hashtable").init() /&amp;gt;&lt;br /&gt;&amp;lt;cfset hints.put(DecodeHintType.PURE_BARCODE, javacast("boolean", true)) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- prepare the image for decoding ---&amp;gt;&lt;br /&gt;&amp;lt;cfset img = ImageGetBufferedImage(ImageNew(imagePath)) /&amp;gt;&lt;br /&gt;&amp;lt;cfset source = loader.create("com.google.zxing.client.j2se.BufferedImageLuminanceSource").init(img) /&amp;gt;&lt;br /&gt;&amp;lt;cfset binarizer = loader.create("com.google.zxing.common.GlobalHistogramBinarizer").init(source) /&amp;gt;&lt;br /&gt;&amp;lt;cfset bitmap = loader.create("com.google.zxing.BinaryBitmap").init(binarizer) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- attempt to decode the image ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Reader = loader.create("com.google.zxing.datamatrix.DataMatrixReader") /&amp;gt;&lt;br /&gt;&amp;lt;cfset decodedResult = Reader.decode( bitmap, hints ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;&amp;lt;!--- display the original image ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Barcode Image&amp;lt;/strong&amp;gt; #imagePath# &amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#imagePath#"&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- display the results ---&amp;gt;&lt;br /&gt;&amp;lt;strong&amp;gt;Decoded Result&amp;lt;/strong&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;#decodedResult.getText()# &amp;lt;hr /&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other Classes&lt;/span&gt;&lt;br /&gt;The j2se component also has a few classes you might find useful for quick tests. The first is GUIRunner. It is a very rudimentary GUI you can use to test a single bar code image. To use it, simply open a command prompt and enter the following. Just modify the "-cp" value (classpath) to point to the location of your jars.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;C:\test\zxing&amp;gt; java -cp c:\test\zxing\core.jar;c:\test\zxing\javase.jar com.google.zxing.client.j2se.GUIRunner&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The other class is CommandLineRunner.  It can be used to decode a single image, a directory of images or a url. Just supply the locations of your jars and the file/directory/url you wish to decode. The "--try_harder" hint can be used to increase accuracy, and the "--dump_results" option to save the results to a file.  Note: The results of each barcode are saved to &lt;span style="font-style: italic;"&gt;individual file&lt;/span&gt;s. So keep that in mind if you are decoding an entire directory.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Example:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre&gt;C:\test\zxing&amp;gt; java -cp c:\test\zxing\core.jar;c:\test\zxing\javase.jar com.google.zxing.client.j2se.CommandLineRunner c:/test/zxing/barcodeimages --try_harder&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well, that is it for now. I will have to experiment with some lower quality images, to see how the results stack up in a real test.  (Once I find a supported phone ...)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6967144745647087497?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6967144745647087497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6967144745647087497&amp;isPopup=true' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6967144745647087497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6967144745647087497'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/seeing-stripes-experiment-with-zxing.html' title='Seeing Stripes: Experiment with ZXing'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4MgprHLfxvM/SwZpi4GTWiI/AAAAAAAAAdk/VgW-Guq_KEY/s72-c/ColdFusion_ZXing_Results.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7999640680040604170</id><published>2009-11-18T16:01:00.000-08:00</published><updated>2009-12-01T03:12:32.379-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>SOT: Who is the fairest browser of them all?</title><content type='html'>I have long been a fan of Firefox. But somewhere in between versions 2 and 3.5 it started behaving like a black-hole of resources, sucking up more and more memory, growing increasing sluggish. Not to mention taking forever to start up.  So fickle user that I am, I have been trying out other browsers while I give Firefox one last chance before giving it the boot.&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Of course one of the browsers I am (re-)trying is Chrome. I did use it briefly when it first came out. But quickly gravitated back to my beloved Firefox, with all of its wonderful extensions and flexible configuration.  But I will admit Chrome is extremely fast. No news there. What was a nice surprise was its mini-Task-Manager (Shft-Esc) and the "Stats for Geeks" breakdown.&lt;br /&gt;&lt;br /&gt;Meanwhile, I did some file shuffling and installed a completely fresh copy of FireFox 3.5.5. Just to see if I could get a sense of whether the true culprit was FireFox itself, a specific setting or one of my plugins. I tried to start with as little functionality and minimal settings as possible.   Not all of them are relevant. But in the interest of full disclosure, here is a run down of the changes I made to the default settings:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Plugins:&lt;/span&gt;&lt;br /&gt;- *Disabled* all of the plugins detected by default (EXCEPT Shockwave Flash 10.0.32.18)&lt;br /&gt;&lt;br /&gt;I always wondered why my plugin list displayed certain entries I never added explicitly. It turns out it is due to Firefox's automatic scan for common plugins: &lt;a href="http://kb.mozillazine.org/Plugin_scanning#Related_preferences"&gt;http://kb.mozillazine.org/Plugin_scanning#Related_preferences&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Extensions:&lt;/span&gt;&lt;br /&gt;- *Added* Echofon  (aka TwitterFox)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Privacy: &lt;/span&gt;&lt;br /&gt;- *Changed* Remember browsing history to (at least &lt;span style="font-style: italic;"&gt;30 &lt;/span&gt;days)&lt;br /&gt;- *Disabled* Remember search and form history&lt;br /&gt;- *Enabled*  Clear history when Firefox closes: &lt;span style="font-style: italic;"&gt;everything&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Cache:&lt;/span&gt;&lt;br /&gt;- *Changed* Cache settings to use up to &lt;span style="font-style: italic;"&gt;30&lt;/span&gt;MB&lt;br /&gt;Reason: Sometime after upgrading to FF3+, I noticed the autosuggest feature in the location bar had changed. It got progressively slower over time. So I am experimenting with a lower history threshold to see how it performs (before taking the extreme step of disabling it entirely).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Content:&lt;/span&gt;&lt;br /&gt;- *Disabled* Java (No point enabling it since I disabled the plugin)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Startup:&lt;/span&gt;&lt;br /&gt;- *Changed* Show a &lt;span style="font-style: italic;"&gt;blank &lt;/span&gt;page&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update:&lt;/span&gt;&lt;br /&gt;- *Changed*  When updates to Firefox are found: (&lt;span style="font-style: italic;"&gt;Ask me what I want to do&lt;/span&gt;)&lt;br /&gt;&lt;br /&gt;So far Firefox is doing a lot better. Definitely faster, though maybe not quite as fast as Chrome.  At one point I had 15 tabs open in Firefox (only one with Flash Content).   Firefox peaked at around 160-180M memory usage in the windows Task Manager and still remained very responsive.&lt;br /&gt;&lt;br /&gt;Now to start adding back a plugin at a time, and wait for ugly things to happen. Though I have to say I am enjoying reading some of the more &lt;a href="http://www.raymond.cc/blog/archives/2009/08/15/firefox-3-5-slow-and-hangs-after-typing-a-few-letters-in-url-location-bar/#comment-456023"&gt;creative ways people express their displeasure&lt;/a&gt; with the latest versions of Firefox.&lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;br /&gt;&lt;b&gt;Update November 19, 2009:&lt;/b&gt; I am now experimenting with the Firefox 3.6b3 beta and also a plugin called &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/11922"&gt;AFOM 2.0&lt;/a&gt; for memory management. (Note: I do not know if this plugin officially supports 3.6b3 yet).  But the results from my limited testing seem very promising. (Windows only)&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;br /&gt;&lt;b&gt;Update November 27, 2009:&lt;/b&gt; While the plugin helps, there are still issues. I think it is time to declare defeat. The memory problem is definitely Firefox!&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7999640680040604170?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7999640680040604170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7999640680040604170&amp;isPopup=true' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7999640680040604170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7999640680040604170'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/sot-who-is-fairest-browser-of-them-all.html' title='SOT: Who is the fairest browser of them all?'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6742653636928394391</id><published>2009-11-16T02:22:00.000-08:00</published><updated>2010-04-06T02:35:01.424-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Barbecue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CFBarbecue.cfc  (...Just because)</title><content type='html'>While &lt;a href="http://cfsearching.blogspot.com/2009/11/introduction-to-java-barbecue-library.html"&gt;experimenting with the Barbecue library&lt;/a&gt; last week, I put together a cfc for my testing. (You knew that was coming. It is the old developer story:  read, test,  build something, re-test).  Anyway, I decided to post it for anyone else out there experimenting with Barbecue. The cfc can generate any of the 25+ barcodes Barbecue handles, with a full range of settings. (Rather than repeat the same code 25+ times, the cfc uses reflection)&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_4MgprHLfxvM/SwEwRWa-fWI/AAAAAAAAAdM/CnYqhNkdXBc/s1600/CFBarbecue_AllBarcodes.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 234px;" src="http://3.bp.blogspot.com/_4MgprHLfxvM/SwEwRWa-fWI/AAAAAAAAAdM/CnYqhNkdXBc/s320/CFBarbecue_AllBarcodes.png" alt="" id="BLOGGER_PHOTO_ID_5404654102455942498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Keep in mind the Barbecue library also includes servlet, which is extremely easy to use.  Since I was using the built-in webserver at the time, the greatest challenge for me was figuring out how to add a servlet.  Not surprisingly I did not find much in the way of documentation.  But once I finally got it working, the servlet was a snap to use. Just a simple call to a url:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;http://127.0.0.1:8500/barbecue/?data=12345&amp;amp;type=PDF417&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Download CFBarbecue.cfc (See the download widget on the right menu)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="update"&gt;&lt;br /&gt;November 19, 2009: Updated source to include missing lib\jdom.jar. Note: This jar is only needed if you are using the JavaLoader &lt;span style="font-weight:bold;"&gt;and &lt;/span&gt; want SVG functionality.  &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6742653636928394391?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6742653636928394391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6742653636928394391&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6742653636928394391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6742653636928394391'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/cfbarbecuecfc-just-because.html' title='CFBarbecue.cfc  (...Just because)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4MgprHLfxvM/SwEwRWa-fWI/AAAAAAAAAdM/CnYqhNkdXBc/s72-c/CFBarbecue_AllBarcodes.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7618788211264254654</id><published>2009-11-15T20:20:00.000-08:00</published><updated>2009-11-19T13:42:20.480-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rant'/><category scheme='http://www.blogger.com/atom/ns#' term='Misc'/><title type='text'>The Wrong Way to Retrieve the Last Record ID Inserted</title><content type='html'>Hardly a week goes by without seeing some forum post that either uses or recommends my pet peeve:  the erroneous SELECT MAX(id) query. Mind you this is across the board, not just in CF.  For some bizarre reason, this faulty technique never seems to die.  And it REALLY should.  There are so many &lt;span style="font-style: italic;"&gt;correct &lt;/span&gt;alternatives, I cannot understand why anyone would still use it for new code.  If you are even considering it, might I inject a note of sanity and recommend some excellent reading material on Adrian J. Moreno's blog:&lt;br /&gt;&lt;br /&gt;    &lt;div style="text-align: center;"&gt;&lt;a href="http://www.iknowkungfoo.com/blog/index.cfm/2008/6/1/Please-stop-using-SELECT-MAX-id"&gt;Please stop using SELECT MAX(id)&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;(His comments on the topic are much more educational and polite than mine ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7618788211264254654?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7618788211264254654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7618788211264254654&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7618788211264254654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7618788211264254654'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/wrong-way-to-retreive-last-record-id.html' title='The Wrong Way to Retrieve the Last Record ID Inserted'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-713080972105370501</id><published>2009-11-13T10:04:00.000-08:00</published><updated>2009-11-15T20:29:13.278-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Databases'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Everything CFDBINFO Never Told You About Your Database (Connection Metadata)</title><content type='html'>I was doing some debugging and came across the nifty &lt;a href="http://java.sun.com/javase/6/docs/api/java/sql/DatabaseMetaData.html"&gt;java.sql.DatbaseMetaData&lt;/a&gt; class.  It is an interface implemented by the various database drivers and it provides you with a ton of information about both your database and driver capabilities. While you can glean some of the information from &amp;lt;cfdbinfo&amp;gt;, DatbaseMetaData tells you so much more.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;To use it, you need to open a database connection first. If you have full server access, the simplest method is using the internal ServiceFactory. But you could just as easily open your own jdbc connection.   Then call one of the 100+ methods to discover things you may have always wondered about.  For example:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What database or driver version you are using?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What is the maximum number of concurrent connections?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What is the maximum number of tables in an ORDER BY?&lt;br /&gt;&lt;/li&gt;&lt;li&gt;What happens when you concatenate a NULL value with a non-NULL value?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;Apparently, the DatabaseMetaData class can tell you that.   While I would not take all of these values "as gospel", they do provide some solid guidelines.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;myDSN = "MSSQL_2005";&lt;br /&gt;&lt;br /&gt;// open a connection to the datasource&lt;br /&gt;factory = createObject("java", "coldfusion.server.ServiceFactory");&lt;br /&gt;datasource = factory.getDataSourceService().getDataSource( myDSN );&lt;br /&gt;connection = datasource.getConnection();&lt;br /&gt;// extract the database metadata&lt;br /&gt;metadata = connection.getMetaData();&lt;br /&gt;&lt;br /&gt;results = {};&lt;br /&gt;&lt;br /&gt;// Display version information&lt;br /&gt;results["getJDBCMajorVersion()"] = metadata.getJDBCMajorVersion();&lt;br /&gt;results["getJDBCMinorVersion()"] = metadata.getJDBCMinorVersion();&lt;br /&gt;results["getDriverMinorVersion()"] = metadata.getDriverMinorVersion();&lt;br /&gt;results["getDriverName()"] = metadata.getDriverName();&lt;br /&gt;results["getDriverVersion()"] = metadata.getDriverVersion();&lt;br /&gt;results["getDatabaseMajorVersion()"] = metadata.getDatabaseMajorVersion();&lt;br /&gt;results["getDatabaseMinorVersion()"] = metadata.getDatabaseMinorVersion();&lt;br /&gt;results["getDatabaseProductName()"] = metadata.getDatabaseProductName();&lt;br /&gt;results["getDatabaseProductVersion()"] = metadata.getDatabaseProductVersion();&lt;br /&gt;&lt;br /&gt;// cleanup&lt;br /&gt;connection.close();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfdump var="#results#" label="[#myDSN#] java.sql.DatbaseMetaData" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;As there are so many functions, I used a bit of reflection to quickly dump all of the simple properties into a structure.  (See the full code at the end of the entry).  It was interesting to see how the metadata differed across drivers. Both in what information was exposed and the results of the core methods.  Notice the sql keywords differ when using the JTDS driver and the built-in CF8 driver.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note: Unfortunately, getSQLKeywords() only returns potential keywords that are &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; also ansi sql:2003 reserved words.  But with a little effort you could easily create a function to list of all potential keywords.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;CF8 Driver&lt;/b&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_4MgprHLfxvM/Sv2jhVN-4nI/AAAAAAAAAdE/bppv_ByOJjA/s1600-h/ColdFusion_MacromediaDriver_DatabaseMetaData.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://3.bp.blogspot.com/_4MgprHLfxvM/Sv2jhVN-4nI/AAAAAAAAAdE/bppv_ByOJjA/s320/ColdFusion_MacromediaDriver_DatabaseMetaData.png" alt="" id="BLOGGER_PHOTO_ID_5403654920941265522" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;JTDS Driver&lt;/b&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_4MgprHLfxvM/Sv2jhDSDaSI/AAAAAAAAAc8/5QgttTrCNL8/s1600-h/ColdFusion_JTDSDriver_DatabaseMetaData.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 202px;" src="http://3.bp.blogspot.com/_4MgprHLfxvM/Sv2jhDSDaSI/AAAAAAAAAc8/5QgttTrCNL8/s320/ColdFusion_JTDSDriver_DatabaseMetaData.png" alt="" id="BLOGGER_PHOTO_ID_5403654916126501154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The metadata contains all kinds of interesting information.  So if you ever wondered about your database or driver capabilities, read up on java.sql.DatbaseMetaData. What it reveals could surprise you.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Full Code&lt;/b&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;myDSN = "MSSQL_2005";&lt;br /&gt;&lt;br /&gt;// open a connection to the datasource&lt;br /&gt;factory = createObject("java", "coldfusion.server.ServiceFactory");&lt;br /&gt;datasource = factory.getDataSourceService().getDataSource( myDSN );&lt;br /&gt;connection = datasource.getConnection();&lt;br /&gt;// extract the database metadata&lt;br /&gt;connMetadata = connection.getMetaData();&lt;br /&gt;&lt;br /&gt;// get all methods in the metadata class&lt;br /&gt;allMethods = connMetadata.getClass().getDeclaredMethods();&lt;br /&gt;Modifier = createObject("java", "java.lang.reflect.Modifier");&lt;br /&gt;&lt;br /&gt;results = {};&lt;br /&gt;&lt;br /&gt;// Execute all simple methods and store the results&lt;br /&gt;for(x=1; x &amp;lt;= arrayLen(allMethods); x++)&lt;br /&gt;{&lt;br /&gt;    method = allMethods[x];&lt;br /&gt;&lt;br /&gt;    // Get the parameters for the current method&lt;br /&gt;    parameters = method.getParameterTypes();&lt;br /&gt;&lt;br /&gt;    // If this is a simple method, requiring no extra information ..&lt;br /&gt;    if (Modifier.isPublic(method.getModifiers()))&lt;br /&gt;    {&lt;br /&gt;        if (not arrayLen(parameters) AND method.getName() neq "getConnection")&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                // run the current method&lt;br /&gt;                data = method.invoke( connMetadata, parameters );&lt;br /&gt;                // convert resultsets to a query object first&lt;br /&gt;                if ( isInstanceOf(data, "java.sql.ResultSet")) {&lt;br /&gt;                    data = createObject("java", "coldfusion.sql.QueryTable").init(data);&lt;br /&gt;                }&lt;br /&gt;                results[method.getName()] = data;&lt;br /&gt;            }&lt;br /&gt;            catch(java.lang.Exception e)&lt;br /&gt;            {&lt;br /&gt;                results[method.getName()] = e.message;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;connection.close() ;&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfdump var="#results#" label="connection.getMetaData() " /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-713080972105370501?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/713080972105370501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=713080972105370501&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/713080972105370501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/713080972105370501'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/everthing-cfdbinfo-never-told-you-about.html' title='Everything CFDBINFO Never Told You About Your Database (Connection Metadata)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4MgprHLfxvM/Sv2jhVN-4nI/AAAAAAAAAdE/bppv_ByOJjA/s72-c/ColdFusion_MacromediaDriver_DatabaseMetaData.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-641700617523070996</id><published>2009-11-12T18:16:00.000-08:00</published><updated>2009-11-12T20:15:58.978-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MS SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='Databases'/><title type='text'>MS SQL:  Useless Function Trivia</title><content type='html'>While reviewing some MS SQL 2005 metadata, I stumbled across something I never noticed before. &lt;span id="fullpost"&gt; It still supports the old ODBC "{fn}" functions.  With the exception of CurDate and CurTime, there is probably not much need for them. (Nor do I find the syntax particularly appealing ...). But still,  it was surprising to find they do still work.  So there is my MS SQL oddity for the day.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt; &lt;br /&gt;&amp;lt;cfquery name="q" datasource="MSSQL_2005"&amp;gt;&lt;br /&gt;    SELECT     &lt;br /&gt;    {fn CurDate()}                       AS [CurrentDate],&lt;br /&gt;    {fn CurTime()}                       AS [CurrentTime],&lt;br /&gt;    {fn DayName( getDate() )}            AS [DayName],&lt;br /&gt;    {fn DayOfMonth( getDate() )}         AS [DayOfMonth],&lt;br /&gt;    {fn DayOfWeek (getDate() )}          AS [DayOfWeek],&lt;br /&gt;    {fn DayOfYear(getDate() )}           AS [DayOfYear],&lt;br /&gt;    {fn Extract(Day From getDate())}     AS [ExtractDay],&lt;br /&gt;    {fn Hour(getDate() )}                AS [Hour],&lt;br /&gt;    {fn Minute(getDate() )}              AS [Minute],&lt;br /&gt;    {fn Month(getDate() )}               AS [Month],&lt;br /&gt;    {fn MonthName(getDate() )}           AS [MonthName],&lt;br /&gt;    {fn Now()}                           AS [Now],&lt;br /&gt;    {fn Quarter(getDate() )}             AS [Quarter],&lt;br /&gt;    {fn Second(getDate() )}              AS [Second],&lt;br /&gt;    {fn Week(getDate() )}                AS [Week],&lt;br /&gt;    {fn Year(getDate() )}                AS [Year], &lt;br /&gt;    {fn TimestampAdd(SQL_TSI_DAY, 14, getDate())}    AS [TimestampAdd],&lt;br /&gt;    {fn TimestampDiff(SQL_TSI_DAY, '2009-10-31', getDate())} AS [TimestampDiff]    &lt;br /&gt;&amp;lt;/cfquery&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#q#" label="Old MS SQL Functions fn{}" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-641700617523070996?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/641700617523070996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=641700617523070996&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/641700617523070996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/641700617523070996'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/ms-sql-useless-function-trivia.html' title='MS SQL:  Useless Function Trivia'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7990582100506039386</id><published>2009-11-12T17:38:00.000-08:00</published><updated>2009-11-12T20:46:26.714-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Humor'/><title type='text'>OT:  Lame error messages</title><content type='html'>So I was having fun, trying to break things, and came across a lame excuse only a computer could get away with:&lt;br /&gt;&lt;br /&gt;  &lt;blockquote style="font-family: courier new;"&gt;com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: memory exhausted. &lt;/blockquote&gt;&lt;br /&gt;I can see it now:  "Sorry Boss-man. No can do. &lt;span style="font-style: italic;"&gt;Geez&lt;/span&gt;, my memory is exhausted. I need time to relax, recharge, reboot. Check back with me tomorrow."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7990582100506039386?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7990582100506039386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7990582100506039386&amp;isPopup=true' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7990582100506039386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7990582100506039386'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/ot-lame-error-messages.html' title='OT:  Lame error messages'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-547314640284725416</id><published>2009-11-08T17:33:00.000-08:00</published><updated>2010-04-05T22:46:34.098-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Barbecue'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: Introduction to the Java Barbecue Library (For Beginners)</title><content type='html'>Just to get this out of the way: if you are looking for a CF wrapper for the Barbecue library, this is &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; the entry for you. If you are interested in the basics of using Barbecue, feel free to read on.&lt;br /&gt;&lt;br /&gt;Why write yet another entry on Barbecue? Well, I was recently reading about barcodes, for my own edification, and did not find many &lt;span style="font-style: italic;"&gt;introductory&lt;/span&gt; resources (you know ... ones that ask and answer those silly novice questions?).  So decided to write up my findings and first impressions, in the hopes of providing someone else with a starting point in their research. Even if they are not using CF.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Background on Barcodes&lt;/span&gt;&lt;br /&gt;Obviously using the library requires you know at least a little bit about the different bar code types.  For example, some encode numeric digits only, others have different limits as to how many characters they can encode, etcetera.  Two of the more helpful references I came across were: &lt;a href="http://www.makebarcode.com/specs/speclist.html" target="_blank&amp;quot;"&gt;Different Types of Barcodes&lt;/a&gt; and a high level &lt;a href="http://www.makebarcode.com/specs/barcodechart.html" target="_blank&amp;quot;"&gt;Barcode Comparison Chart&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Installing the Barbecue Library&lt;/span&gt;&lt;br /&gt;Using the Barbecue library is very simple. Just download the library from sourceforge.net and extract the main jar from the .zip file. The current jar version is: barbecue-1.5-beta1.jar. Then place the main jar somewhere in your CF classpath, such as: C:\ColdFusion8\wwwroot\WEB-INF\lib. Finally restart the ColdFusion server so it will detect the jar.&lt;br /&gt;&lt;br /&gt;Another option is to use Mark Mandel's &lt;a href="http://www.compoundtheory.com/?action=displayCategory&amp;amp;ID=22"&gt;JavaLoader.cfc&lt;/a&gt;, which is the option I chose. Just load the Barbecue jar in your array of paths, and create a new instance of the JavaLoader. (Obviously, this is just for demonstration. Usually you &lt;a href="http://www.compoundtheory.com/?action=displayPost&amp;amp;ID=212"&gt;store the javaLoader instance in the server scope to avoid memory leaks&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note: The jdom.jar must also be added to the JavaLoader paths if you intend to use Barbecue's SVG functionality. &lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset paths = [] /&amp;gt;&lt;br /&gt;&amp;lt;cfset arrayAppend(paths, expandPath('barbecue-1.5-beta1/barbecue-1.5-beta1.jar')) /&amp;gt;&lt;br /&gt;&amp;lt;cfset arrayAppend(paths, expandPath('barbecue-1.5-beta1/lib/jdom.jar')) /&amp;gt;&lt;br /&gt;&amp;lt;cfset loader = createObject("component", "javaloader.JavaLoader").init( paths ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-size: 100%; font-weight: bold;"&gt;Factory Workers: (So much for progress..&lt;/span&gt;&lt;span style="font-size: 100%;"&gt;)&lt;/span&gt;&lt;br /&gt;I found the easiest way to work with bar codes was using the factory classes. The factories provide easy to use static methods that make it a breeze to create, format and save barcodes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Creating a Barcode&lt;/span&gt;&lt;br /&gt;To a create a barcode, you use the BarcodeFactory. This class contains about 25+ methods for creating several different types of barcodes, such as  Interleaved 2 or 5, EAN128, etcetera.  Currently, only one 2d bacode is supported: PDF417.  The methods are intuitively named, and most require only the string to be encoded.  For example, to create a Bookland barcode, just grab a reference to the Factory and call the createBookland() method with the value you wish to encode:&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset factory = loader.create("net.sourceforge.barbecue.BarcodeFactory") /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode = factory.createBookland( "0123456789" ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Creating a Barcode Image (Simple)&lt;/span&gt;&lt;br /&gt;Now the object returned from the BarCodeFactory is not image. It is an instance of one of the Barbecue classes: &lt;span style="font-family: courier new;"&gt;net.sourceforge.barbecue.Barcode&lt;/span&gt;.    But there are several easy ways for converting the barcode object into an image.    I found at least five (5) methods. (There is a catch to a few of them, but more about that in a minute) .&lt;br /&gt;&lt;br /&gt;The first three (3) options use the &lt;span style="font-family: courier new;"&gt;BarcodeImageHandler&lt;/span&gt; factory.  It has a few handy methods for converting a barcode object to either an in memory image or to a physical file.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(1) Generating a BufferedImage&lt;/span&gt;&lt;br /&gt;To convert a barcode object to a BufferedImage, simply grab a reference to the factory, then call the getImage() method.  To display or manipulate the BufferedImage in CF, just wrap it in a CF image object. &lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset ImageHandler = loader.create("net.sourceforge.barbecue.BarcodeImageHandler") /&amp;gt;&lt;br /&gt;&amp;lt;cfset buffImage = ImageHandler.getImage( barcode ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcodeImage = ImageNew(buffImage) /&amp;gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#barcodeImage#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;(2) Writing Images to an OutputStream&lt;/span&gt;&lt;br /&gt;You can also write the image directly to an &lt;a href="http://java.sun.com/javase/6/docs/api/java/io/OutputStream.html"&gt;OutputStream&lt;/a&gt;. There are various uses of OuputStream's, such as &lt;a href="http://blogs.adobe.com/cantrell/archives/2003/06/using_coldfusio.html"&gt;streaming images to the browser&lt;/a&gt;.  There is probably less need for that particular technique in later versions of CF.  But as there are several different types of streams, it is good to be aware of this option.&lt;br /&gt;&lt;br /&gt;The image handler has three (3) methods for writing images to a stream: writePNG(), writeGIF() and writeJPG(). As their names imply, they generate an image in the desired format and write the image bytes to the supplied stream.  You can then use the stream however you wish:&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset ImageHandler = loader.create("net.sourceforge.barbecue.BarcodeImageHandler") /&amp;gt;&lt;br /&gt;&amp;lt;cfset outStream = loader.create("java.io.ByteArrayOutputStream").init() /&amp;gt;&lt;br /&gt;&amp;lt;cfset ImageHandler.writePNG( barcode, outStream ) /&amp;gt;&lt;br /&gt;&amp;lt;!--- 1) Display the image using cfimage ... ---&amp;gt;&lt;br /&gt;&amp;lt;cfset barcodeImage = ImageNew(outStream.toByteArray()) /&amp;gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#barcodeImage#" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- 2) OR .. using cfcontent ... ---&amp;gt;&lt;br /&gt;&amp;lt;cfcontent type="image/png" variable="#outStream.toByteArray()#" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;(3) Saving Images to a File&lt;/span&gt;&lt;br /&gt;Lastly, the handler has three methods for saving barcode images to a physical file: saveGIF(), saveJPG() and savePNG().  It is much like the previous option, only you pass in a &lt;a href="http://java.sun.com/javase/6/docs/api/java/io/File.html"&gt;java.io.File&lt;/a&gt; object representing the output file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset ImageHandler = loader.create("net.sourceforge.barbecue.BarcodeImageHandler") /&amp;gt;&lt;br /&gt;&amp;lt;cfset IOFile = loader.create("java.io.File") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- save the barcode in three (3) different formats  ---&amp;gt;&lt;br /&gt;&amp;lt;cfset imageFile = IOFile.init( ExpandPath("myBarcode.gif") ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset ImageHandler.saveGIF( barcode, imageFile ) /&amp;gt;&lt;br /&gt;&amp;lt;img src="myBarcode.gif" alt="GIF  Format" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;Now earlier I mentioned a catch. In my tests, the generated images all had a black border along the bottom of the barcode. I am guessing it has something to do with the canvas color of the image object.  One way I was able to remove it, was by creating a blank image first. So I could control the canvas color. Then use some lower level methods to draw the barcode onto my image.  That brings me to the other two (2) options for creating images.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/SveYxNcTnWI/AAAAAAAAAbk/8Ent2dnahAA/s1600-h/myBarcode.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5401954249243598178" src="http://1.bp.blogspot.com/_4MgprHLfxvM/SveYxNcTnWI/AAAAAAAAAbk/8Ent2dnahAA/s400/myBarcode.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Creating a Barcode Image (Advanced)&lt;/span&gt;&lt;br /&gt;While not as easy as using the factory methods, you can also use two methods within the &lt;a href="http://barbecue.sourceforge.net/apidocs/net/sourceforge/barbecue/Barcode.html#draw%28java.awt.Graphics2D,%20int,%20int%29"&gt;Barcode&lt;/a&gt; class itself to generate an image.  But unlike using the image factory, it is strictly B.Y.O.  (bring your own) .. image.  You must already have a blank image in order to use these methods. They are probably what the BarcodeImageFactory uses behind the scenes.   However, I thought I would point them out to explain how they work.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1)  Using Barcode.draw(graphics, x, y)&lt;/span&gt;&lt;br /&gt;The first, and simpler, method is: &lt;span style="font-family: courier new;"&gt;draw()&lt;/span&gt;.  To use it,  I just created a blank CF image.  Since the default canvas color for "rgb" images is black, I changed it to white.   Then extracted the graphics object from my image and passed it into the draw function.  The result was a barcode without that bottom border.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_4MgprHLfxvM/SvefvC3kZiI/AAAAAAAAAbs/yfHTkc7MKYo/s1600-h/ColdFusion_Barbecue_Bookland_Barcode.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5401961908626810402" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SvefvC3kZiI/AAAAAAAAAbs/yfHTkc7MKYo/s400/ColdFusion_Barbecue_Bookland_Barcode.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- Option 1: RBG image, white canvas ---&amp;gt;&lt;br /&gt;&amp;lt;cfset img = ImageNew("", barcode.getWidth(), barcode.getHeight(), "rgb", "ffffff") /&amp;gt;&lt;br /&gt;&amp;lt;cfset graphics = ImageGetBufferedImage(img).getGraphics() /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.draw( graphics, 0, 0) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#img#"&amp;gt;&lt;br /&gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Option 2: Transparent image ---&amp;gt;&lt;br /&gt;&amp;lt;cfset img = ImageNew("", barcode.getWidth(), barcode.getHeight(), "argb") /&amp;gt;&lt;br /&gt;&amp;lt;cfset graphics = ImageGetBufferedImage(img).getGraphics() /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.draw( graphics, 0, 0) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;div style="background-color: blue;"&amp;gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#img#"&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2)  Using Barcode.output(output)&lt;/span&gt;&lt;br /&gt;The second method is a little more complex.  You probably will not need it.  But still, it is good to know.  The output() method works with an instance of what Barbecue calls an &lt;a href="file:///C:/ColdFusion8/wwwroot/cfbarbecue/barbecue-1.5-beta1/docs/apidocs/index.html"&gt;Output&lt;/a&gt; object.  The are several types of Output classes, and they are all just used to convert Barcode objects from one format to another: like to image, svg or eps.&lt;br /&gt;&lt;br /&gt;Since I wanted to create an image, I used the &lt;a href="file:///C:/ColdFusion8/wwwroot/cfbarbecue/barbecue-1.5-beta1/docs/apidocs/index.html"&gt;GraphicsOutput&lt;/a&gt; class.  It is not as complicated as it looks, but it does involve more moving pieces than other options.  Constructing a GraphicsOutput object requires several pieces of information:  the image graphics, barcode font and fore/background colors.  You simply pass these objects into the constructor to create a new Output object.  Then call Barcode.output() to paint the barcode &lt;span style="font-style: italic;"&gt;onto&lt;/span&gt; your image graphics using the supplied settings.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example&lt;/b&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/SvhOpBieU_I/AAAAAAAAAb0/LAl7ZrpHL9k/s1600-h/ColdFusion_Barbecue_GraphicsOutput.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402154219725542386" src="http://1.bp.blogspot.com/_4MgprHLfxvM/SvhOpBieU_I/AAAAAAAAAb0/LAl7ZrpHL9k/s400/ColdFusion_Barbecue_GraphicsOutput.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;Code&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- create a new image and extract the graphics ---&amp;gt;&lt;br /&gt;&amp;lt;cfset img = ImageNew("", barcode.getWidth(), barcode.getHeight(), "rgb", "ffffff") /&amp;gt;&lt;br /&gt;&amp;lt;cfset graphics = ImageGetBufferedImage(img).getGraphics() /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- create the desired font and colors ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Font = createObject("java", "java.awt.Font") /&amp;gt;&lt;br /&gt;&amp;lt;cfset Color = createObject("java", "java.awt.Color") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset barcodeFont = Font.init("Arial", Font.PLAIN, 12 ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset backgroundColor = Color.BLUE /&amp;gt;&lt;br /&gt;&amp;lt;cfset foregroundColor = Color.decode("##008040") /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- grab a Color object that will be used to set the barcode fore/background ---&amp;gt;&lt;br /&gt;&amp;lt;cfset GraphicsOutput = loader.create("net.sourceforge.barbecue.output.GraphicsOutput")&amp;gt;&lt;br /&gt;&amp;lt;cfset gOut = GraphicsOutput.init( graphics, barcodeFont, foregroundColor, backgroundColor ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.output( gOut ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfset ImageWrite( img, ExpandPath("ColdFusion_Barbecue_GraphicsOutput.png")) /&amp;gt;&lt;br /&gt;&amp;lt;!--- display the barcode image ---&amp;gt;&lt;br /&gt;&amp;lt;cfimage action="writeToBrowser" source="#img#"&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Working with Barcode Properties&lt;/span&gt;&lt;br /&gt;Working with the various ways of creating images eventually brought me back to the Barcode class itself, and using its methods to alter some of the default settings.  One of the things that struck me about the Barcode class is that it extends &lt;a href="http://java.sun.com/docs/books/tutorial/uiswing/components/jcomponent.html"&gt;JComponent&lt;/a&gt;. At first that seemed a bit strange, as JComponent is one of the base classes for &lt;a href="http://en.wikipedia.org/wiki/Swing_java"&gt;swing&lt;/a&gt; gui components.  But further reading revealed Barbecue can be used in servlets or swing applications. So extending JComponent made more sense.&lt;br /&gt;&lt;br /&gt;Now I mentioned swing for a reason.  After testing various Barcode properties,  I quickly realized many of the properties only apply if you are using swing.  For example, there are several methods for adjusting width and height.  But they had no effect when using images.  Considering these methods are inherited from JComponent, that makes sense.   (Not that you can really force the barcode dimensions anyway).    An &lt;a href="http://blog.adampresley.com/2009/barbecue-barcode-coldfusion-and-size/"&gt;entry on Adam Presley's blog&lt;/a&gt; confirmed my suspicion.  You cannot set the dimensions explicitly.  But instead should use the barWidth and barHeight properties to adjust the overall barcode size.&lt;br /&gt;&lt;br /&gt;Here are some of the more useful Barcode properties.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setBarWidth()/setBarHeight()&lt;/span&gt;&lt;br /&gt;These methods can be used to set the width of the thinnest bar or the height of a single bar, &lt;span style="font-style: italic;"&gt;within &lt;/span&gt;the overall barcode.  You may need to experiment to get the correct settings. So you do not end up with an invalid barcode or one that does not render properly ;)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;setBarWidth(&lt;/span&gt; 6 )&lt;/span&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_4MgprHLfxvM/SviiZSjWe0I/AAAAAAAAAb8/QFCTa13mjcs/s1600-h/ColdFusion_Barbecue_setBarWidth.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402246308391451458" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SviiZSjWe0I/AAAAAAAAAb8/QFCTa13mjcs/s400/ColdFusion_Barbecue_setBarWidth.png" style="cursor: pointer; display: block; height: 31px; margin: 0px auto 10px; text-align: center; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset BarcodeFactory = loader.create("net.sourceforge.barbecue.BarcodeFactory") /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode = BarcodeFactory.createStd2of5( "0123456789" ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.setBarWidth( 6 ) /&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setDrawingQuietSection(boolean)&lt;/span&gt;&lt;br /&gt;This setting controls whether extra whitespace (ie quiet zone) should be rendered.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;	&amp;lt;cfset barcode.setDrawingQuietSection( false ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;setDrawingQuietSection(true)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/Svim77qK88I/AAAAAAAAAcM/zI-Bp41HtXs/s1600-h/ColdFusion_Barbecue_setDrawingQuietSectionTrue.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402251301587973058" src="http://4.bp.blogspot.com/_4MgprHLfxvM/Svim77qK88I/AAAAAAAAAcM/zI-Bp41HtXs/s400/ColdFusion_Barbecue_setDrawingQuietSectionTrue.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;setDrawingQuietSection(false)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/Svim7hvkQHI/AAAAAAAAAcE/d71_qSQsDmE/s1600-h/ColdFusion_Barbecue_setDrawingQuietSectionFalse.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402251294631280754" src="http://1.bp.blogspot.com/_4MgprHLfxvM/Svim7hvkQHI/AAAAAAAAAcE/d71_qSQsDmE/s400/ColdFusion_Barbecue_setDrawingQuietSectionFalse.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 204px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setDrawingText(boolean)&lt;/span&gt;&lt;br /&gt;This setting controls whether the barcode data (ie un-encoded) is displayed beneath the barcode.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;	&amp;lt;cfset barcode.setDrawingText( false ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;setDrawingText(false)&lt;/span&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/Svio0HXhGAI/AAAAAAAAAcU/6x98JzapJBo/s1600-h/ColdFusion_Barbecue_setDrawingTextFalse.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402253366315259906" src="http://4.bp.blogspot.com/_4MgprHLfxvM/Svio0HXhGAI/AAAAAAAAAcU/6x98JzapJBo/s400/ColdFusion_Barbecue_setDrawingTextFalse.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setLabel(string)&lt;/span&gt;&lt;br /&gt;This method should allow you to override the text displayed beneath the barcode. But I was not able to get this setting to work.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setFont(java.awt.Font)&lt;/span&gt;&lt;br /&gt;This method allows you to use a different font for any text displayed beneath the barcode.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset Font = createObject("java", "java.awt.Font") /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcodeFont = Font.init("Arial", Font.ITALIC, 12) /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.setFont( barcodeFont ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;setFont( [Arial, Italic, size 12] )&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="http://1.bp.blogspot.com/_4MgprHLfxvM/Svitd94nWXI/AAAAAAAAAc0/WEGOiKBcA9c/s1600-h/ColdFusion_Barbecue_setFont.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402258483370744178" src="http://1.bp.blogspot.com/_4MgprHLfxvM/Svitd94nWXI/AAAAAAAAAc0/WEGOiKBcA9c/s400/ColdFusion_Barbecue_setFont.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setBackground(java.awt.Color)/setForeground(&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;java.awt.Color)&lt;/span&gt;&lt;br /&gt;These methods can be used to change the foreground or background colors of the barcode. They are inherited from JComponent, but are used by the Barcode class.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;!--- change foreground ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Color = createObject("java", "java.awt.Color") /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.setForeground( Color.RED ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- change background (hex color) ---&amp;gt;&lt;br /&gt;&amp;lt;cfset Color = createObject("java", "java.awt.Color") /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode.setBackground( Color.decode("##0080c0") ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-style: italic;"&gt;setForeground()&lt;/span&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/_4MgprHLfxvM/SvitN30tbkI/AAAAAAAAAck/663jeHOEgxU/s1600-h/ColdFusion_Barbecue_setForeground.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402258206865845826" src="http://3.bp.blogspot.com/_4MgprHLfxvM/SvitN30tbkI/AAAAAAAAAck/663jeHOEgxU/s400/ColdFusion_Barbecue_setForeground.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-style: italic; text-align: center;"&gt;setBackground()&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_4MgprHLfxvM/SvitN-uyebI/AAAAAAAAAcs/xCf0F_Z7ocs/s1600-h/ColdFusion_Barbecue_setBackground.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5402258208720058802" src="http://4.bp.blogspot.com/_4MgprHLfxvM/SvitN-uyebI/AAAAAAAAAcs/xCf0F_Z7ocs/s400/ColdFusion_Barbecue_setBackground.png" style="cursor: pointer; display: block; height: 50px; margin: 0px auto 10px; text-align: center; width: 226px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Barcode.setResolution(int)&lt;/span&gt;&lt;br /&gt;Used to adjust the resolution. Default is 72dpi.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;	&amp;lt;cfset barcode.setResolution( 300 ) /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;"&gt;SVG&lt;/span&gt;&lt;br /&gt;You can also convert barcode objects to svg.  Simply grab a reference to the SVGFormatter class, then call the formatAsSVG() method.  The result is an svg string.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Code:&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre class="xhtml" name="code"&gt;&amp;lt;cfset BarcodeFactory = loader.create("net.sourceforge.barbecue.BarcodeFactory") /&amp;gt;&lt;br /&gt;&amp;lt;cfset barcode = BarcodeFactory.createBookland( "0123456789" ) /&amp;gt;&lt;br /&gt;&amp;lt;cfset SVGFormatter = loader.create("net.sourceforge.barbecue.formatter.SVGFormatter") /&amp;gt;&lt;br /&gt;&amp;lt;cfset svgString = SVGFormatter.formatAsSVG( barcode )&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-style: italic;"&gt;Related Entries:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://cfsearching.blogspot.com/2009/11/cfbarbecuecfc-just-because.html"&gt;CFBarbecue.cfc  (...Just because)&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href="http://cfsearching.blogspot.com/2009/11/seeing-stripes-experiment-with-zxing.html"&gt;Seeing Stripes: Experiment with ZXing&lt;/a&gt;&lt;br /&gt;&lt;a href="http://cfsearching.blogspot.com/2009/11/cfbarbecuecfc-just-because.html"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-547314640284725416?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/547314640284725416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=547314640284725416&amp;isPopup=true' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/547314640284725416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/547314640284725416'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/introduction-to-java-barbecue-library.html' title='ColdFusion: Introduction to the Java Barbecue Library (For Beginners)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/SveYxNcTnWI/AAAAAAAAAbk/8Ent2dnahAA/s72-c/myBarcode.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2702005227978122575</id><published>2009-11-07T20:54:00.000-08:00</published><updated>2009-11-08T21:06:01.172-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Humor'/><title type='text'>OT: ColdFusion Trials (Let's Do The Time Warp Again)</title><content type='html'>I was checking my "trials" email folder the other day and these messages gave me a chuckle.  That and the fact that I received a "Your ColdFusion 9 trial starts now" message, before my download had even finished! Can you spot what is wrong here?&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_4MgprHLfxvM/SvZPSUSvdcI/AAAAAAAAAbc/ylReK1xGXdA/s1600-h/ColdFusionTrial_TimeWarp.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 33px;" src="http://1.bp.blogspot.com/_4MgprHLfxvM/SvZPSUSvdcI/AAAAAAAAAbc/ylReK1xGXdA/s400/ColdFusionTrial_TimeWarp.png" alt="" id="BLOGGER_PHOTO_ID_5401591979181045186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:78%;"&gt;Yes... I did download the ColdFusion 9 Trial previously.  But it still made me laugh ;) &lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2702005227978122575?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2702005227978122575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2702005227978122575&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2702005227978122575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2702005227978122575'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/ot-coldfusion-trials-lets-do-time-warp.html' title='OT: ColdFusion Trials (Let&apos;s Do The Time Warp Again)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/SvZPSUSvdcI/AAAAAAAAAbc/ylReK1xGXdA/s72-c/ColdFusionTrial_TimeWarp.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6547064205507786272</id><published>2009-11-07T20:18:00.000-08:00</published><updated>2009-11-08T01:17:50.553-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion: Small Try/Catch Gotcha With CreateObject() and Exceptions</title><content type='html'>Exceptions can be deceptive and loathsome creatures at times.  Case in point, I was happily using createObject() to load an object from a java jar in my classpath. I then added a try/catch. So I could detect when the jar probably was not added to the CF classpath properly, and display a more meaningful error message.&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;  handler = createObject("java", "net.sourceforge.barbecue.BarcodeImageHandler");&lt;br /&gt;}      &lt;br /&gt;catch(java.lang.ClassNotFoundException e)&lt;br /&gt;{&lt;br /&gt;  throwError(message="Verify the Barbecue jar is in your CF classpath", type="SupportingClassNotFound");      &lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Great in theory, the only problem was my try/catch did not work. I double checked the stack trace and it sure seemed like I was catching the correct exception type: &lt;span style="font-family:courier new;"&gt;java.lang.ClassNotFoundException&lt;/span&gt;. So I tried the broader type java.lang.Exception. Then cfdump'd the details, to see if I could spot the problem.  Sure enough, the actual exception type was &lt;span style="font-style: italic;"&gt;not&lt;/span&gt; what CF was reporting on the error screen.  The actual exception type being:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;coldfusion.runtime.java.JavaObjectClassNotFoundException&lt;/span&gt;.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;(Boy, what a mouthful. As if the base exception name is not long enough already...?)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/SvZGSMU_dJI/AAAAAAAAAbU/Fmx8Q1dCPoQ/s1600-h/ColdFusion_JavaObjectClassNotFoundException.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 102px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/SvZGSMU_dJI/AAAAAAAAAbU/Fmx8Q1dCPoQ/s320/ColdFusion_JavaObjectClassNotFoundException.png" alt="" id="BLOGGER_PHOTO_ID_5401582081438348434" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Apparently the stack trace in the error page was displaying the &lt;span style="font-family:courier new;"&gt;RootCause&lt;/span&gt;, not the actual exception thrown.  While that makes some&lt;span style="font-style: italic;"&gt; &lt;/span&gt;sense, unfortunately the &lt;span style="font-style: italic;"&gt;thrown &lt;/span&gt;exception type is what is needed to catch the darned thing.  Anyway, once I changed my try/catch to use the &lt;span&gt;actual&lt;/span&gt; exception type being thrown, everything was just dandy.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;  handler = createObject("java", "net.sourceforge.barbecue.BarcodeImageHandler");&lt;br /&gt;}        &lt;br /&gt;catch(coldfusion.runtime.java.JavaObjectClassNotFoundException e)&lt;br /&gt;{&lt;br /&gt;  throwError(message="Verify the Barbecue jar is in your CF classpath", type="SupportingClassNotFound");        &lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;What is the world coming to when you cannot even trust error messages Oh, wait. Scratch that. Error messages lie all the time. I am sure they do not &lt;span style="font-style: italic;"&gt;mean to lie&lt;/span&gt;, they just hold back critical information when you most need it. The secretive little trolls ;)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6547064205507786272?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6547064205507786272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6547064205507786272&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6547064205507786272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6547064205507786272'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/coldfusion-small-trycatch-gotcha-with.html' title='ColdFusion: Small Try/Catch Gotcha With CreateObject() and Exceptions'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/SvZGSMU_dJI/AAAAAAAAAbU/Fmx8Q1dCPoQ/s72-c/ColdFusion_JavaObjectClassNotFoundException.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3435542271634332880</id><published>2009-11-07T09:15:00.000-08:00</published><updated>2009-11-07T09:40:41.645-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>No more use for StructFind() ?</title><content type='html'>For some reason I always forget about &lt;a href="http://www.coldfusionjedi.com/index.cfm/2007/9/20/A-use-for-structFind"&gt;the one good use for StructFind()&lt;/a&gt;. (Thank goodness for old blog entries). Though it seems even that use is gone in ColdFusion 9. Can anyone think of another one?&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;!--- Works in CF9, not CF8 ---&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;  #getSomeStructure()["dog"]# &lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cffunction name="getSomeStructure" returntype="struct"&amp;gt;&lt;br /&gt; &amp;lt;cfset var myStruct = {} /&amp;gt;&lt;br /&gt; &amp;lt;cfset myStruct.cat = "felix" /&amp;gt;&lt;br /&gt; &amp;lt;cfset myStruct.dog = "clifford" /&amp;gt;&lt;br /&gt; &amp;lt;cfreturn myStruct /&amp;gt;&lt;br /&gt;&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3435542271634332880?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3435542271634332880/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3435542271634332880&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3435542271634332880'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3435542271634332880'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/no-more-use-for-structfind.html' title='No more use for StructFind() ?'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-6690383544647951363</id><published>2009-11-03T18:58:00.000-08:00</published><updated>2009-11-14T13:28:11.776-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iText'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>A Better PdfPageEventHandler with JavaLoader/CFCDynamicProxy</title><content type='html'>&lt;a href="http://cfsearching.blogspot.com/2009/11/javaloader-10-cfcdynamicproxy-i-think-i.html"&gt;Yesterday&lt;/a&gt; , I wrote about discovering a true gem in latest version of Mark Mandel's JavaLoader:  the &lt;a href="http://www.compoundtheory.com/?action=javaloader.index"&gt;CFCDynamicProxy&lt;/a&gt;. This tiny, but powerful, class acts as a wrapper around a ColdFusion cfc.  Essentially allowing it to &lt;span style="font-style: italic;"&gt;mimic&lt;/span&gt; a native java object and communicate directly with other java objects in ways it never could before!  We all know just about everything in ColdFusion boils down to a java object internally. But until now there were certain things you just could not do from a cfc without taking the r-e-a-l-l-y long way around.  Well, the CFCDynamicProxy changes all that.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;A perfect example is page events in iText. In order to add custom headers, footers, etcetera with iText you need a custom java class that implements the &lt;a href="http://cfsearching.blogspot.com/2008/03/using-itexts-pdfpageeventhelper-with.html"&gt;PdfPageEvent&lt;/a&gt; interface. Well as easy and natural as that is in a java environment, it is a bit awkward to have to create and load a new java class in CF every time you wish to create a different set of headers or footers.&lt;br /&gt;&lt;br /&gt;Eventually, I came up with a more dynamic method of calling a cffunction to add headers/footers from a java, but it still required that custom java class. But using the CFCDynamicProxy, I was able to simplify and rewrite the code entirely in CF, and let me say... man what a difference! It is now totally dynamic and written in native CF,  no extra java classes needed. In comparison to the elegance of using the new Proxy, my previous attempt looks like a decrepit, &lt;a href="http://cfsearching.blogspot.com/2008/09/experiment-with-calling-cffunctions.html"&gt;wart-nosed-hag&lt;/a&gt;.  To be fair, a lot of what the previous entry was doing manually is still going on in the background.  But &lt;/span&gt;&lt;span id="fullpost"&gt;the CFCDynamicProxy makes it much, much simpler.&lt;/span&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;The first step in my code beautification effort was creating a CFC that implemented all of the methods in the iText PdfPageEvent interface.  Just as you would if you were implementing a CF interface.  Using the &lt;a href="http://www.1t3xt.info/api/com/lowagie/text/pdf/PdfPageEvent.html"&gt;PdfPageEvent API&lt;/a&gt;, I created a cfc with a function for each of the methods in that interface,  taking care to properly align the arguments and data types so they matched their java counterparts.&lt;br /&gt;&lt;br /&gt;Mapping the java to ColdFusion data types is pretty simple. Any arguments that are instances of a java class (like PdfWriter, Document, Rectangle) are all mapped to type="any". The rest are usually primitive types like "string" and "float" and the &lt;a href="http://livedocs.adobe.com/coldfusion/8/htmldocs/Java_8.html"&gt;conversions&lt;/a&gt; are intuitive, for the most part.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/SvJg6tKlnCI/AAAAAAAAAa0/TsaeZhMaHG4/s1600-h/Itext_PdfPageEvent_API.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 244px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/SvJg6tKlnCI/AAAAAAAAAa0/TsaeZhMaHG4/s320/Itext_PdfPageEvent_API.png" alt="" id="BLOGGER_PHOTO_ID_5400485464843328546" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_4MgprHLfxvM/SvJhARLHqnI/AAAAAAAAAa8/X0n9y9o40fQ/s1600-h/ColdFusion_PdfPageEventHandlerCFC.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 235px;" src="http://1.bp.blogspot.com/_4MgprHLfxvM/SvJhARLHqnI/AAAAAAAAAa8/X0n9y9o40fQ/s320/ColdFusion_PdfPageEventHandlerCFC.png" alt="" id="BLOGGER_PHOTO_ID_5400485560408582770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Next I filled in a few functions needed for generating basic page footers. The key function was onPageEnd, which is where all the action takes place. OnPageEnd will be called by iText just before new pages are written to my new pdf document. So inside that function, I grab the writer object and use it to set the desired properties  and finally write the footer text onto the pdf.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cffunction name="onEndPage" access="public" returntype="void" output="true"&lt;br /&gt;    hint="Called when a page is finished, just before being written to the document."&amp;gt;&lt;br /&gt;&amp;lt;cfargument name="writer" type="any" required="true" hint="Writer for the target pdf. Instance of com.lowagie.text.pdf.PdfWriter" /&amp;gt;&lt;br /&gt;&amp;lt;cfargument name="document" type="any" required="true" hint="Document for target pdf. Instance of com.lowagie.text.Document" /&amp;gt;&lt;br /&gt;&amp;lt;cfset var Local = {} /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;if (len(variables.instance.footerText))&lt;br /&gt;{&lt;br /&gt;     Local.cb = arguments.writer.getDirectContent();&lt;br /&gt;     Local.cb.saveState();&lt;br /&gt;&lt;br /&gt;     Local.cb.beginText();&lt;br /&gt;     Local.cb.setColorFill( variables.instance.textColor );&lt;br /&gt;     Local.cb.setFontAndSize( variables.instance.font, javacast("float", variables.instance.fontSize) );&lt;br /&gt;     Local.cb.setTextMatrix( arguments.document.left(), arguments.document.bottom() - 10);&lt;br /&gt;     Local.text = variables.instance.footerText &amp;amp;" page ["&amp;amp; arguments.writer.getPageNumber() &amp;amp;"]";&lt;br /&gt;     Local.cb.showText( Local.text );&lt;br /&gt;     Local.cb.endText();&lt;br /&gt;&lt;br /&gt;     Local.cb.restoreState();&lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/cffunction&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Having completed my faux-java-class/cfc, the next step was using the CFCDynamicProxy to see if this stuff actually worked.   Using the Dynamic proxy is like using any other jar with the JavaLoader. You just add the new cfcdynamicproxy.jar to the array of paths. Then create an instance of the JavaLoader, except this time you set the &lt;span style="font-family:courier new;"&gt;loadColdFusionClassPath&lt;/span&gt; parameter equal to true. This allows the JavaLoader to access ColdFusion's classes to create the proxy object.  &lt;/span&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:100%;" &gt;Note:  The code example included with JavaLoader 1.0 was very easy to follow.  So my base code is ripped straight out of Mark's example.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;//add the javaloader dynamic proxy library (and the iText jar) to the javaloader&lt;br /&gt;libpaths = [];&lt;br /&gt;arrayAppend(libpaths, expandPath("/javaLoader/support/cfcdynamicproxy/lib/cfcdynamicproxy.jar"));&lt;br /&gt;arrayAppend(libpaths, expandPath("/dev/itext/iText-2.1.7.jar") );&lt;br /&gt;&lt;br /&gt;//we HAVE to load the ColdFusion class path to use the dynamic proxy, as it uses ColdFusion's classes&lt;br /&gt;loader = createObject("component", "javaLoader.JavaLoader").init(loadPaths=libpaths, loadColdFusionClassPath=true);&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once you have an instance of the JavaLoader, instantiate your cfc as usual.  (In my case, I am instantiating my PdfPageEventHander.cfc) The last step is to wrap the cfc in a proxy, which was incredibly simple.  First you create an array of all of the interfaces, your cfc implements. Then grab a reference to the new Dynamic Proxy class and use its createInstance method to create your proxy object.  That is all there is to it.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;//....&lt;br /&gt;//intialize the page event handler component&lt;br /&gt;eventHandler = createObject("component", "PdfPageEventHandler").init( font=textFont, fontSize=10, textColor=textColor);&lt;br /&gt;//add a custom footer&lt;br /&gt;eventHandler.setFooterText( "www.clueless.corp * 85 anywhere blvd * lost city" );&lt;br /&gt;&lt;br /&gt;//we can pass in an array of strings which name all the interfaces we want out dynamic proxy to implement&lt;br /&gt;interfaces = ["com.lowagie.text.pdf.PdfPageEvent"];&lt;br /&gt;&lt;br /&gt;//get a reference to the dynamic proxy class&lt;br /&gt;CFCDynamicProxy = loader.create("com.compoundtheory.coldfusion.cfc.CFCDynamicProxy");&lt;br /&gt;&lt;br /&gt;// create a proxy that we will pass to the iText writer&lt;br /&gt;eventHandlerProxy = CFCDynamicProxy.createInstance(eventHandler, interfaces);&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now for the real test.  I passed my proxy object into my iText writer object, just as I would if it were a native java class:&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;// ...&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;fullPathToOutputFile = ExpandPath("./ABetterPdfPageEventHandler.pdf");&lt;br /&gt;  document = loader.create("com.lowagie.text.Document").init();&lt;br /&gt;  outStream = createObject("java", "java.io.FileOutputStream").init(fullPathToOutputFile);&lt;br /&gt;  writer = loader.create("com.lowagie.text.pdf.PdfWriter").getInstance(document, outStream);&lt;br /&gt;&lt;br /&gt;  // ** register the PROXY as the page event handler **&lt;br /&gt;  writer.setPageEvent( eventHandlerProxy );&lt;br /&gt;      &lt;br /&gt;  document.open();&lt;br /&gt;  Paragraph = loader.create("com.lowagie.text.Paragraph");&lt;br /&gt;  document.add( Paragraph.init("Paragraph Text....") );&lt;br /&gt;  document.newPage();  &lt;br /&gt;  document.add( Paragraph.init("Paragraph Text....") );&lt;br /&gt;  document.newPage();&lt;br /&gt;  document.close();&lt;br /&gt;  outStream.close();&lt;br /&gt;&lt;br /&gt;  WriteOutput("Done!");&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;..  and iText was none the wiser!  Voila, instant footers.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/SvJhWI2Ho5I/AAAAAAAAAbE/mv-kOYc3IkA/s1600-h/ColdFusion_iText_PageFootersA.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 264px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/SvJhWI2Ho5I/AAAAAAAAAbE/mv-kOYc3IkA/s320/ColdFusion_iText_PageFootersA.png" alt="" id="BLOGGER_PHOTO_ID_5400485936130139026" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A few simple changes to my cfc and I had instant headers instead. It feels like writing java code ... except in CF ;)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_4MgprHLfxvM/SvJhZ0Ja1SI/AAAAAAAAAbM/dw1ORISwd68/s1600-h/ColdFusion_iText_PageHeaders.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 170px;" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SvJhZ0Ja1SI/AAAAAAAAAbM/dw1ORISwd68/s320/ColdFusion_iText_PageHeaders.png" alt="" id="BLOGGER_PHOTO_ID_5400485999293420834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You know when I woke up this morning, I thought all of this might have been just a dream. But CFCDynamicProxy is real .. and this class seriously rocks!&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.box.net/shared/5ahr8pl5g3"&gt;Download Example&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-6690383544647951363?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/6690383544647951363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=6690383544647951363&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6690383544647951363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/6690383544647951363'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/better-itext-pdfpageeventhandler-with.html' title='A Better PdfPageEventHandler with JavaLoader/CFCDynamicProxy'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/SvJg6tKlnCI/AAAAAAAAAa0/TsaeZhMaHG4/s72-c/Itext_PdfPageEvent_API.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-484518413438504110</id><published>2009-11-03T15:18:00.000-08:00</published><updated>2009-11-12T05:32:10.273-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>JavaLoader 1.0 / CFCDynamicProxy (I Think I am in Love)</title><content type='html'>So after many weeks, I &lt;span style="font-style: italic;"&gt;finally&lt;/span&gt; got a chance to work with Mark Mandel's JavaLoader 1.0 Beta today, and boy did it put a smile on my face. When I started reading the documentation on the Dynamic Proxy, I nearly fell out of my chair.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;...And there on the other side, read the following words ...&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;In JavaLoader 1.0, I've written a &lt;a href="http://www.compoundtheory.com/?action=displayPost&amp;amp;ID=422"&gt;Dynamic Proxy&lt;/a&gt; that you are able to wrap around a CFC, and thereby make Java Objects think they are interacting with a native Java object, but are in fact, talking to your CFC.&lt;/blockquote&gt;&lt;br /&gt;Holy cow!  If you do any interaction with java from CF (or ever wanted to) I think you can appreciate this phenomenally cool feature.  It means you can hook directly into a java library,  from a CFC.  No need to write and compile a custom java class.  Now obviously it only applies to &lt;a href="http://java.sun.com/docs/books/tutorial/java/concepts/interface.html"&gt;interfaces&lt;/a&gt;.   But hey, most good libraries "program to the interface and not the implementation" anyway.  So this opens up a &lt;span style="font-style: italic;"&gt;lot&lt;/span&gt; of possibilities.&lt;br /&gt;&lt;br /&gt;A good example is adding custom headers and footers with iText. (See this &lt;a href="http://cfsearching.blogspot.com/2008/03/using-itexts-pdfpageeventhelper-with.html"&gt;previous entry&lt;/a&gt; some background on page events).  If you were using java, you would create a custom class that implements the PdfPageEvent &lt;span style="font-family:courier new;"&gt;interface&lt;/span&gt;. By implementing that interface, the custom class can capture certain pdf events like document opened, page added, etcetera. Then the code inside the custom class adds the desired headers, footers, watermarks, etcetera as those events are detected.&lt;br /&gt;&lt;br /&gt;Now that is easy enough to do from java. But until now, it was not possible with ColdFusion alone, because iText requires an instance of a java class to handle the page events. Prior to now there were work-arounds,  but none as elegant as using the Dynamic Proxy.  With the new Proxy, you can simply write the event handler in CF. Then wrap it up in a proxy object and pass the proxy into iText.   iText will think it is dealing with a real java class and simply route the events to your cfc as usual.&lt;br /&gt;&lt;br /&gt;In a relatively short period of time, I was able to &lt;span style="font-style: italic;"&gt;greatly &lt;/span&gt;simplify some old code for adding headers and footers to pdf documents using iText. I will &lt;a href="http://cfsearching.blogspot.com/2009/11/better-itext-pdfpageeventhandler-with.html"&gt;post it shortly&lt;/a&gt; just so you can see how easy it was to interact with iText using the new Dynamic Proxy. I have to say it feels a lot more natural, and I am seeing endless possibilities here.&lt;br /&gt;&lt;br /&gt;I said it before and I will say it again. That Mark Mandel is a freak...'in genius.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-484518413438504110?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/484518413438504110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=484518413438504110&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/484518413438504110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/484518413438504110'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/javaloader-10-cfcdynamicproxy-i-think-i.html' title='JavaLoader 1.0 / CFCDynamicProxy (I Think I am in Love)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-8155590161928543625</id><published>2009-11-03T01:07:00.001-08:00</published><updated>2009-11-03T05:11:49.651-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>What the heck is ConvolveOp? (ImageSharpen Alternative)</title><content type='html'>A &lt;a href="http://forums.adobe.com/message/2362466"&gt;recent question&lt;/a&gt; on the adobe forums mentioned the ImageSharpen() function was adding a black border to the generated image.   As google did not turn up much on the topic, I concluded most people are using alternate methods to sharpen images.   A quick peek at some of the more popular image components confirmed it.   These components all use java's ConvolveOp class, internally, for sharpening.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.alagad.com/projects.imageComponent"&gt;Alagad Image Component&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.opensourcecf.com/imagecfc/"&gt;ImageCFC&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://imageutils.riaforge.org/"&gt;ImageUtil.cfc&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;So what is ConvolveOp?  This article gives a great explanation on how it works, why the border effect occurs and how to avoid it:  &lt;a href="http://www.informit.com/articles/article.aspx?p=1013851&amp;amp;seqNum=5&amp;amp;rll=1"&gt;Java 2D's ConvolveOp Class&lt;/a&gt;. If you are already using one of the components above, you probably do not have to worry about it. But if you are curious about how things work, the article makes a good read.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-8155590161928543625?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/8155590161928543625/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=8155590161928543625&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8155590161928543625'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8155590161928543625'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/what-heck-is-convolveop-imagesharpen.html' title='What the heck is ConvolveOp? (ImageSharpen Alternative)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2948097784966220994</id><published>2009-11-01T22:34:00.000-08:00</published><updated>2009-11-04T19:14:00.331-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CFThread Must Die (Kill Bill) - Part 2</title><content type='html'>In &lt;a href="http://cfsearching.blogspot.com/2009/10/cfthread-must-die-kill-bill-part-1.html"&gt;Part 1&lt;/a&gt; I mentioned the internal CF class coldfusion.thread.Task that seems to be used for running processes with cfthread. Tasks for a given thread can be retrieved from the FusionContext class using a method called getUserThreadTask().  So between the two, you should have enough information for makings of an experimental tracker.&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;Now I was particularly interested in the coldfusion.thread.Task's cancel() method and whether it could be used to kill a cfthread programatically.  So I created a very simple cfthread. The thread itself does very little besides outputting a few messages. But I added a few sleep statements to simulate a thread that would take twenty (20) seconds to execute.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfset threadName = "CFZombieThread_Test" &amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Start the new thread ----&amp;gt;&lt;br /&gt;&amp;lt;cfthread action="run" name="#threadName#" myName="#threadName#"&amp;gt;&lt;br /&gt;&amp;lt;cfset var zombieThreadName = getPageContext().getFusionContext().getCurrentUserThreadName() /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfloop from="1" to="20" index="counter"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;cfoutput&amp;gt;&lt;br /&gt; Mindless groan from zombie thread #zombieThreadName# at #now()# ...&amp;lt;br/&amp;gt;&lt;br /&gt; &amp;lt;/cfoutput&amp;gt;&lt;br /&gt; &amp;lt;!---&lt;br /&gt;     Force the thread to sleep to simulate a long running task&lt;br /&gt; ---&amp;gt;     &lt;br /&gt; &amp;lt;cfset sleep(1 * 1000) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/cfloop&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/cfthread&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Next, I used the ever handy getPageContext() function to grab the FusionContext. I am not extremely familiar with this class. But from what I have learned, it provides executing requests with access to context-sensitive information like session variables, application settings, etcetera. After grabbing the context, I called the getUserThreadTask() method to retrieve the Task associated with my newly created thread.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note:&lt;/span&gt;  When using this method &lt;span style="font-style: italic;"&gt;be sure to convert the thread name to upper case&lt;/span&gt;. I discovered through trial and error that the thread names are stored in some type of case sensitive structure, and all the keys are in upper case.  So if you use mixed, or lower case, the method will not be able to locate your thread.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfset context = getPageContext().getFusionContext() /&amp;gt;&lt;br /&gt;&amp;lt;cfset task = context.getUserThreadTask(UCASE(threadName)) /&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#cfthread[threadName]#" label="#threadName# BEFORE cancel() request " /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next, I forced the current page to take a brief nap, to give my thread a chance to produce some output and prove it was running.  Finally, I used the Task's cancel() method to kill the thread.  Then forced the parent page to sleep again before checking the thread's final status. Just to give the thread a chance to catch its breath.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;!--- Sleep for a few seconds to give the thread a chance to produce some output ...---&amp;gt;&lt;br /&gt;&amp;lt;cfset createObject("java", "java.lang.Thread").currentThread().sleep(2000) /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Now, try and kill the thread ---&amp;gt;&lt;br /&gt;&amp;lt;cfset task.cancel() /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- Finally, give the thread a chance to catch up before we check its final status ...---&amp;gt;&lt;br /&gt;&amp;lt;cfset createObject("java", "java.lang.Thread").currentThread().sleep(500) /&amp;gt;&lt;br /&gt;&amp;lt;cfdump var="#cfthread[threadName]#" label="#threadName# AFTER cancel() request " /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, the thread was successfully terminated.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_4MgprHLfxvM/Su5_tSi_opI/AAAAAAAAAaE/WtK-cCkhoyk/s1600-h/ColdFusionStandard_KillCFThread.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 194px;" src="http://1.bp.blogspot.com/_4MgprHLfxvM/Su5_tSi_opI/AAAAAAAAAaE/WtK-cCkhoyk/s400/ColdFusionStandard_KillCFThread.png" alt="" id="BLOGGER_PHOTO_ID_5399393419313259154" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The next step was storing the thread information in a shared scope. So it could be accessed as needed. Now I know there are a few ways you could approach it and different scopes you could use. But for the sake of simplicity, I decided to have the threads add and remove themselves from a tracker object stored the application scope. It is obviously not as elegant as a built in monitor, and could definitely use improvement. But it was good enough for some simple tests.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt; &amp;lt;!--- Start the new thread ----&amp;gt;&lt;br /&gt; &amp;lt;cfthread action="run" name="#newThreadName#" &amp;gt;&lt;br /&gt;      &lt;br /&gt;         &amp;lt;cfset var myThreadUUID = "" /&amp;gt;&lt;br /&gt;         &amp;lt;cfset var myThreadContext = getPageContext().getFusionContext() /&amp;gt;&lt;br /&gt;         &amp;lt;cfset var myThreadName = myThreadContext.getCurrentUserThreadName() /&amp;gt;&lt;br /&gt;&lt;br /&gt;         &amp;lt;!---&lt;br /&gt;             First, the thread will add itself to the tracker object&lt;br /&gt;         ---&amp;gt;         &lt;br /&gt;         &amp;lt;cfset myThreadUUID = application.threadTracker.addThread(&lt;br /&gt;                                     threadName = myThreadName,&lt;br /&gt;                                     threadTask = myThreadContext.getUserThreadTask(myThreadName)     &lt;br /&gt;                                 ) /&amp;gt;&lt;br /&gt;&lt;br /&gt;         &amp;lt;!---&lt;br /&gt;             DO THREAD STUFF HERE .....&lt;br /&gt;         ---&amp;gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;         &amp;lt;!---&lt;br /&gt;             Finally, the finished thread will remove itself from&lt;br /&gt;             the application tracker object&lt;br /&gt;         ---&amp;gt;         &lt;br /&gt;         &amp;lt;cfset application.threadTracker.removeThread(&lt;br /&gt;                                     threadUUID = myThreadUUID&lt;br /&gt;                                 ) /&amp;gt;&lt;br /&gt; &amp;lt;/cfthread&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Now for the Usual Disclaimers....&lt;/span&gt;&lt;br /&gt;As there is a bit too much code to post, I threw together a small example to demonstrate the concepts.  It is rough and &lt;span&gt;highly experimental&lt;/span&gt;. So use it at your own risk ;) Now I have only had a chance to test it on the Developer version.  I am assuming it will work on the Standard edition too. &lt;/span&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;br /&gt;Anyway, for those interested in how it works, you can &lt;a href="http://www.box.net/shared/fd54bod1h4"&gt;download&lt;/a&gt; the sample code from widget in the right menu. (Absolutely zero time went into window dressing. So if you have delicate eyes, you might want to leave the room now).&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2948097784966220994?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2948097784966220994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2948097784966220994&amp;isPopup=true' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2948097784966220994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2948097784966220994'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/11/cfthread-must-die-kill-bill-part-2.html' title='CFThread Must Die (Kill Bill) - Part 2'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_4MgprHLfxvM/Su5_tSi_opI/AAAAAAAAAaE/WtK-cCkhoyk/s72-c/ColdFusionStandard_KillCFThread.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3417915085366989260</id><published>2009-10-31T23:59:00.000-07:00</published><updated>2009-11-05T13:04:15.405-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>CFThread Must Die (Kill Bill) - Part 1</title><content type='html'>I saw an interesting question on stackoverflow.com last week asking &lt;a href="http://stackoverflow.com/questions/1602346/how-can-i-monitor-cfthread-processes"&gt;how to monitor cfthreads&lt;/a&gt; when using the CF Standard edition. The Enterprise edition comes with a very slick Server Monitor. However, that is off limits if you are running the Standard Edition.  As I am the ever curious type, I decided to do some investigating.  After a lot of digging I eventually came up with some (highly experimental) code that seems to work.  As the experiment revealed a few interesting things about the internals of cfthreads, I decided to post it for the curious masses.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;FX - It's Just an Illusion&lt;/span&gt;&lt;br /&gt;Let me say up front this was a learning exercise. The code is &lt;span style="font-style: italic;"&gt;highly experimental&lt;/span&gt;. I am not gutsy enough to use home-spun code to manage threads on a production system, over a commercial monitoring product.&lt;br /&gt;&lt;br /&gt;Commercial products have several advantages over most home-spun code. First, most monitors use listeners to hook into the server. So they are capable of intercepting events at an early stage and routing them directly to an appropriate handler.   That is far more elegant than trying to handle events after-the-fact in custom code.   Second, commercial products are likely to be more robust and typically more thoroughly tested.  That is especially important when it comes to threads.  Threads can be a magical thing indeed. But if you have ever spent hours chasing down obscure bugs caused by a race condition in a single line of code, then you have a &lt;span style="font-style: italic;"&gt;tiny&lt;/span&gt; inkling of the &lt;span style="font-weight: bold; color: rgb(204, 0, 0);"&gt;extremely&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(204, 0, 0);"&gt; &lt;/span&gt;&lt;span style="color: rgb(204, 0, 0); font-weight: bold;"&gt;bad things &lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;that can happen when threads are mishandled&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;O-k-a-y! Now that I have completely burst your bubble (and hopefully weeded out the reckless in the process) on to the example ..&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Java Connection&lt;/span&gt;&lt;br /&gt;Since cfthread is just a wrapper around java.lang.Thread, my first inclination was to approach the problem from the java angle. So I hit the &lt;a href="http://java.sun.com/docs/books/tutorial/essential/concurrency/runthread.html"&gt;old java trail&lt;/a&gt; and did some reading to brush up on my &lt;a href="http://www.javaworld.com/javaworld/jw-04-1996/jw-04-threads.html"&gt;threads&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now given that you can identify the Thread of the current page with a simple bit of java code, I imagined you could use something similar to locate other threads running on the server.&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;  &amp;lt;cfscript&amp;gt;&lt;br /&gt;CurrentThread = createObject("java", "java.lang.Thread").currentThread();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now threads can belong to ThreadGroups.  ThreadGroups are a bit like directories. They have a hierarchical structure and groups can contain both Threads and other ThreadGroups (ie files and subdirectories).  So in theory you could work your way up the chain to identify all active threads.&lt;br /&gt;&lt;br /&gt;A &lt;a href="http://www.exampledepot.com/egs/java.lang/ListThreads.html"&gt;handy snippet&lt;/a&gt; from the slightly dated javaalmanac.com site provided an example of how to traverse ThreadGroups and display all active threads. With a small modification I was able to output the names of all my active threads. (The image below is a much condensed version)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/Su1ahF6It2I/AAAAAAAAAZs/GgqsHQeVFq4/s1600-h/ColdFusion_ThreadGroupDump.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 89px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/Su1ahF6It2I/AAAAAAAAAZs/GgqsHQeVFq4/s400/ColdFusion_ThreadGroupDump.PNG" alt="" id="BLOGGER_PHOTO_ID_5399071052855293794" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;That is when I noticed something curious. All of the threads I created started with the name "cfthread".  (You have to love development teams that adhere to naming conventions!).  The thread status, or more accurately the &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Thread.State.html"&gt;Thread.State&lt;/a&gt;, is similar to cfthread statuses. But with slightly different names: NEW, RUNNABLE, etcetera.&lt;br /&gt;&lt;br /&gt;So I decided to try a brute force approach and stop() any cfthreads in a RUNNABLE state.  Now, it is worth noting that &lt;a href="http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html"&gt;Thread.stop() was deprecated&lt;/a&gt; because &lt;span style="color: rgb(255, 0, 0);"&gt;it can be unsafe&lt;/span&gt; under certain situations. But as this was just an experiment, I decided to give it a whirl.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;In the Event of a Zombie Attack...&lt;/span&gt;&lt;br /&gt;It seemed to work. But in one or two of my tests, the threads seemed to die. Yet did not seem to be removed from CF's list of running threads. Since the Standard Edition is limited to ten (10) threads, when I tried to fire up new threads they never executed. They just kept piling up in the queue.   I am not sure if it was an anomaly or a flaw in my testing.  But that, combined with the warnings about Thread.stop() convinced me to try a different approach.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Dumpster Diving&lt;/span&gt;&lt;br /&gt;After much digging and copious usage of cfdump, I found a promising method in the FusionContext class called getUserThreadTask(). Following the trail of this method, I discovered that cfthread runs as a type of scheduled task, under a worker thread.  Considering the set-it-and-forget-it nature of threads, the fact that they are scheduled was not that surprising.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/Su1opLVkpmI/AAAAAAAAAZ0/V1qLtRoLsBo/s1600-h/ColdFusion_Filter_FusionContext_CFDump.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 320px;" src="http://4.bp.blogspot.com/_4MgprHLfxvM/Su1opLVkpmI/AAAAAAAAAZ0/V1qLtRoLsBo/s400/ColdFusion_Filter_FusionContext_CFDump.png" alt="" id="BLOGGER_PHOTO_ID_5399086584914290274" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Task class looked extremely promising. It seemed to contain all of the methods I would need for tracking and stopping threads. But it took a bit of work to figure how and when to use the getUserThreadTask() method.  As I will explain in &lt;a href="http://cfsearching.blogspot.com/2009/11/cfthread-must-die-kill-bill-part-2.html"&gt;Part 2&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_4MgprHLfxvM/Su1opQl4KbI/AAAAAAAAAZ8/_mwmO9UyLew/s1600-h/CodlFusion_Thread_Task_CFDump.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 281px; height: 400px;" src="http://1.bp.blogspot.com/_4MgprHLfxvM/Su1opQl4KbI/AAAAAAAAAZ8/_mwmO9UyLew/s400/CodlFusion_Thread_Task_CFDump.png" alt="" id="BLOGGER_PHOTO_ID_5399086586324855218" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;----------------&lt;br /&gt;&lt;span style="font-style: italic;"&gt;* On a totally unrelated note, in case you were wondering, no I did &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; &lt;/span&gt;see the zombie movie referred to in this entry .. thank goodness.&lt;br /&gt;&lt;br /&gt;It is late. Time to pack it in before I turn into a pumpkin.  Happy Halloween ;)&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3417915085366989260?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3417915085366989260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3417915085366989260&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3417915085366989260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3417915085366989260'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/10/cfthread-must-die-kill-bill-part-1.html' title='CFThread Must Die (Kill Bill) - Part 1'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_4MgprHLfxvM/Su1ahF6It2I/AAAAAAAAAZs/GgqsHQeVFq4/s72-c/ColdFusion_ThreadGroupDump.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-2755593420273723555</id><published>2009-10-20T21:04:00.000-07:00</published><updated>2009-10-21T10:23:24.727-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 8 Downloads (They're baaaaack)</title><content type='html'>Well, apparently the &lt;a href="http://forums.adobe.com/message/2328525#2328525"&gt;ColdFusion 8 Downloads are back on Adobe.com&lt;/a&gt;.  While I cannot say I understand why they ever went away in the first place ... it is good to see they are back.  But what with Halloween coming up, you may want to download a copy of CF8 now. Just in case they disappear again ;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-2755593420273723555?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/2755593420273723555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=2755593420273723555&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2755593420273723555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/2755593420273723555'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/10/coldfusion-8-downloads-theyre-baaaaack.html' title='ColdFusion 8 Downloads (They&apos;re baaaaack)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-8813571297077237629</id><published>2009-10-01T18:17:00.000-07:00</published><updated>2009-10-02T19:19:47.041-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 8: Draw a Text Outline on an Image</title><content type='html'>In one of my older entries, I wrote about &lt;a href="http://cfsearching.blogspot.com/2008/01/how-to-fill-text-with-image-using.html"&gt;how to fill text with an image&lt;/a&gt;.  A recent poster asked about doing something similar, except they wanted to draw an &lt;span style="font-style: italic;"&gt;outline&lt;/span&gt; of the text instead of filling it with an image.  As far as I know, this is not supported using the basic ColdFusion image functions.  But there is a great example of how to do this in one of the older &lt;a href="http://java.sun.com/developer/onlineTraining/Media/2DText/index.html"&gt;java2D tutorials&lt;/a&gt;.  While there is not much to the example, it does use a few interesting concepts.  So I decided to write up a quick CF translation.&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;All you need is a new image that supports transparency.  Next, grab the underlying graphics object from the image. You will be using it to draw the text outline onto the image.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;transparentImage = ImageNew("", width, height, "argb");&lt;br /&gt;graphics = ImageGetBufferedImage(transparentImage).createGraphics();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now here is where you veer into the java code. The first step in the example is to enable antialiasing for smoother text.  This is achieved with &lt;a href="http://java.sun.com/javase/6/docs/api/java/awt/RenderingHints.html"&gt;RenderingHints&lt;/a&gt;. If you are not familiar with them, think of them as java's version of ImageSetAntialiasing().&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;RenderingHints = createObject("java", "java.awt.RenderingHints");&lt;br /&gt;graphics.setRenderingHint(     RenderingHints.KEY_ANTIALIASING,&lt;br /&gt;                           RenderingHints.VALUE_ANTIALIAS_ON&lt;br /&gt;                       );&lt;br /&gt;graphics.setRenderingHint(    RenderingHints.KEY_RENDERING,&lt;br /&gt;                           RenderingHints.VALUE_RENDER_QUALITY&lt;br /&gt;                       );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next the example creates a graphical representation of the text. In other words, it gets the &lt;span style="font-style: italic;"&gt;shape&lt;/span&gt; of the rendered text.  This is done with a neat class called TextLayout. TextLayout handles all the hard work of positioning, spacing, text styles and generating the final glyphs.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;Font = createObject("java", "java.awt.Font");&lt;br /&gt;textFont = Font.init("Arial", Font.PLAIN, width / 5 );&lt;br /&gt;textColor = createObject("java", "java.awt.Color").decode("##80aa1c");&lt;br /&gt;fontContext = graphics.getFontRenderContext();&lt;br /&gt;layout = createObject("java", "java.awt.font.TextLayout").init(text, textFont, fontContext);&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But before the text shape can be drawn onto the image, it must be positioned. This is done with an &lt;a href="http://java.sun.com/javase/6/docs/api/java/awt/geom/AffineTransform.html"&gt;AffineTransform&lt;/a&gt;. In this case it is a fancy way of saying move the x,y drawing coordinates. (I tweaked the code example to center the text).&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;transX = (width/2) - (layout.getBounds().getWidth()/2);&lt;br /&gt;transY = (height/2) + layout.getDescent();&lt;br /&gt;transform = createObject("java", "java.awt.geom.AffineTransform").init();&lt;br /&gt;transform.setToTranslation( transX, transY );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally, the example grabs the shape of the text, sets the text color and draws the outline onto the image. That is all there is to it.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;shape = layout.getOutline(transform);&lt;br /&gt;graphics.setColor(textColor);&lt;br /&gt;graphics.draw(shape);&lt;br /&gt;graphics.dispose();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_4MgprHLfxvM/SsVquyoUQWI/AAAAAAAAAZk/DdspJw066GY/s1600-h/ColdFusion_TextOutline_Image.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 329px; height: 298px;" src="http://3.bp.blogspot.com/_4MgprHLfxvM/SsVquyoUQWI/AAAAAAAAAZk/DdspJw066GY/s400/ColdFusion_TextOutline_Image.PNG" alt="" id="BLOGGER_PHOTO_ID_5387829881316065634" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Full Code&lt;/b&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt;   width  = 330;&lt;br /&gt;   height = 150;&lt;br /&gt;   text   = "Crossfade";&lt;br /&gt;    &lt;br /&gt;   // Create a new image that supports transparency&lt;br /&gt;   transparentImage = ImageNew("", width, height, "argb");&lt;br /&gt;   graphics = ImageGetBufferedImage(transparentImage).createGraphics(); &lt;br /&gt;   &lt;br /&gt;   // Add rendering hints to smooth text edges&lt;br /&gt;   RenderingHints = createObject("java", "java.awt.RenderingHints");&lt;br /&gt;   graphics.setRenderingHint(    RenderingHints.KEY_ANTIALIASING,&lt;br /&gt;                               RenderingHints.VALUE_ANTIALIAS_ON&lt;br /&gt;                            );&lt;br /&gt;   graphics.setRenderingHint(   RenderingHints.KEY_RENDERING,&lt;br /&gt;                               RenderingHints.VALUE_RENDER_QUALITY&lt;br /&gt;                            );&lt;br /&gt;&lt;br /&gt;   // Create a graphical representation of the text&lt;br /&gt;   Font = createObject("java", "java.awt.Font");&lt;br /&gt;   textFont = Font.init("Arial", Font.PLAIN, width / 5 );&lt;br /&gt;   textColor = createObject("java", "java.awt.Color").decode("##80aa1c");&lt;br /&gt;   fontContext = graphics.getFontRenderContext();&lt;br /&gt;   layout = createObject("java", "java.awt.font.TextLayout").init(text, textFont, fontContext);&lt;br /&gt;&lt;br /&gt;   // Center text outline &lt;br /&gt;   transX = (width/2) - (layout.getBounds().getWidth()/2);&lt;br /&gt;   transY = (height/2) + layout.getDescent();&lt;br /&gt;    transform = createObject("java", "java.awt.geom.AffineTransform").init();&lt;br /&gt;   transform.setToTranslation( transX, transY );&lt;br /&gt;&lt;br /&gt;   // Draw the text outline onto the image&lt;br /&gt;   shape = layout.getOutline(transform);&lt;br /&gt;   graphics.setColor(textColor);&lt;br /&gt;   graphics.draw(shape);&lt;br /&gt;   graphics.dispose();&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;   &amp;lt;!--- display raw image ---&amp;gt;   &lt;br /&gt;   &amp;lt;cfimage source="#transparentImage#" action="writeToBrowser"&amp;gt;&lt;br /&gt;   &amp;lt;!--- display WITH background ---&amp;gt;   &lt;br /&gt;   &amp;lt;div style="background-color: ##000080; width: #width#; height=#height#;"&amp;gt;&lt;br /&gt;      &amp;lt;cfimage source="#transparentImage#" action="writeToBrowser"&amp;gt;&lt;br /&gt;   &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-8813571297077237629?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/8813571297077237629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=8813571297077237629&amp;isPopup=true' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8813571297077237629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8813571297077237629'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/10/coldfusion-draw-text-outline-on-image.html' title='ColdFusion 8: Draw a Text Outline on an Image'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_4MgprHLfxvM/SsVquyoUQWI/AAAAAAAAAZk/DdspJw066GY/s72-c/ColdFusion_TextOutline_Image.PNG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3995749146022467294</id><published>2009-08-28T00:03:00.000-07:00</published><updated>2009-11-13T11:29:06.063-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>No, my glasses do not need buffing. They just need a little javacast (StringBuffer gotcha)</title><content type='html'>I was working with the StringBuffer class earlier and ran into a small gotcha. I needed to create a StringBuffer with a capacity larger than default (16 characters). So I used one of the &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuffer.html#StringBuffer%28int%29"&gt;alternate constructors&lt;/a&gt;:&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfscript&amp;gt;&lt;br /&gt; sb = createObject("java", "java.lang.StringBuffer").init( 256 );&lt;br /&gt;&amp;lt;/cfscript&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As I tested the results, I noticed some numeric characters kept appearing at the end of the string.  At first I thought was it was a mistake in my code. The base data did contain a lot of numbers. (Did I mention the string was reversed as well?). Yes, eventually I realized the value I kept seeing was .. wait for it .. the &lt;span&gt;capacity &lt;/span&gt;value. &lt;br /&gt;&lt;br /&gt;I was a bit surprised. The last time I checked 256 was a numeric value, and well within the range of Integer.MIN_VALUE and Integer.MAX_VALUE. However, there is &lt;a href="http://www.blogger.com/%20http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuffer.html#StringBuffer%28java.lang.String%29"&gt;another constructor&lt;/a&gt; for the StringBuffer class that accepts a java.lang.String  and apparently that constructor won out in the "battle of the data types".   So my object was initialized with the &lt;span style="font-style: italic;"&gt;contents&lt;/span&gt; "256" rather than a &lt;span style="font-weight: bold;"&gt;capacity &lt;/span&gt;of 256 characters.&lt;br /&gt;&lt;br /&gt;So lesson of the day: Sometimes it pays to use javacast. &lt;span style="font-style: italic;"&gt;Even when you think you do not need it.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-3995749146022467294?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/3995749146022467294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=3995749146022467294&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3995749146022467294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/3995749146022467294'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/08/no-my-glasses-do-not-need-buffing-they.html' title='No, my glasses do not need buffing. They just need a little javacast (StringBuffer gotcha)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-773169403412772461</id><published>2009-08-12T16:58:00.001-07:00</published><updated>2009-08-12T18:11:22.804-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>An episode of CSI that I actually *would* watch</title><content type='html'>Like most people, my brain is conditioned to tune out ad banners. But while reading a blog entry today, it did register something seemed off with one of the rotating images. So I actually waited, and watched &lt;span style="font-style:italic;"&gt;all&lt;/span&gt; of the rotating ads, until one in particular came around again.  When I saw the CSI logo, I laughed out loud. No wonder it caught my attention ;) &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.fusion-reactor.com/events/cfunited09.cfm"&gt;http://www.fusion-reactor.com/events/cfunited09.cfm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(Nice to know my ColdFusionOnlyFilter is working properly)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-773169403412772461?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/773169403412772461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=773169403412772461&amp;isPopup=true' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/773169403412772461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/773169403412772461'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/08/episode-of-csi-that-i-acutally-would.html' title='An episode of CSI that I actually *would* watch'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-7327982634956152485</id><published>2009-08-07T00:09:00.001-07:00</published><updated>2009-08-07T05:18:04.085-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>ColdFusion 8:  CFINPUT DateField Experiment (Setting Minimum and Maximum Dates)</title><content type='html'>In a previous entry, I mentioned a question on &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt; about restricting the "selectable" dates in a calendar control.  I eventually figured out how to customize a cfcalendar. But that got me to thinking about how you might do the same for an HTML datefield.&lt;br /&gt;&lt;br /&gt;Not being very familiar with the inner workings of datefields,   I poked around a bit and discovered that these controls are based on the &lt;a href="http://developer.yahoo.com/yui/calendar/"&gt;YUI Calendar Library&lt;/a&gt;.   After reviewing the YUI documentation,   I realized it opened up a lot of possibilities for customization.   To start with, the YUI documentation mentions you can limit the available dates by setting the configuration properties: &lt;span style="font-family:courier new;"&gt;mindate&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;maxdate&lt;/span&gt;.   But since cfinput does not have those attributes,  the question was how to customize the ColdFusion scripts to add those properties.   It turns out it was easier than I thought.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;My first step was to figure out how the controls are created.   So I made a simple form with a datefield.    While viewing the html source,  I noticed that ColdFusion generates some javascript code to create the calendar control.  The generated code calls a method named &lt;span style="font-family:courier new;"&gt;ColdFusion.Calendar.setUpCalendar()&lt;/span&gt;.  The source of that method can be found in &lt;span style="font-family:courier new;"&gt;C:\ColdFusion8\wwwroot\CFIDE\scripts\ajax\package\cfcalendar.js&lt;/span&gt;.  If you view the source of cfcalendar.js,  you can clearly see how the function arguments correspond to cfinput attributes.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_4MgprHLfxvM/SnvuRrPu0uI/AAAAAAAAAZM/PW8ArWQ_Dho/s1600-h/ColdFusion_DateField_DateRange.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 386px;" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SnvuRrPu0uI/AAAAAAAAAZM/PW8ArWQ_Dho/s400/ColdFusion_DateField_DateRange.png" alt="" id="BLOGGER_PHOTO_ID_5367145368375972578" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The next challenge was figuring out how to access the darn things from javascript! Arguably, one of the best things about CFForm controls is they are created "automagically", with minimal code.  Ironically, it is also one of the worst things about CFForm controls.  Because the objects are dynamically created behind the scenes, extending them is a bit of a challenge.  But with a little work, it can be done.&lt;br /&gt;&lt;br /&gt;Understandably, calendar objects are dynamically named by ColdFusion.  But part of the object name is based on a counter number.   That makes it a bit difficult if you are trying to locate the calendar instance tied to a specific form field.  Now I searched high and low for a simple method or object that would return the calendar instance linked to a specific form field.  But I could not find one.  So I decided to make my own.&lt;br /&gt;&lt;br /&gt;At the top of &lt;span style="font-family:courier new;"&gt;cfcalendar.js&lt;/span&gt; are a few lines that initialize the ColdFusion.Calendar object, if it does not already exist.  Inside this section, I added a new object called &lt;span style="font-family:courier new;"&gt;lookupByID&lt;/span&gt;. As its name implies, it  will store calendar instances by form field id, for easier access.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;if(!ColdFusion.Calendar){&lt;br /&gt;ColdFusion.Calendar={};&lt;br /&gt;ColdFusion.Calendar.lookupByID={}; // NEW CODE&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Further down in the file,  new calendar instances are created and assigned to a rather cryptically named variable &lt;span style="font-style: italic;font-family:courier new;" &gt;_14&lt;/span&gt;.    Just after that section is where I added the rest of the custom code.   First, I store new calendar instances in the look-up structure.&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;ColdFusion.Calendar.lookupByID[_e.id]=_14;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The next step is detecting whether a minimum or maximum date was specified for the current field.  Then adding those dates to the calendar settings.     Now obviously &lt;span style="font-family:courier new;"&gt;minDate &lt;/span&gt;and &lt;span style="font-family:courier new;"&gt;maxDate&lt;/span&gt; are not official attributes of &amp;lt;cfinput&amp;gt;.   (If they were,  there would be no need for this entry.)   However,  ColdFusion will simply ignore them and pass them through to the generated HTML.  So it is easy to extract any extra attributes with a little DOM magic.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;// Apply the minimum date to the calendar instance&lt;br /&gt;if ( document.getElementById &amp;amp;&amp;amp; _e.getAttribute("minDate") ) {&lt;br /&gt;_14.cfg.setProperty("mindate", _e.getAttribute("minDate"));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Apply the maximum date to the calendar instance&lt;br /&gt;if ( document.getElementById &amp;amp;&amp;amp; _e.getAttribute("maxDate") ) {&lt;br /&gt;_14.cfg.setProperty("maxdate", _e.getAttribute("maxDate"));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Once the calendar settings are updated, any dates outside the allowed range will be disabled.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_4MgprHLfxvM/SnvxelqeDgI/AAAAAAAAAZU/9iAq5sd7FX0/s1600-h/ColdFusion_DateField_DisabledDates.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 330px; height: 260px;" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SnvxelqeDgI/AAAAAAAAAZU/9iAq5sd7FX0/s400/ColdFusion_DateField_DisabledDates.png" alt="" id="BLOGGER_PHOTO_ID_5367148888750689794" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As users can also enter dates manually,   I needed a validation function as well.  Fortunately, the robust YUI library already contains a function for detecting whether a date is outside the allowed range.  So with a small amount of code, I created a function that could be called from the &lt;span style="font-family:courier new;"&gt;onValidate &lt;/span&gt;event.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;ColdFusion.Calendar.checkDate = function(_form, _field, _value) {&lt;br /&gt;var cal = ColdFusion.Calendar.lookupByID[_field.id];&lt;br /&gt;var str = _value.replace(/\s+/g, '');&lt;br /&gt;var isOK = str.length == 0;&lt;br /&gt;&lt;br /&gt;if (!isOK) {&lt;br /&gt;    var dtTime = Date.parse(_value);&lt;br /&gt;    if (dtTime &amp;amp;&amp;amp; !isNaN(dtTime )) {&lt;br /&gt;        var dt = new Date(dtTime );&lt;br /&gt;   isOK = !cal.isDateOOB( dt );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return isOK;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A few form changes later,  I had an instant, customized datefield.  Now the code below is not highly tested.  But I thought it would be useful to show an example of how you might customize datefields.&lt;br /&gt;&lt;br /&gt;As always, any comments/questions or suggestions are welcome.&lt;br /&gt;&lt;br /&gt;&lt;a name="code"&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;CF Example&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&amp;lt;cfform format="html"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfinput type="datefield"&lt;br /&gt;   name="startDate"&lt;br /&gt;   id="startDate"&lt;br /&gt;   required="true"&lt;br /&gt;   mask="MM/dd/yyyy"&lt;br /&gt;   minDate="08/5/2009"&lt;br /&gt;   maxDate="09/15/2009"&lt;br /&gt;   onValidate="ColdFusion.Calendar.checkDate"&lt;br /&gt;   message="Start Date is invalid or out of range" &amp;gt;&lt;br /&gt;&amp;lt;cfinput type="submit" name="submit" value="Submit Form"&amp;gt;&lt;br /&gt;&amp;lt;/cfform&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;CFCalendar.js &lt;/span&gt;&lt;span style="font-style: italic;"&gt;(Changes only)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Notes:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic; color: rgb(255, 0, 0);"&gt;1.  If you are smart, you will make a backup before making any modifications ;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;2.  For brevity, the code below uses Date.parse to convert input values to date objects.  You may prefer to use something a bit more robust.&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="javascript"&gt;&lt;br /&gt;// ...&lt;br /&gt;&lt;br /&gt;if(!ColdFusion.Calendar){&lt;br /&gt;ColdFusion.Calendar={};&lt;br /&gt;/////////////////////////////////////&lt;br /&gt;//     BEGIN CUSTOM CODE&lt;br /&gt;&lt;br /&gt;ColdFusion.Calendar.lookupByID={};&lt;br /&gt;&lt;br /&gt;//     END CUSTOM CODE&lt;br /&gt;/////////////////////////////////////&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// ... more code&lt;br /&gt;&lt;br /&gt;ColdFusion.objectCache[_11+_b]=_14;&lt;br /&gt;&lt;br /&gt;/////////////////////////////////////&lt;br /&gt;//     BEGIN CUSTOM CODE&lt;br /&gt;&lt;br /&gt;// Add this calendar to the lookup structure (key = form field element ID)&lt;br /&gt;ColdFusion.Calendar.lookupByID[_e.id]=_14;&lt;br /&gt;&lt;br /&gt;// Apply any minimum date to the calendar instance&lt;br /&gt;if ( document.getElementById &amp;amp;&amp;amp; _e.getAttribute("minDate") ) {&lt;br /&gt;  _14.cfg.setProperty("mindate", _e.getAttribute("minDate"));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Apply any maximum date to the calendar instance&lt;br /&gt;if ( document.getElementById &amp;amp;&amp;amp; _e.getAttribute("maxDate") ) {&lt;br /&gt;  _14.cfg.setProperty("maxdate", _e.getAttribute("maxDate"));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// Verify the text field value is a date and is within range&lt;br /&gt;ColdFusion.Calendar.checkDate = function(_form, _field, _value) {&lt;br /&gt;  // lookup the calendar instance for this field&lt;br /&gt;  var cal = ColdFusion.Calendar.lookupByID[_field.id];&lt;br /&gt;  var str = _value.replace(/\s+/g, '');&lt;br /&gt;  var isOK = str.length == 0;&lt;br /&gt;&lt;br /&gt;  // if the text box value is not empty ..&lt;br /&gt;  if (!isOK) {&lt;br /&gt;   var dtTime = Date.parse(_value);&lt;br /&gt;     // verify this is a valid date, and is not outside of the allowed range&lt;br /&gt;      if (dtTime &amp;amp;&amp;amp; !isNaN(dtTime )) {&lt;br /&gt;         var dt = new Date(dtTime );&lt;br /&gt;          isOK = !cal.isDateOOB( dt );&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return isOK;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//     END CUSTOM CODE&lt;br /&gt;/////////////////////////////////////&lt;br /&gt;&lt;br /&gt;// ... more code&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-7327982634956152485?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/7327982634956152485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=7327982634956152485&amp;isPopup=true' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7327982634956152485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/7327982634956152485'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/08/coldfusion-8-customizing-cfinput.html' title='ColdFusion 8:  CFINPUT DateField Experiment (Setting Minimum and Maximum Dates)'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4MgprHLfxvM/SnvuRrPu0uI/AAAAAAAAAZM/PW8ArWQ_Dho/s72-c/ColdFusion_DateField_DateRange.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-8877241347449794385</id><published>2009-08-06T16:00:00.000-07:00</published><updated>2009-08-07T00:15:43.762-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Mission Impossible: Restrict Selectable Dates in CFCalendar / Format="html"</title><content type='html'>A recent question on stackoverflow.com prompted me to revisit the idea of restricting the selectable dates in a cfcalendar. For example, allowing only future dates to be selected. It is relatively easy if you are using flash forms. But it turned out to be a bit more challenging with html forms.&lt;br /&gt;&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Your mission, should you choose to accept it ..&lt;/span&gt;&lt;br /&gt;As CFCalendar is a flash control, you must use ActionScript to manipulate the calendar (for the most part).   If you review the underlying &lt;a href="http://livedocs.adobe.com/flex/15/asdocs_en/mx/controls/DateChooser.html"&gt;Flex documentation&lt;/a&gt;, there are at least two properties available for restricting dates: &lt;span style="font-family:courier new;"&gt;selectableRange&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;disabledRanges&lt;/span&gt;.  When you use cfcalendar's &lt;span style="font-family:courier new;"&gt; startRange&lt;/span&gt; or &lt;span style="font-family:courier new;"&gt;endRange&lt;/span&gt; attributes you are actually setting one of those properties: disabledRanges.&lt;br /&gt;&lt;br /&gt;If you are not familiar with the underlying properties, selectableRange and disabledRanges are essentially a structure of date ranges, with the keys: rangeStart and rangeEnd. To indicate a property should apply to everything &lt;span style="font-style: italic;"&gt;before &lt;/span&gt;or everything &lt;span style="font-style: italic;"&gt;after &lt;/span&gt;a particular date,  just omit one of the keys.  That is easy enough to do with flash forms and a bit of actionscript.  Unfortunately, it seems impossible to achieve using an html form and cfcalendar attributes alone.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Murder She Wrote&lt;/span&gt;&lt;br /&gt;I ran into several problems with the html forms scenario.  First, cfcalendar's date range attributes do not function the way you might expect.   If you only provide one of the attributes (ie startRange or endRange), CF disables a single date.  Not everything after the start date or everything before the end date.  Again, not the behavior I would have expected.&lt;br /&gt;&lt;br /&gt;Second, I do not know of any way to specify a &lt;span style="font-style: italic;"&gt;null&lt;/span&gt; date using cfcalendar's date attributes (or any tag for that matter).  Personally, I think there are cases where allowing a null date not only makes sense, but would be very useful.   It would be great if CF had the concept of a NULL_DATE for use with tag attributes.   But for now, it does not.&lt;br /&gt;&lt;br /&gt;Finally, there is the issue of events.  With flash forms you could use the form's onLoad method to initialize the calendar with the desired settings, via actionscript.  From what I can tell, there is no way to do this from within an html form.  CFCalendar does not have its own &lt;span style="font-family:courier new;"&gt;onLoad &lt;/span&gt;method, and while it does expose events like &lt;span style="font-family:courier new;"&gt;onFocus&lt;/span&gt;, &lt;span style="font-family:courier new;"&gt;onBlur &lt;/span&gt;and &lt;span style="font-family:courier new;"&gt;onChange&lt;/span&gt;, they unfortunately occur too late to be used for initialization code.&lt;br /&gt;&lt;br /&gt;This basically leaves you with hacking the date range. You could supply a ridiculous date (like the year 1500 or the year 9999) to simulate and open ended range.   I suppose that it is the simplest option.  But it rubs me the wrong way,  as it is not necessary when using actionScript directly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Outer Limits&lt;/span&gt;&lt;br /&gt;So back to the original goal: do not allow past dates to be selected. I decided to use a little trickery to simulate initialization code.  Since cfcalendar only displays one month at a time, I realized all I needed to handle was the current month initially.  So I could to disable prior dates in the current month when the calendar loaded.  Then disable previous dates when the calendar month is changed. That would create the illusion the calendar was initialized with desired settings.&lt;br /&gt;&lt;br /&gt;While it does involve more code, it has one interesting advantage over the date range hack. When using &lt;span style="font-family:courier new;"&gt;selectableRange&lt;/span&gt;,  the navigation arrows are disabled for months that cannot be selected.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;!--- disable all dates in the current month, prior to today  ---&amp;gt;&lt;br /&gt;&amp;lt;cfset endRange  = dateAdd("d", -1, now())&amp;gt;&lt;br /&gt;&amp;lt;cfset startRange  = dateAdd("d", -( day(endRange)-1 ), endRange)&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!--- generate the actionScript to set the date ranges (once) ---&amp;gt;&lt;br /&gt;&amp;lt;cfsavecontent variable="asCode"&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;if (myCalendar["rangeInitialized"] == undefined) {&lt;br /&gt;    var displayDate = new Date(myCalendar.displayedYear, myCalendar.displayedMonth, 1);&lt;br /&gt;    var range = {};&lt;br /&gt;    #ToScript(endRange, "range.rangeStart", false, true)#;&lt;br /&gt;    myCalendar.selectableRange = range;&lt;br /&gt;    // modifying selectableRange alter the display month. so restore the previous selection&lt;br /&gt;    myCalendar.displayedMonth = displayDate.getMonth();&lt;br /&gt;    myCalendar.displayedYear =  displayDate.getYear();&lt;br /&gt;    myCalendar["rangeInitialized"] = true;&lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfform format="html"&amp;gt;&lt;br /&gt;&amp;lt;cfcalendar     name="myCalendar"&lt;br /&gt;            onFocus="#asCode#"&lt;br /&gt;            startRange="#startRange#"&lt;br /&gt;            endRange="#endRange#"&lt;br /&gt;            width="300"&lt;br /&gt;            height="200"&lt;br /&gt;    /&amp;gt;&lt;br /&gt;&amp;lt;/cfform&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Get Smart&lt;/span&gt;&lt;br /&gt;If you would prefer to leave the navigation arrows enabled, you could use similar code with disabledRanges.    But ... there is a catch.    By default, cfcalendar displays today's date with a different background color.    For some reason, when you modify disabledRanges, it causes that day of the month to disappear from subsequent months. (Really the font color is probably changed to "ffffff", making it appear invisible).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_4MgprHLfxvM/SntjDnBai6I/AAAAAAAAAZE/f1V-pT31JJw/s1600-h/cfcalendar_invisible_date_cell.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 317px; height: 215px;" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SntjDnBai6I/AAAAAAAAAZE/f1V-pT31JJw/s400/cfcalendar_invisible_date_cell.PNG" alt="" id="BLOGGER_PHOTO_ID_5366992294607752098" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;br /&gt;The only work-around I could find was to disable the highlighting.  Not perfect, but it does work.  (Now if only I could find that magical style setting...)&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xhtml"&gt;&lt;br /&gt;&amp;lt;cfset endRange     = dateAdd("d", -1, now())&amp;gt;&lt;br /&gt;&amp;lt;cfset startRange     = dateAdd("d", -( day(endRange)-1 ), endRange)&amp;gt;&lt;br /&gt;&amp;lt;cfsavecontent variable="asCode"&amp;gt;&lt;br /&gt;&amp;lt;cfoutput&amp;gt;&lt;br /&gt;if (myCalendar["rangeInitialized"] == undefined) {&lt;br /&gt;    var range = {};&lt;br /&gt;    #ToScript(endRange, "range.rangeEnd", false, true)#;&lt;br /&gt;    myCalendar.disabledRanges = [ range ];&lt;br /&gt;    myCalendar.showToday = false;&lt;br /&gt;    myCalendar["rangeInitialized"] = true;&lt;br /&gt;}&lt;br /&gt;&amp;lt;/cfoutput&amp;gt;&lt;br /&gt;&amp;lt;/cfsavecontent&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;cfform format="html"&amp;gt;&lt;br /&gt;&amp;lt;cfcalendar     name="myCalendar"&lt;br /&gt;            onFocus="#asCode#"&lt;br /&gt;            startRange="#startRange#"&lt;br /&gt;            endRange="#endRange#"&lt;br /&gt;            width="300"&lt;br /&gt;            height="200"&lt;br /&gt;    /&amp;gt;&lt;br /&gt;&amp;lt;/cfform&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ah, cfcalendar. "Good Times. Good Times." ;)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5824660313967021040-8877241347449794385?l=cfsearching.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://cfsearching.blogspot.com/feeds/8877241347449794385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5824660313967021040&amp;postID=8877241347449794385&amp;isPopup=true' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8877241347449794385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5824660313967021040/posts/default/8877241347449794385'/><link rel='alternate' type='text/html' href='http://cfsearching.blogspot.com/2009/08/mission-impossible-restrict-selectable.html' title='Mission Impossible: Restrict Selectable Dates in CFCalendar / Format=&quot;html&quot;'/><author><name>cfSearching</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_4MgprHLfxvM/SntjDnBai6I/AAAAAAAAAZE/f1V-pT31JJw/s72-c/cfcalendar_invisible_date_cell.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5824660313967021040.post-3153525743781567626</id><published>2009-07-31T02:07:00.000-07:00</published><updated>2009-07-31T22:24:03.196-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ColdFusion'/><title type='text'>Installing a Development Mail Server for Testing CFMAIL</title><content type='html'>Occasionally I need to run some cfmail tests in an environment that does not have access to a mail server, or only a live server I do not want to use for testing.    A while back I stumbled across the &lt;a href="http://www.hmailserver.com/"&gt;hMailServer&lt;/a&gt; program which is a great tool to have in those situations.  Although it can function as a full fledged mail server, it can also be configured to act as a local mail server &lt;span style="font-style: italic;"&gt;only&lt;/span&gt;.   I have not used it in a while, but I found myself needing to install it this week.  It is pretty easy to configure.   But my memory was a little hazy on a few points.  So I thought I would write up some instructions as a reference for next time.&lt;br /&gt;&lt;br /&gt;The basic process is very simple. You just install the mail server and create a fake domain with a few email addresses. Then modify the mail server settings to ensure it does not allow messages to be sent to external email addresses (ie the outside world).&lt;br /&gt;&lt;span id="fullpost"&gt;&lt;br /&gt;The latest stable version (currently 5.2) can be installed in just a few steps. You only need to create an Administrator password when prompted.  Then once the installation is complete, log into the Administrator using the password you selected during the installation.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_4MgprHLfxvM/SnPIPzLZ8QI/AAAAAAAAAYM/M7EaoQbf95k/s1600-h/ColdFusion_HMailServer_Connect.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 198px;" src="http://2.bp.blogspot.com/_4MgprHLfxvM/SnPIPzLZ8QI/AAAAAAAAAYM/M7EaoQbf95k/s400/ColdFusion_HMailServer_Connect.png" alt="" id="BLOGGER_PHOTO_ID_5364851754890031362" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Before you can create email addresses you obviously need a domain. So from the left menu select &lt;font face="courier new"&gt;Domains &amp;gt; Add&lt;/font&gt; and enter the desired name on the &lt;font face="courier new"&gt;General &lt;/font&gt;tab. I chose the wildly imaginative domain name:  &lt;font style="font-style: italic;"&gt;psuedo-yahoo.com&lt;/font&gt;.  Then click &lt;font face="courier new"&gt;Save &lt;/font&gt;to actually create the domain.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_4MgprHLfxvM/SnPH
