Welcome!

You will be redirected in 30 seconds or close now.

ColdFusion Authors: Yakov Fain, Jeremy Geelan, Maureen O'Gara, Nancy Y. Nee, Tad Anderson

Related Topics: ColdFusion

ColdFusion: Article

Toward Better Error Handling - Part 4

Toward Better Error Handling - Part 4

If you've programmed in a modern programming language (Java, C, JavaScript, or even stored procedure languages), you've probably heard of exception handling via try/catch statements. ColdFusion supports the same capability.

If you're new to using them, I'll explain how they're used, and even experienced programmers may learn a thing or two about CF's particular use of try/catch exception handling.

This is the fourth in a series on error handling (see CFDJ, Vol. 2, issues 10 and 12, and Vol. 3, issue 2). In the three previous installments, we've focused on handling errors at the page level. Something goes wrong, and you want to do something other than have the user see the typical CF error message. That rather cryptic, black-on-white message is great for developers but it's not useful to end users, and we discussed several ways to improve on that.

In this article, we'll move a level further down the "error-handling hierarchy" introduced in Part 2 (see Figure 1). With try/catch handling, or specifically the CFTRY/CFCATCH tags, we're generally designing a way to detect and handle an error that we suspect may happen at runtime, but that we can't know will always happen.

Why a CFTRY?
On a simple level, CFTRY and CFCATCH are used to handle a possible error that might arise in some code. Maybe the code is doing a database interaction that could fail due to integrity errors, or the database is unavailable. Perhaps you're attempting a CFHTTP and the connection to the remote site may fail. Or you're calling a COM or Java object and the object is unavailable.

In these or any circumstance like them, if you know an error may happen, you can anticipate and handle it. Of course, if you've implemented a CFERROR tag for your application (as discussed in the last issue), then it could handle the error, but that will be on a more global scale for the entire page or, indeed, application.

But if some particular tag (or function) or set of them may cause a problem that you can at least contemplate, then the CFTRY/CFCATCH pair will give you much finer control in handling the error. Indeed, handling the error may mean simply ignoring it, as we'll see later.

A Simple Example
CFTRY and CFCATCH work in tandem to:

  1. Identify the code to be monitored
  2. Describe how to handle any error that arises
The tags are always used together, and neither can be used without the other. The simplest form of using them is:
<CFTRY>
<!--- some code you want to monitor--->
<CFCATCH>
<!--- code to handle an error that arises --->
</CFCATCH>
</CFTRY>
A specific example might be:
<CFTRY>
<CFQUERY DATASOURCE="#request.dsn#"NAME="test">
SELECT * FROM MyTable
</CFQUERY>
<CFCATCH>

An Error has occurred while selecting records from MyTable.<p>
The details of the error are:<br>
<CFOUTPUT>#CFCATCH.MESSAGE# <p>#CFCATCH.DETAIL#
<CFABORT>
</CFCATCH>
</CFTRY>

There are a few very important things to note about what goes on within this process.

What Goes on Within the CFTRY/CFCATCH Process
If you're new to TRY/CATCH processing, you should be aware of the following when starting to use this processing. The processing differs depending on whether or not an error occurs in the code being "tried."

If No Error Occurs
If no error occurs while processing the code within the CFTRY block (the CFQUERY, in our example), then:

  1. None of the code in the CFCATCH would be executed
  2. Processing would continue with the next statement after the /CFTRY
In that sense, it's like a CFIF that tests for an error code from the code being tried and only does something if there's an error.

That's the really cool thing about TRY/CATCH processing: it's as if we now have return codes to test for CF tags. Of course, some processes (like CFQUERY) do in fact return a code (a database error code, that is), but we've never had a way to trap that error before Release 4. More on that in a moment. But just keep in mind that if an error does not occur, then processing simply skips the CFCATCH and continues after the /CFTRY.

If An Error Occurs
The more important processing is what takes place if there is an error within the code being tried. In that case:

  1. The statements within the CFCATCH (in our simple example) would be executed.
  2. The normal CF error message would not be displayed to the end user. You would be responsible for determining what message (if any) to show the user.
  3. No error message would be written to the CF error logs.
  4. After processing the error handling code within the CFCATCH (when an error has been trapped this way), execution will continue with the next statement following the /CFTRY, which may not always be what you intend. Note that we've used a CFABORT tag in the example above to stop execution.
