The future of ColdFusion -- there is no doubt!

Good article posted on Fusion Authority Community Chronicles about the future of ColdFusion recapping an interview between Jared Rypka-Hauer and former Adobe CEO Bruce Chizen.

Simple Form Processing and E-mailing with CFFormMail

I posted a new project today to RIA Forge called CFFormMail. This project is a ColdFusion port of the venerable formmail Perl script found on Matt's Script Archive. Every attempt was made to make this a drop-in replacement for the perl script, so that the only necessary change in an existing html form is to modify the form action from formmail.pl to formmail.cfm.

Beyond the port, some new functionality has been added, most significantly is integration with Jake Munson's CF Form Protect to help deter form spam. I also began the integration of language resource bundles, but currently only have an English translation.

I created this processing engine last year and had planned on posting it on RIA Forge, but completely forgot about doing so until I read Ben Nadel's recent post on Generic Form Processing and Emailing in ColdFusion. Mine was designed as a drop-in replacement for formmail.pl (but can certainly be used on new forms!) with support for all the parameters in the original Perl version, while the code in Ben's post appears to have a subset of the functionality of the Perl version plus the ability to handle file uploads.

Hopefully you will find this script useful. I welcome any suggestions for improvements and also any additional language translations you would like to include (submit them translated also). Please post suggestions to the forums over at the project site.

ColdFusion 8 Random Slowness? Downgrade the JVM!

I upgraded our main production server to ColdFusion 8 during the Christmas holidays. We had been running it on our beta server for several weeks without issue. Everything seemed to be humming along fine, until the student population returned. We began having intermittent slowness, causing intermittent timeouts, and headaches with several of our apps that wouldn't finish processing because of the timeouts (e.g. credit card transactions!). Tracking down the problem proved quite difficult. We would tried tweaking network settings (firewall settings, VLAN settings, traffic priority), increasing timeouts on some pages (to 120 seconds!) to make sure they complete, etc. While some of these changes seemed to help, the problem did not go away.

I began to suspect that ColdFusion's default Java 6 might be to blame since many of the timeouts were occurring with reactor-based applications. I added some JVM logging, but not being a JVM garbage collection log guru, I couldn't really tell if that was really the issue or not.

In a bit of frustration, I decided to back-rev the JVM as Sean Corfield suggested. I decided to go with Sun's latest 1.5 JRE, version 1.5.0-14. I installed it, set the JVM (or here for JRUN installs), and restarted ColdFusion. ColdFusion hummed along as normal, and after checking some internal indicators over the weekend, it appears that the random slowness/timeouts have disappeared.

Hopefully this issue can be resolved in either a ColdFusion updater or the next version of Sun's JVM (it's supposed to be fixed in 1.7, but they apparently haven't back-revved it into 1.6).

Querying Excel files in ColdFusion Part II

After penning my first blog entry about Querying Excel files in ColdFusion, a friend pinged and asked if this would work with arbitrary files that users could upload. Since I was using an ODBC datasource that pointed directly to the Excel file, I told him that really wouldn't work. I then remembered that Ben Nadel had created a ColdFusion wrapper for the Apache POI utility that can read and write Excel files.

After discussing this with my friend, I decided to explore the POI Utility myself. It turns out that Ben made things quite easy. The code to get a ColdFusion query of the Excel worksheet with my data is as simple as this:

<cfset objPOIUtility = CreateObject("component","POIUtility").Init() />
<cfset strFilePath = ExpandPath( "./rooms.xls" ) />
<!--- grab the second Excel worksheet (use "1" b/c it is zero-based) --->
<cfset RoomSheet = objPOIUtility.ReadExcel(FilePath = strFilePath,HasHeaderRow = true, SheetIndex = 1) />
<!--- get the ColdFusion query object --->
<cfset qExcel=RoomSheet.query>
Those few lines replace the <cfquery> I had that queried the Excel file through ODBC.

There are two huge benefits to doing it this way:

  1. No need for an ODBC connection to the Excel sheet
  2. Which means I don't have to run this on Windows (I develop on Windows, but my production server is Linux)

There is one downside that I found: the utility creates the ColdFusion query with generic column names rather than the names I used in the spreadsheet. So I have to refer to the fields using "Column1", "Column2", etc. It's a little thing that I can get over, but it would be nicer to use the column headers instead.

