Ordinarily, when ColdFusion encounters an error, it stops processing and displays an error message or error page (as specified by the cferror
tag). However, you can use ColdFusion's exception handling tags to catch and process exceptions in ColdFusion pages. Exceptions include any event that disrupts the normal flow of instructions in a ColdFusion page, such as failed database operations, missing include files, or developer-specified events.
In order for your code to handle an exception, the tags in question must appear within a cftry
block. It is a good idea to enclose an entire application page in a cftry
block. You then follow the cftry
block with cfcatch
blocks, which respond to potential errors. When an exception occurs within the cftry
block, processing is thrown to the cfcatch
block for that type of exception.
Note For cases when the error handler is not able to successfully handle the thrown error, use the |
Here is an outline for using cftry
and cfcatch
to handle errors:
<cftry
> ... Put your page's application code here ... <cfcatch
type
="exception type1"> ... Add exception processing code here ... </cfcatch
> <cfcatch
type
="exception type2"> ... Add exception processing code here ... </cfcatch
> <cfcatch
type
="Any"> ... Add exception processing code appropriate for all other exceptions here ... </cfcatch
> </cftry
>
To catch errors in a single problematic SQL statement, for example, you might narrow the focus by surrounding the ColdFusion tag that contains the SQL statement with a cftry
block and following it with a cfcatch type="Database"
tag that displays the information in the cfcatch.SQLState
variable.
Note Do not attempt to enclose an entire application in a |
For information on the cftry
, cfcatch
, cfrethrow
, and cfthrow
tags, see the CFML Reference.
ColdFusion Server supports several types of recoverable exceptions. Use the type
attribute in the cfcatch
tag to determine which type of exception to catch. You can also use these types as the values of the exception
attribute in cferror type=exception
tags.
You can specify the following basic exception types. For a list of advanced exception types, see the CFML Reference.
Specifying the type as any
causes the ColdFusion Application Server to catch internal exceptions, memory allocation errors, and access violations, which you might not be prepared to handle.
Applications can optionally use the cfthrow
tag to raise custom exceptions. Such exceptions are caught with any of the following type specifications:
type="custom_exception_type"
type="application
"type="any"
The custom_exception_type type designates the name of a user-defined type specified in the cfthrow
tag.
An exception raised within a cfcatch
block cannot be handled by the cftry
block that immediately encloses the cfcatch
tag.
Within a cfcatch
block, the active exception's properties can be accessed as variables. The following variables are available in most cfcatch blocks:
On the Debugging Settings page in the ColdFusion Administrator you can select the Enable CFML stack trace option. When you enable this option, cfcatch
blocks make available an array of structures called cfcatch
.tagContext. Each structure represents one level of the ColdFusion runtime's active tag context at the time when the ColdFusion interpreter detected the exception.
The structure at position 1 of the array represents the outermost tag in the stack of tags that were executing when the interpreter detected the exception. The structure at position ArrayLen(cfcatch
.tagContext) represents the currently executing tag at the time the interpreter detected the exception.
The tagContext structures have the following attributes:
Note Clear the Enable CFML stack trace option to avoid having production servers expend resources creating a traceback stack by default. When you turn off this setting, |
The following additional variables are available whenever the exception type is database:
Property variable |
Description |
---|---|
cfcatch.errnumber |
An internal expression error number, valid only when type="Expression". |
The following additional information is available for exceptions related to cflock
sections:
The following additional variable is available if the error is caused by a missing file specified by a cfinclude
tag:
Property variable |
Description |
---|---|
cfcatch.missingFileName |
The name of the missing file. |
Use cftry
with cfcatch
to handle exceptions based on their point of origin within an application page, or based on diagnostic information.
Use the cftry
tag with one or more cfcatch
blocks to define a ColdFusion block for exception handling. When an application page raises an error condition, the ColdFusion Server checks the stack of currently active blocks for a corresponding cfcatch
handler. In particularly problematic cases, you might enclose an exception-prone tag in a specialized combination of cftry
and cfcatch
to immediately isolate the tag's exceptions, or to use cftry
with cfcatch
type="Any"
at a main processing level to gracefully terminate a subsystem's processing in case of an unexpected error.
The following example shows cftry
and cfcatch
, using the CompanyInfo data source used in many of the examples in this book and a sample included file, includeme.cfm.
If an exception occurs during the cfquery
statement's execution, the application page flow switches to the cfcatch
type
="Database"
exception handler. It then resumes with the next statement after the cftry
block, once the cfcatch
type
="Database"
handler completes.
Similarly, the cfcatch
type
="MissingInclude"
block handles exceptions raised by the cfinclude
tag. Any unknown, but possibly recoverable, exceptions are handled by the cfcatch
type
="Any"
block.
<!--- Wrap code you want to check in a cftry block --->
<cfset EmpID=3>
<cftry>
<cfquery name="test" datasource="CompanyInfo">
SELECT Dept_ID, FirstName, LastName
FROM Employee
WHERE Emp_ID=#EmpID#
</cfquery>
<html>
<head>
<title>Test cftry/cfcatch</title>
</head>
<body>
<hr>
<cfinclude template="includeme.cfm">
<cfoutput query="test">
<p>Department: #Dept_ID#<br>
Last Name: #LastName#<br>
First Name: #FirstName#</p>
</cfoutput>
<hr>
<!--- Use cfcatch to test for missing included files. --->
<!--- Print Message and Detail error messages. --->
<!--- Block executes only if a MissingInclude exception is thrown. --->
<cfcatch type="MissingInclude">
<h1>Missing Include File</h1>
<cfoutput>
<ul>
<li><b>Message:</b> #cfcatch.Message#
<li><b>Detail:</b> #cfcatch.Detail#
<li><b>File name:</b> #cfcatch.MissingFilename#
</ul>
</cfoutput>
</cfcatch>
<!--- Use cfcatch to test for database errors.--->
<!--- Print error messages. --->
<!--- Block executes only if a Database exception is thrown. --->
<cfcatch type="Database">
<h1>Database Error</h1>
<cfoutput>
<ul>
<li><b>Message:</b> #cfcatch.Message#
<li><b>Native error code:</b> #cfcatch.NativeErrorCode#
<li><b>SQLState:</b> #cfcatch.SQLState#
<li><b>Detail:</b> #cfcatch.Detail#
</ul>
</cfoutput>
</cfcatch>
<!--- Use cfcatch with TYPE="Any" --->
<!--- to find unexpected exceptions. --->
<cfcatch type="Any">
<cfoutput>
<h1>Other Error: #cfcatch.Type#</h1>
<ul>
<li><b>Message:</b> #cfcatch.message#
<li><b>Detail:</b> #cfcatch.Detail#
</ul>
</cfoutput>
</cfcatch>
</cftry>
</body>
</html>
cfcatch type="MissingInclude"
block displays the error.
cfquery
tag change the line:FROM Employee
to:
FROM Employer
Display the page. This time the cfcatch type="Database"
block displays an error message.
cfoutput
line:<p>Department: #Dept_ID#<br>
to:
<p>Department: #DepartmentID#<br>
Display the page. This time the cfcatch type="Any"
block displays an error message indicating an expression error.
The type
attribute allows a cfthrow
tag to throw an exception of a specific type, which can be caught by a cfcatch
tag that has a matching type
attribute.
A cfthrow
tag without a type
attribute will throw a type
="Application" exception.
A naming convention for custom exception types follows a convention that is similar to Java class naming conventions: domain name in reverse order, followed by project identifiers, as in this example:
<cfthrow
type="Invalid_field.codeValue" errorcode="Dodge14B">
The predefined exception types, except for type="Application",
are reserved; for example, <cfthrow type="Database">
will be rejected.
A cfcatch
tag can specify a custom type as well as one of the predefined types. For example, to catch the exception thrown above, you use this syntax:
<cfcatch type="Invalid_field.codeValue">
ColdFusion uses the catch type as a pattern to find a catch handler. For example,
<cfthrow type="MyApp.BusinessRuleException.InvalidAccount">
would be handled by any of the following cfcatch
error handlers.
<cfcatch
type
="MyApp.BusinessRuleException.InvalidAccount">
<cfcatch
type
="MyApp.BusinessRuleException"> <cfcatch
type
="MyApp">
The handler that matches most exactly handles the error. Therefore, in this case, the MyApp.BusinessRuleException.InvalidAccount
handler gets invoked. However, if you used the following cfthrow
tag:
<cfthrow type="MyApp.BusinessRuleException.InvalidVendorCode
the MyApp.BusinessRuleException
handler receives the error.
The type comparison is case-insensitive. To match types exactly, rather than performing pattern matching, use the cfsetting
attribute catchExceptionsByPattern="No"
.