Also note that within the CFCATCH sample code, we're able to perform any CF tag. We're using a CFOUTPUT to display some information to the user. We could also use a CFMAIL to send ourselves (as developers) some information on the error. We might create a log entry in a database, but be careful not to cause yet another error and, yes, you can nest another try/catch block within a catch. (One of the new features in Release 5, CFLOG, will allow us to programmatically write an entry in the CF application log file.)

CFCATCH Error Variables
Note also that the example shows us referring to some special variables within the CFCATCH, such as CFCATCH.MESSAGE and CFCATCH.DETAIL. In the previous articles, we discussed the ERROR.DIAGNOSTICS variable as well as ERROR.BROWSER, and more. While the "ERROR." variables are not available, there are several specific new CFCATCH variables. They always include at least those shown in Table 1.

There are a few other variables available when specific kinds of errors are being handled, including ErrNumber, LockName, LockOperation, MissingFileName, Native-ErrorCode, SQLState, ErrorCode, and ExtendedInfo. The CF documentation (the CFML Language Reference) contains more detail on each of these.

Keep in mind, too, that you have full access to all the other CF variables including CGI.HTTP_ USER_AGENT (in place of ERROR.BROWSER), so the loss of the "ERROR." variables is easily supplemented by the full range of CF variables providing the same information (indeed, the only reason the "ERROR." variables were created was because the original CFERROR handler couldn't process CF tags or variables, as was discussed in the last two articles).

Before leaving the subject of CFCATCH variables, note something about how CF will catch an exception thrown by a Java object (called via CFOBJECT). From the 4.5 New Features document: "ColdFusion checks if the exception thrown is the method exception and stores the classname of the exception in the CFCATCH.MESSAGE variable."

Anticipating Multiple Exceptions
Our simple example presumes that the error-handling routine in the CFCATCH is the only one necessary for the process being "tried." But it's certainly possible that the code may be doing several things, or that the error can have one of a number of causes. There are two ramifications of this:

  1. You may have multiple CFCATCH blocks within a single CFTRY.
  2. You may distinguish one CFCATCH from another, in that case, using an exception TYPE.
In fact, the Allaire documentation shows a TYPE being provided as if it's required. It's not. There is a default type (called any) which if it's not specified, is presumed. But you may trap for any number of error types in a manner such as:
<CFCATCH TYPE="Database">
or
<CFCATCH TYPE="Lock">
More types are provided in Table 2.

The last item - "custom_type" - literally means any phrase at all. As we'll learn later, your code can "throw" an exception within a CFTRY to be caught by CFCATCH. In such a case, you can choose to create your own "type" for the error-handling mechanism to look for.

Finally, be aware that there's also a possible type of "unknown" for certain exceptions caught by TYPE="ANY". And there are a whole host of types whose names start with "COM.Allaire.ColdFusion" that may be returned under certain conditions.

Again, you don't need to worry about catching a specific type if you're simply trying to catch any error that occurs. Leave the type off. Remember, you can view the type in the available CFCATCH.TYPE variable.

A Change in Processing Multiple CFCATCHes in 4.51
Before leaving the subject of multiple CFCATCHes, you should note that there was a change in behavior as of Release 4.51. The change can be set back to the former behavior via a new CFSETTING parameter. Following is a quote from the Release 4.51 notes:

CFCATCH selection logic in ColdFusion 4.5.1 differs slightly from ColdFusion 4.0.x. In Cold-Fusion 4.0.x, the first matching CFCATCH block encountered would be selected to handle an exception. ColdFusion 4.5 scans a CFTRY tag's entire list of CFCATCH blocks to find the closest match. For example, if a CFTRY tag has a CFCATCH TYPE= TEMPLATE block, followed by a CFCATCH TYPE=MISSINGINCLUDE block, ColdFusion 4.0.x will select the TEMPLATE block to handle a MISSINGINCLUDE exception, while ColdFusion 4.5.1 will select the MISSINGINCLUDE block. ColdFusion 4.5.1 can be reset to handle a template using ColdFusion 4.0.x rules by setting the compatibility setting, <cfsetting catchexceptionsbypattern=no>.

What You Can and Can't Catch
With all this talk about catching errors, it may help to take a moment to clarify what kind of things you can and cannot catch with CFTRY/CFCATCH.

Don't Wrap Entire Program in a Try!
Frequently, folks getting started with this tool presume that they can surround their entire program with a CFTRY to catch any error (or indeed they try to place an opening CFTRY in application.cfm and a closing one in onrequestend.cfm). It won't work, and in fact it's not necessary since that's basically what the new CFERROR TYPE="Exception" (discussed in the last article) does for you. It can catch any exception that occurs in your program that's not otherwise being handled by a CFTRY/CATCH.

Preventing Syntax Errors
You may lament that you can't be warned by an error handler when you've made a syntax mistake. We all make mistakes, right ? And who has time to thoroughly test every template, especially when it may be part of a long, multi-page process that can't easily be tested? But take heed: you can (and should) at least confirm that the code will complile, and you don't actually have to run it to find out. CF comes with a syntax checker. It's executed via a page in the CFDOCS directory on the Web server where CF is installed, at http://yourdomain/CFDOCS/cfmlsyntaxcheck/cfmlsyntaxcheck.cfm. Its also reached from the Welcome Page at http://yourdomain/CFDOCS/index.htm

Can't Catch Syntax Errors
Note, though, that I said catch any exception. I didn't say it can catch any error. CFTRY can't be used to catch a syntax error. If you think about it, it makes sense. If a syntax error is encountered, the interpreter stops processing right away. It doesn't matter if there's a CFTRY surrounding the code having the error. The interpreter will never begin executing the code.

That stresses the point that CFTRY is for catching "runtime" or execution errors. It can't catch compilation or syntax errors. (Again, CFERROR can help us here, but see the end of the article for more on when it may or may not catch syntax errors.)

Use It to Ignore Array Existence Errors
In a previous CFDJ article, "Testing Existence in Arrays," (Vol. 3, issue 4), I showed how attempting to refer to an array element that doesn't exist will generate a runtime exception. Unfortunately, there's simply no function to test for such existence (see the article for more on why IsDefined and others simply don't work in this circumstance). As the article demonstrated, you could wrap such array element references in a CFTRY and use CFCATCH to simply ignore the error (code no error message and use no CFABORT, so processing simply proceeds following the /CFTRY).

Use It to Catch Unavoidable Database Errors
I had mentioned previously that one of the neat things you can now do with a CFTRY is determine if a database error has occurred. Say "so long" to users confused about ODBC errors caused by bad SQL being created, databases being locked, or servers being down; now you can catch such an error and give the user a friendlier message.

Be Careful Using It to Catch Avoidable Database Errors
Be careful about this power for trapping database errors. Some have gone a bit too far and have used the capability in a way that wasn't intended and which may be more harmful than useful. For instance, if you're facing a decision in your code about whether to do an insert or an update, don't try an insert and then if it fails, do an update instead.

It may seem that it's saving you from having to do a test to see if the record already exists (in which case an update is the action to perform), but consider that the error causes the database connection to be lost. The time involved to re-create that connection may outweigh the performance gain from avoiding the quick check for the existence of a given primary key value. Just do a "Select keyname from tablename where keyname=value" (as opposed to a more wasteful "select *"), which should execute very quickly. (Often you can program your interface so that your insert/update page is passed information that indicates whether the process is to be an insert or update, with an update being indicated if the primary key is passed from a hidden form field.)

The same consideration about not overusing CFTRY for avoidable database errors applies when doing an insert or update to a record having a column with a uniqueness constraint. Consider a userID column. There should be only one. Whether it's the primary key or has a "unique index" on the column, there can never be more than one record with a given userID. So what can you do as you contemplate inserting or updating that column with a given value, since you don't want to proceed if there's already a record with that value?

The simple solution is to just do a select on that value to see if it already exists and report an error if it does. Some clever programmers wrap the insert or update in a try, and catch and report the uniqueness constraint error if the value already exists (which would violate the uniqueness constraint and cause the insert/update to fail). Their thinking is that database will do the same check for whether the value already exists on the insert/update, so why bother suffering the redundancy of doing it first themselves?

But the cost in the lost DB connection likely outweighs the savings of just checking if the value already exists. Your mileage may vary, but consider that uniqueness is enforced via an index, so the check you do first will be very fast. Plus, while the insert or update will proceed to do another check for that value's existence, consider that the check you've done first will have caused that result to be cached in the database engine by the time the second check is done, making the "redundancy" even less painful. (Thanks to Daryl Banttari, senior consultant for Macromedia Consulting, for offering that insight.)

Some Quirks in Studio
Before concluding, you should take note of some quirks in Studio that may make working with CFTRY and CFCATCH just a little more challenging than it should be. First, Studio doesn't create a closing tag for CFTRY or CFCATCH when you type the opening tag, as it does on all others (assuming you have tag completion enabled). You can add it to the autocompletion list in Studio using Options>Settings> Editor>Tag Completion, adding a new entry for both CFTRY and CFCATCH.

You may also notice that if you look for CFCATCH in the CFML Language Reference's alphabetical listing of tags, you won't find it. It's listed as CFTRY CFCATCH. That may make sense since it's really a subtag to CFTRY, but it's confusing at first. Worse still, pressing F1 on CFCATCH won't produce the expected help for the same reason.

More to Come
I've said in previous articles that this would be the last of four parts, but as I continue the series, I find there's lots more to cover. We still have the interesting CFERROR TYPE="monitor" to discuss. There's also more to talk about regarding intentionally "raising" an error (using CFTHROW), as well as how to provide substantial improvements in error handling when using modular programming (custom tags) with CFRETHROW.

And then there are quirks in the way a sitewide error handler will override a CFERROR TYPE="Request", as well as how a sitewide missing template handler won't catch a missing file in a CFINCLUDE or CFMODULE (you have to code your own CFERROR TYPE="EXCEPTION"EXCEPTION="MISSINGINCLUDE"). There are also quirks when a CFERROR TYPE="Exception" will catch a syntax error.

Still another quirk exists in the aforementioned "CATCHEXCEPTIONSBYPATTERN" process, which doesn't quite work as expected in some situations. When throwing a type of "x.foo", the docs say we should be able to catch it with type x, but it doesn't work. We'll get to all that eventually. As always, forewarned is forearmed.

We'll also eventually talk about how to get errors logged to the logs even when being handled by CFERROR or CFTRY (which will be even easier with the new CFLOG tag in CF 5), as well as how to detect and handle a long-running request (perhaps in a different way than other errors), and generally how you might detect and handle different "types" of errors in the CFERROR handlers, now that you know about the differences among such types.

I know some have wondered how I even got four articles out of the subject of error handling. From feedback so far, you agree that there is indeed more to it than many had imagined.

More Stories By Charlie Arehart

A veteran ColdFusion developer since 1997, Charlie Arehart is a long-time contributor to the community and a recognized Adobe Community Expert. He's a certified Advanced CF Developer and Instructor for CF 4/5/6/7 and served as tech editor of CFDJ until 2003. Now an independent contractor (carehart.org) living in Alpharetta, GA, Charlie provides high-level troubleshooting/tuning assistance and training/mentoring for CF teams. He helps run the Online ColdFusion Meetup (coldfusionmeetup.com, an online CF user group), is a contributor to the CF8 WACK books by Ben Forta, and is frequently invited to speak at developer conferences and user groups worldwide.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


@ThingsExpo Stories
High-velocity engineering teams are applying not only continuous delivery processes, but also lessons in experimentation from established leaders like Amazon, Netflix, and Facebook. These companies have made experimentation a foundation for their release processes, allowing them to try out major feature releases and redesigns within smaller groups before making them broadly available. In his session at 21st Cloud Expo, Brian Lucas, Senior Staff Engineer at Optimizely, will discuss how by using...
In this strange new world where more and more power is drawn from business technology, companies are effectively straddling two paths on the road to innovation and transformation into digital enterprises. The first path is the heritage trail – with “legacy” technology forming the background. Here, extant technologies are transformed by core IT teams to provide more API-driven approaches. Legacy systems can restrict companies that are transitioning into digital enterprises. To truly become a lead...
SYS-CON Events announced today that Daiya Industry will exhibit at the Japanese Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Ruby Development Inc. builds new services in short period of time and provides a continuous support of those services based on Ruby on Rails. For more information, please visit https://github.com/RubyDevInc.
As businesses evolve, they need technology that is simple to help them succeed today and flexible enough to help them build for tomorrow. Chrome is fit for the workplace of the future — providing a secure, consistent user experience across a range of devices that can be used anywhere. In her session at 21st Cloud Expo, Vidya Nagarajan, a Senior Product Manager at Google, will take a look at various options as to how ChromeOS can be leveraged to interact with people on the devices, and formats th...
SYS-CON Events announced today that Yuasa System will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Yuasa System is introducing a multi-purpose endurance testing system for flexible displays, OLED devices, flexible substrates, flat cables, and films in smartphones, wearables, automobiles, and healthcare.
SYS-CON Events announced today that Taica will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Taica manufacturers Alpha-GEL brand silicone components and materials, which maintain outstanding performance over a wide temperature range -40C to +200C. For more information, visit http://www.taica.co.jp/english/.
As hybrid cloud becomes the de-facto standard mode of operation for most enterprises, new challenges arise on how to efficiently and economically share data across environments. In his session at 21st Cloud Expo, Dr. Allon Cohen, VP of Product at Elastifile, will explore new techniques and best practices that help enterprise IT benefit from the advantages of hybrid cloud environments by enabling data availability for both legacy enterprise and cloud-native mission critical applications. By rev...
Organizations do not need a Big Data strategy; they need a business strategy that incorporates Big Data. Most organizations lack a road map for using Big Data to optimize key business processes, deliver a differentiated customer experience, or uncover new business opportunities. They do not understand what’s possible with respect to integrating Big Data into the business model.
Recently, REAN Cloud built a digital concierge for a North Carolina hospital that had observed that most patient call button questions were repetitive. In addition, the paper-based process used to measure patient health metrics was laborious, not in real-time and sometimes error-prone. In their session at 21st Cloud Expo, Sean Finnerty, Executive Director, Practice Lead, Health Care & Life Science at REAN Cloud, and Dr. S.P.T. Krishnan, Principal Architect at REAN Cloud, will discuss how they b...
Enterprises have taken advantage of IoT to achieve important revenue and cost advantages. What is less apparent is how incumbent enterprises operating at scale have, following success with IoT, built analytic, operations management and software development capabilities – ranging from autonomous vehicles to manageable robotics installations. They have embraced these capabilities as if they were Silicon Valley startups. As a result, many firms employ new business models that place enormous impor...
SYS-CON Events announced today that Dasher Technologies will exhibit at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 - Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. Dasher Technologies, Inc. ® is a premier IT solution provider that delivers expert technical resources along with trusted account executives to architect and deliver complete IT solutions and services to help our clients execute their goals, plans and objectives. Since 1999, we'v...
SYS-CON Events announced today that MIRAI Inc. will exhibit at the Japan External Trade Organization (JETRO) Pavilion at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. MIRAI Inc. are IT consultants from the public sector whose mission is to solve social issues by technology and innovation and to create a meaningful future for people.
SYS-CON Events announced today that TidalScale, a leading provider of systems and services, will exhibit at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 - Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. TidalScale has been involved in shaping the computing landscape. They've designed, developed and deployed some of the most important and successful systems and services in the history of the computing industry - internet, Ethernet, operating s...
SYS-CON Events announced today that TidalScale will exhibit at SYS-CON's 21st International Cloud Expo®, which will take place on Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA. TidalScale is the leading provider of Software-Defined Servers that bring flexibility to modern data centers by right-sizing servers on the fly to fit any data set or workload. TidalScale’s award-winning inverse hypervisor technology combines multiple commodity servers (including their ass...
Amazon is pursuing new markets and disrupting industries at an incredible pace. Almost every industry seems to be in its crosshairs. Companies and industries that once thought they were safe are now worried about being “Amazoned.”. The new watch word should be “Be afraid. Be very afraid.” In his session 21st Cloud Expo, Chris Kocher, a co-founder of Grey Heron, will address questions such as: What new areas is Amazon disrupting? How are they doing this? Where are they likely to go? What are th...
SYS-CON Events announced today that IBM has been named “Diamond Sponsor” of SYS-CON's 21st Cloud Expo, which will take place on October 31 through November 2nd 2017 at the Santa Clara Convention Center in Santa Clara, California.
Infoblox delivers Actionable Network Intelligence to enterprise, government, and service provider customers around the world. They are the industry leader in DNS, DHCP, and IP address management, the category known as DDI. We empower thousands of organizations to control and secure their networks from the core-enabling them to increase efficiency and visibility, improve customer service, and meet compliance requirements.
Join IBM November 1 at 21st Cloud Expo at the Santa Clara Convention Center in Santa Clara, CA, and learn how IBM Watson can bring cognitive services and AI to intelligent, unmanned systems. Cognitive analysis impacts today’s systems with unparalleled ability that were previously available only to manned, back-end operations. Thanks to cloud processing, IBM Watson can bring cognitive services and AI to intelligent, unmanned systems. Imagine a robot vacuum that becomes your personal assistant tha...
SYS-CON Events announced today that IBM has been named “Diamond Sponsor” of SYS-CON's 21st Cloud Expo, which will take place on October 31 through November 2nd 2017 at the Santa Clara Convention Center in Santa Clara, California.
In his Opening Keynote at 21st Cloud Expo, John Considine, General Manager of IBM Cloud Infrastructure, will lead you through the exciting evolution of the cloud. He'll look at this major disruption from the perspective of technology, business models, and what this means for enterprises of all sizes. John Considine is General Manager of Cloud Infrastructure Services at IBM. In that role he is responsible for leading IBM’s public cloud infrastructure including strategy, development, and offering ...