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
"Cloud Academy is an enterprise training platform for the cloud, specifically public clouds. We offer guided learning experiences on AWS, Azure, Google Cloud and all the surrounding methodologies and technologies that you need to know and your teams need to know in order to leverage the full benefits of the cloud," explained Alex Brower, VP of Marketing at Cloud Academy, in this SYS-CON.tv interview at 21st Cloud Expo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clar...
In his session at 21st Cloud Expo, Carl J. Levine, Senior Technical Evangelist for NS1, will objectively discuss how DNS is used to solve Digital Transformation challenges in large SaaS applications, CDNs, AdTech platforms, and other demanding use cases. Carl J. Levine is the Senior Technical Evangelist for NS1. A veteran of the Internet Infrastructure space, he has over a decade of experience with startups, networking protocols and Internet infrastructure, combined with the unique ability to it...
"IBM is really all in on blockchain. We take a look at sort of the history of blockchain ledger technologies. It started out with bitcoin, Ethereum, and IBM evaluated these particular blockchain technologies and found they were anonymous and permissionless and that many companies were looking for permissioned blockchain," stated René Bostic, Technical VP of the IBM Cloud Unit in North America, in this SYS-CON.tv interview at 21st Cloud Expo, held Oct 31 – Nov 2, 2017, at the Santa Clara Conventi...
Gemini is Yahoo’s native and search advertising platform. To ensure the quality of a complex distributed system that spans multiple products and components and across various desktop websites and mobile app and web experiences – both Yahoo owned and operated and third-party syndication (supply), with complex interaction with more than a billion users and numerous advertisers globally (demand) – it becomes imperative to automate a set of end-to-end tests 24x7 to detect bugs and regression. In th...
Widespread fragmentation is stalling the growth of the IIoT and making it difficult for partners to work together. The number of software platforms, apps, hardware and connectivity standards is creating paralysis among businesses that are afraid of being locked into a solution. EdgeX Foundry is unifying the community around a common IoT edge framework and an ecosystem of interoperable components.
"MobiDev is a software development company and we do complex, custom software development for everybody from entrepreneurs to large enterprises," explained Alan Winters, U.S. Head of Business Development at MobiDev, in this SYS-CON.tv interview at 21st Cloud Expo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
Large industrial manufacturing organizations are adopting the agile principles of cloud software companies. The industrial manufacturing development process has not scaled over time. Now that design CAD teams are geographically distributed, centralizing their work is key. With large multi-gigabyte projects, outdated tools have stifled industrial team agility, time-to-market milestones, and impacted P&L stakeholders.
"Space Monkey by Vivent Smart Home is a product that is a distributed cloud-based edge storage network. Vivent Smart Home, our parent company, is a smart home provider that places a lot of hard drives across homes in North America," explained JT Olds, Director of Engineering, and Brandon Crowfeather, Product Manager, at Vivint Smart Home, in this SYS-CON.tv interview at @ThingsExpo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
"Akvelon is a software development company and we also provide consultancy services to folks who are looking to scale or accelerate their engineering roadmaps," explained Jeremiah Mothersell, Marketing Manager at Akvelon, in this SYS-CON.tv interview at 21st Cloud Expo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
Coca-Cola’s Google powered digital signage system lays the groundwork for a more valuable connection between Coke and its customers. Digital signs pair software with high-resolution displays so that a message can be changed instantly based on what the operator wants to communicate or sell. In their Day 3 Keynote at 21st Cloud Expo, Greg Chambers, Global Group Director, Digital Innovation, Coca-Cola, and Vidya Nagarajan, a Senior Product Manager at Google, discussed how from store operations and ...
"There's plenty of bandwidth out there but it's never in the right place. So what Cedexis does is uses data to work out the best pathways to get data from the origin to the person who wants to get it," explained Simon Jones, Evangelist and Head of Marketing at Cedexis, in this SYS-CON.tv interview at 21st Cloud Expo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
SYS-CON Events announced today that CrowdReviews.com has been named “Media Sponsor” of SYS-CON's 22nd International Cloud Expo, which will take place on June 5–7, 2018, at the Javits Center in New York City, NY. CrowdReviews.com is a transparent online platform for determining which products and services are the best based on the opinion of the crowd. The crowd consists of Internet users that have experienced products and services first-hand and have an interest in letting other potential buye...
SYS-CON Events announced today that Telecom Reseller has been named “Media Sponsor” of SYS-CON's 22nd International Cloud Expo, which will take place on June 5-7, 2018, at the Javits Center in New York, NY. Telecom Reseller reports on Unified Communications, UCaaS, BPaaS for enterprise and SMBs. They report extensively on both customer premises based solutions such as IP-PBX as well as cloud based and hosted platforms.
It is of utmost importance for the future success of WebRTC to ensure that interoperability is operational between web browsers and any WebRTC-compliant client. To be guaranteed as operational and effective, interoperability must be tested extensively by establishing WebRTC data and media connections between different web browsers running on different devices and operating systems. In his session at WebRTC Summit at @ThingsExpo, Dr. Alex Gouaillard, CEO and Founder of CoSMo Software, presented ...
WebRTC is great technology to build your own communication tools. It will be even more exciting experience it with advanced devices, such as a 360 Camera, 360 microphone, and a depth sensor camera. In his session at @ThingsExpo, Masashi Ganeko, a manager at INFOCOM Corporation, introduced two experimental projects from his team and what they learned from them. "Shotoku Tamago" uses the robot audition software HARK to track speakers in 360 video of a remote party. "Virtual Teleport" uses a multip...
A strange thing is happening along the way to the Internet of Things, namely far too many devices to work with and manage. It has become clear that we'll need much higher efficiency user experiences that can allow us to more easily and scalably work with the thousands of devices that will soon be in each of our lives. Enter the conversational interface revolution, combining bots we can literally talk with, gesture to, and even direct with our thoughts, with embedded artificial intelligence, whic...
SYS-CON Events announced today that Evatronix 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. Evatronix SA offers comprehensive solutions in the design and implementation of electronic systems, in CAD / CAM deployment, and also is a designer and manufacturer of advanced 3D scanners for professional applications.
Leading companies, from the Global Fortune 500 to the smallest companies, are adopting hybrid cloud as the path to business advantage. Hybrid cloud depends on cloud services and on-premises infrastructure working in unison. Successful implementations require new levels of data mobility, enabled by an automated and seamless flow across on-premises and cloud resources. In his general session at 21st Cloud Expo, Greg Tevis, an IBM Storage Software Technical Strategist and Customer Solution Architec...
To get the most out of their data, successful companies are not focusing on queries and data lakes, they are actively integrating analytics into their operations with a data-first application development approach. Real-time adjustments to improve revenues, reduce costs, or mitigate risk rely on applications that minimize latency on a variety of data sources. In his session at @BigDataExpo, Jack Norris, Senior Vice President, Data and Applications at MapR Technologies, reviewed best practices to ...
An increasing number of companies are creating products that combine data with analytical capabilities. Running interactive queries on Big Data requires complex architectures to store and query data effectively, typically involving data streams, an choosing efficient file format/database and multiple independent systems that are tied together through custom-engineered pipelines. In his session at @BigDataExpo at @ThingsExpo, Tomer Levi, a senior software engineer at Intel’s Advanced Analytics gr...