One last item to note. When using the ODBC connection, I had to close the Excel file before reading it. With the POI Utility, I can read files that are currently open in Excel. Nice!

Querying Excel files in ColdFusion

I have a project where I regularly import some data from an Excel file. Up until recently, I was exporting the data to a text file, using cffile to read it in, then parsing the data. Since I can run this particular process on my development machine, I decided to instead query the Excel file directly to cut down on the number of steps involved in the update.

Initially I ran into a problem with a column titled "Room". This column is a room number which is strictly a number half the time, but may also contain letters, such as in "26A". The problem was that Excel decides what each column data type is and it thought this column was a number. Guess what Excel does with the data that is not numeric--it throws it out and makes it a null value. So my initial queries had a bunch of null data for the room column.

To fix the problem, my google search turned up this resource on the ColdFusion FAQ. It talks about how to force a data type of text on a column containing mixed data. Here is the basic idea:

How to force a cell to be text;
You need a "copy" column beside it and put the following formula into it;
=Mid("'"&a2,2,Len(a2))
Assuming that A2 is the cell that contains the original data

So I created a new column in my spreadsheet that duplicated the Room column and named it RoomText. Then in my ColdFusion query, I referenced RoomText instead of Room. This fixed my problem! Whoohoo! It seems like there should be a better way...

Ben Forta in my backyard

OK, not exactly my backyard but closer than San Jose, but Adobe Evangelist Ben Forta is coming to the Dayton area on January 9 for a Books & Co event at The Greene in Beavercreek. Unfortunately I cannot make it given prior commitments...

Block direct access to xml configuration files

I realized today that the configuration files for some ModelGlue apps I'm running are basically exposed to the public if someone can get the path and filename. The reason is that I'm using ColdFusion for server-side processing, authentication and authorization, but that only protects files that end in .cfm. Since my configuration files typically end in .xml, they can be directly accessed on the web.

Since I'm running Apache, the fix was quite simple. Place the following code into a .htaccess file at the root of your application (or higher if possible). Subfolders will automatically look up the tree to find the .htaccess files.

<Files ~ "\.xml$">
Order allow,deny
Deny from all
Satisfy All
</Files>

Now when you try to access the xml configuration file, the web server returns a 403 - Forbidden error and doesn't display the file. Note that the ColdFusion apps can still read them since they typically access the file more directly on the file system than through the http protocol.

CFPayment - The ColdFusion Payment Processing API

Have you ever wanted a simple way to hook into one or more payment processing systems? I've teamed up with Brian Ghidinelli on the new CFPayment project to provide a unified interface to many different back-end payment processors. Read Brian's blog entry about it, then get on the forums and discuss your needs and/or contributions!

ColdFusion Sneak Peak

Ray Camden beat me to showing off the ColdFusion Sneak Peak at MAX 2007. I'm here trying to learn Flex and AIR, so the demo of the CFAirAccess tag was very intriguing! I've wanted to post more about MAX, but my wireless has been so flaky and is usually not working. So I'll be posting when I'm back on a wired connection or perhaps at the airport on the way home.

Form Data in Field Order Part II

As a follow up to yesterday's post and the comments by "Some guy", I did a bit of experimenting with form.fieldnames versus getHttpRequestData().content. There are some significant differences in how the two treat form data:

form.fieldnames

  • All uppercase field names
  • No values (use form[fieldname] to access)
  • Comma-delimited
  • Form[fieldname] values are automatically URL decoded by ColdFusion
  • Only one field name is output even when multiple fields had the same name in the form

getHttpRequestData().content

  • Case of field names matches case used in HTML form
  • FieldName=Value syntax
  • Each name/value pair delimited by an ampersand
  • Both the name and the value are URL encoded (e.g. spaces are replaced by the plus sign, the @ sign is replaced by it's hexadecimal equivalent, etc.)
  • Multiple fields with the same name in the form are output multiple times (according to their location in the form)

In the end, I decided to switch over to using the form.fieldnames because of the automatic URL decoding.

This discussion has been an exercise in humility since: (1) I have been working with ColdFusion since version 4.0, (2) I have used form.fieldnames before, (3) but I have never noticed nor read anyone (that I recall) that the fields are listed in the form order.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.8.