No matter how good you think you are as a developer, there will most likely be times when an exception happens in your application. Exceptions in ColdFusion will typically display a technical and confusing error message to your user. While these error messages may be great for developers to troubleshoot the problem, to a user they are often left wondering what went wrong.
As a developer, your job is to catch these exceptions and of course correct them, but it is also your job to make sure that your user isn’t presented with a scary technical error message or even worse, a message that could possibly give critical details about the code behind your application. Using ColdFusion, we can find a much more user friendly way of displaying an error message to the user and still receive all of the information we need to correct the issue.
Catching Errors with CFTRY and CFCATCH
By using the <cftry> and <cfcatch> tags we are going to catch errors and handle them appropriately before the user sees them. Instead of letting the user experience a messy glitch in the application we are going to display a nice user friendly screen letting them know an exception occurred and that we are doing our best to correct the issue. At no point will they ever see an actual error message produced by the ColdFusion error system.
The first thing you will need to is identify where in your application you have potential for error. You obviously wouldn’t need to catch any errors within a block of text, but you might want to watch out for areas where you are connecting to a data source or doing complex math processing. Complicated processing code blocks and database connections are two of my more standard types of code to use a <cftry> with. Let’s take a look at a snippet of code that will grab the ID and Name of a user based on the username that they entered on a previous form.
<cftry> <cfquery name="GetUserInfo"> SELECT ID, Name FROM userAccounts WHERE Username = '#form.username#' </cfquery> <cfcatch type="any"> <cfmail to="email@example.com" from="firstname.lastname@example.org" subject="An Error Has Occurred" type="html"> Error Message: #cfcatch.message#<br> Error Detail: #cfcatch.detail#<br> Error Location: #GetBaseTemplatePath()#<br> </cfmail> <p>We're sorry, an error has occurred and our developers have been notified.</p> </cfcatch> </cftry>
In the above example, I’ve chosen to check and catch any errors that happen within the <cfquery> call to my database. I’ve wrapped the entire block inside of a <cftry> and </cftry> tag set. After the query is attempted to be called, if anything happens that would cause an exception it will run whatever is located in the <cfcatch> tag.
I have decided to do two things with this error handling. To be sure I am notified of the error, I will first send an email to myself using the <cfmail> tag. I’ve included details that I need to know to be able to find and correct the error that the user received. For example, I am collecting the ColdFusion error message that is generated, the detail of the error and the actual path to the file that the error occurred on.
The second thing I am doing is displaying a nice message to the user instead of the error message. This means you can keep your application looking clean with a standard header and footer, and a nicely formatted message that will fit nicely in the center of your page, or however you wish to design it.
You will notice I currently have the <cfcatch> tag set to catch the error types of “any”. That means, no matter what goes wrong, it will catch it and process the error as I have defined in the <cfcatch> tag. You may have instances where you want to handle errors differently based on the type of error it is. With our example containing only a database call, it will most likely be a “database” type of error, for example if the data source can’t connect to the database. But we are also looking for a form variable called username. If you were to run this code on your ColdFusion server and go directly to this page instead of submitting a form, you would produce an “expression” error as it would be missing the form variable.
This time let’s set up some error handling that still sends us an email if it’s a database error, but if it’s only missing the form variable, we can just send them back to the login page.
<cftry> <cfquery name="GetUserInfo"> SELECT ID, Name FROM userAccounts WHERE Username = '#form.username#' </cfquery> <cfcatch type="expression"> <!--- Missing the form element ---> <cflocation url="login.cfm"> </cfcatch> <cfcatch type="database"> <cfmail to="email@example.com" from="firstname.lastname@example.org" subject="A database Error Has Occurred" type="html"> Error Message: #cfcatch.message#<br> Error Detail: #cfcatch.detail#<br> Error Location: #GetBaseTemplatePath()#<br> Error Time: #timeformat(Now(), 'hh:mm:ss')#<br> </cfmail> <p>We're sorry, an error has occurred and our developers have been notified.</p> </cfcatch> </cftry>
In this example, we’ve used two new error types: expression and database. In the expression error catch, I’ve set it do a <cflocation> to direct the user immediately to the login.cfm page. A <cflocation> is simply a basic redirect that can send the user to any page you specify in the url variable.
If we get a database error, such as a connection issue, it will use the code block within the <cfcatch> using the type of database.
If you are wanting to test for other possible errors, ColdFusion makes the following error types available to test for:
Debugging Tool: CGI Variables
One of the most useful tools within ColdFusion that will help you to debug your application is the built in CGI variable structure. CGI variables can let you know many important things about your application such as the referring url, the server name, IP address, script file names and much more.
For example, if you wanted to capture the browser that the user is using to browse your application you could output the CGI variable for HTTP_USER_AGENT as shown:
On my own system this would return the following value:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36
There is a large number of CGI variables that are available to you but don’t worry, I don’t expect you to memorize them all. You can easily output all of the CGI variables available to you on your own server and view what the possible value of those variables are by dumping the entire structure using the <cfdump> tag.
Debugging Tool: CFDUMP
The <cfdump> tag is used to created a grid like display of the contents of any variable that you pass it. This is especially useful as you are debugging your ColdFusion code and need to quickly see what is happening in your errors.
As a developer, you will pass to it variables for queries, CGI variables as mentioned above or just simply variables passed from a form. To use the <cfdump> tag you will simply pass in the value of the variable you want to process through the parameter called “var” as shown below.
If you were to run the above code, you would see a grid structure of all of the available CGI variables as well as the current value for each variable as it processes the user viewing it.
Along with sending through CGI variables and simple variables, you can also dump the contents of a complex query variable. Dumping the results of a query is as simple as changing out the variable name to the name of your query.
<cfquery name="GetCourses" datasource="MytestDB"> select * from courses </cfquery> <cfdump var=”GetCourses”>
This would result in a nested grid structure that would output the results of the entire recordset from the courses table noted in our query.