Handling runtime exceptions with ColdFusion tags

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. Ordinarily, when ColdFusion encounters an exception, it stops processing and displays an error message, or an error page specified by a cferror tag or the Site-wide Error Handler option on the Settings page in the Administrator. However, you can use the ColdFusion exception handling tags to catch and process runtime exceptions directly in ColdFusion pages. 
This ability to handle exceptions directly in your application pages enables your application to do the following:

  • Respond appropriately to specific errors within the context of the current application page
  • Recover from errors whenever possible.

Exception-handling tags

ColdFusion provides the exception-handling tags listed in the following table:

Tag

Description

cftry

If any exceptions occur while processing the tag body, look for a cfcatch tag that handles the exception, and execute the code in the cfcatch tag body.

cfcatch

Execute code in the body of this tag if the exception caused by the code in the cftry tag body matches the exception type specified in this tag's attributes.Used in cftry tag bodies only.

cfthrow

Generate a user-specified exception.

cfrethrow

Exit the current cfcatch block and generates a new exception of the same type. Used only in cfcatch tag bodies.

Using cftry and cfcatch tags

The cftry tag lets you go beyond reporting error data to the user:

  • You can include code that recovers from errors so your application can continue processing without alerting the user.
  • You can create customized error messages that apply to the specific code that causes the error.
    For example, you can use cftry to catch errors in code that enters data from a user registration form to a database. The cfcatch code could do the following:
  1. Retry the query, so the operation succeeds if the resource was only temporarily unavailable.
  2. If the retries fail:
    • Display a custom message to the user
    • Post the data to an e-mail address so the company staff can enter the data after the problem has been solved.
      Code that accesses external resources such as databases, files, or LDAP servers where resource availability is not guaranteed is a good candidate for using try/catch blocks.
Try/catch code structure

In order for your code to directly 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. 
Here is an outline for using cftry and cfcatch to handle errors:

<cftry>
Put your 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>

Try/catch code rules and recommendations

Follow these rules and recommendations when you use cftry and cfcatch tags:

  • The cfcatch tags must follow all other code in a cftry tag body.
  • You can nest cftryblocks. For example, the following structure is valid:

    <cftry>
    code that may cause an exception
    <cfcatch ...>
    <cftry>
    First level of exception handling code
    <cfcatch ...>
    Second level of exception handling code
    </cfcatch
    </cftry>
    </cfcatch>
    </cftry>

    If an exception occurs in the first level of exception-handling code, the inner cfcatch block can catch and handle it. (An exception in a cfcatch block cannot be handled by cfcatch blocks at the same level as that block.)

  • ColdFusion always responds to the latest exception that gets raised. For example, if code in a cftry block causes an exception that gets handled by a cfcatch block, and the cfcatch block causes an exception that has no handler, ColdFusion displays the default error message for the exception in the cfcatch block, and you are not notified of the original exception.
  • If an exception occurs when the current tag is nested inside other tags, the CFML processor checks the entire stack of open tags until it finds a suitable cftry/cfcatch combination or reaches the end of the stack.
  • Use cftry with cfcatch to handle exceptions based on their point of origin within an application page, or based on diagnostic information.
  • The entire cftry tag, including all its cfcatch tags, must be on a single ColdFusion page. You cannot place the <cftry> start tag on one page and have the </cftry> end tag on another page.
  • For cases when a cfcatch block is not able to successfully handle an error, consider using the cfrethrow tag, as described in Using the cfrethrow tag in Handling runtime exceptions with ColdFusion tags.
  • If an exception can be safely ignored, use a cfcatchtag with no body; for example:

    <cfcatch Type = Database />

  • In problematic cases, enclose an exception-prone tag in a specialized combination of cftry and cfcatch tags to immediately isolate the tag's exceptions.
Exception information in cfcatch blocks

Within the body of a cfcatch tag, the active exception's properties are available in a cfcatch object. The object contents are described as follows:

Standard cfcatch variables

The following table describes the variables that are available in most cfcatch blocks:

Property variable

Description

cfcatch.Detail

A detailed message from the CFML compiler. This message, which can contain HTML formatting, can help to determine which tag threw the exception. The cfcatch.Detail value is available in the CFScript catch statement as the exceptionVariable parameter.

cfcatch.ErrorCode

The cfthrow tag can supply a value for this code through the errorCode attribute. For Type="Database", cfcatch.ErrorCode has the same value as cfcatch.SQLState. Otherwise, the value of cfcatch.ErrorCode is the empty string.

cfcatch.ExtendedInfo

Custom error message information. This is returned only to cfcatch tags for which the type attribute is Application or a custom type.Otherwise, the value of cfcatch.ExtendedInfo is the empty string.

cfcatch.Message

The exception's default diagnostic message, if one was provided. If no diagnostic message is available, this is an empty string.The cfcatch.Message value is included in the value of the CFScript catch statement exceptionVariable parameter.

cfcatch.RootCause

The Java servlet exception reported by the JVM as the cause of the "root cause" of the exception.

cfcatch.TagContext

An array of structures structure containing information for each tag in the tag stack The tag stack consists of each tag that is currently open.

cfcatch.Type

The exception's type, returned as a string.

 

Note: If you use the cfdump tag to display the cfcatch variable, the display does not include variables that do not have values.

The cfcatch.TagContext variable contains an array of tag information structures. Each structure represents one level of the active tag context at the time when ColdFusion detected the exception. That is, there is one structure for each tag that is open at the time of the exception. For example, if the exception occurs in a tag on a custom tag page, the tag context displays information about the called custom tag and the tag in which the error occurs.
The structure at position 1 in the array represents the currently executing tag at the time the exception was detected. The structure at position arrayLen represents the initial tag in the stack of tags that were executing when the compiler detected the exception.
The following table lists the tagContext structure attributes:

Entry

Description

Column

Obsolete (retained for backwards compatibility). Always 0.

ID

The tag in which the exception occurred. Exceptions in CFScript are indicated by two question marks (??). All custom tags, including those called directly, are identified as cfmodule.

Line

The line on the page in which the tag is located.

Raw_Trace

The raw Java stack trace for the error.

Template

The pathname of the application page that contains the tag.

Type

The type of page; it is always a ColdFusion page.

Database exceptions

The following additional variables are available whenever the exception type is database:

Property variable

Description

cfcatch.NativeErrorCode

The native error code associated with this exception. Database drivers typically provide error codes to assist in the diagnosis of failing database operations. The values assumed by cfcatch.NativeErrorCode are driver-dependent.If no error code is provided, the value of cfcatch.nativeErrorCode is -1. The value is 0 for queries of queries.

cfcatch.SQLState

The SQLState code associated with this exception. Database drivers typically provide error codes to assist in the diagnosis of failing database operations. SQLState codes are more consistent across database systems than native error codes. If the driver does not provide an SQLState value, the value of cfcatch.SQLState is -1.

cfcatch.Sql

The SQL statement sent to the data source.

cfcatch.queryError

The error message as reported by the database driver.

cfcatch.where

If the query uses the cfqueryparam tag, query parameter name-value pairs.

Expression exceptions

The following variable is only available for Expression exceptions:

Property variable

Description

cfcatch.ErrNumber

An internal expression error number, valid only when type="Expression".

Locking exceptions

The following additional information is available for exceptions related to errors that occur in cflock tags:

Property variable

Description

cfcatch.lockName

The name of the affected lock. This is set to "anonymous" if the lock name is unknown.

cfcatch.lockOperation

The operation that failed. This is set to "unknown" if the failed operation is unknown.

Missing include exceptions

The following additional variable is available if a missing file specified by a cfinclude tag causes the error.

Property variable

Description

cfcatch.missingFileName

The name of the missing file.

Using the cftry tag: an example

The following example shows the cftry and cfcatch tags. It uses the cfdocexamples data source, which many of the examples listed here use, and a sample included file, includeme.cfm.
If an exception occurs when you run the cfquery statement, 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.

<!--- Wrap code you want to check in a cftry block --->
<cfset EmpID=3>
<cfparam name="errorCaught" default="">
<cftry>
<cfquery name="test" datasource="cfdocexamples">
SELECT Dept_ID, FirstName, LastName
FROM Employee
WHERE Emp_ID=#EmpID#
</cfquery>

<html>
<head>
<title>Test cftry/cfcatch</title>
</head>
<body>
<cfinclude template="includeme.cfm">
<cfoutput query="test">
<p>Department: #Dept_ID#<br>
Last Name: #LastName#<br>
First Name: #FirstName#</p>
</cfoutput>

<!--- 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>Filename:</b> #cfcatch.MissingFileName#
</ul>
</cfoutput>
<cfset errorCaught = "MissingInclude">
</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>
<cfset errorCaught = "Database">
</cfcatch>

<!--- Use cfcatch with type="Any" --->
<!--- to find unexpected exceptions. --->
<cfcatch type="Any">
<cfoutput>
<hr>
<h1>Other Error: #cfcatch.Type#</h1>
<ul>
<li><b>Message:</b> #cfcatch.Message#
<li><b>Detail:</b> #cfcatch.Detail#
</ul>
</cfoutput>
<cfset errorCaught = "General Exception">
</cfcatch>
</body>
</html>
</cftry>

Use the following procedure to test the code.

Test the code
  1. Make sure that there is no includeme.cfm file and display the page. The cfcatch type="MissingInclude" block displays the error.
  2. Create a nonempty includeme.cfm file and display the page. If your database is configured properly, you see an employee entry and do not get any error.
  3. In the cfquerytag, change the line:

    FROM Employee

    to:

    FROM Employer

    Display the page. This time the cfcatch type="Database" block displays an error message.

  4. Change Employer to Employee. Change the cfoutputline:

    <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.

  5. Change DepartmentID back to Dept_ID and redisplay the page. The page displays properly.Open \CFusion\Log\MyAppPage.log in your text editor. You should see a header line, an initialization line, and four detail lines, like the following:

    "Severity","ThreadID","Date","Time","Application","Message"
    "Information","web-0","11/20/01", "16:27:08",, "cf_root\runtime\servers\default\logs\ MyAppPage.log initialized"
    "Information","web-0","11/20/01","16:27:08",,
    "Page: web_root/MYStuff/MyDocs/ cftryexample.cfm Error: MissingInclude"
    "Information","web-1","11/20/01","16:27:32",,"
    Page: web_root/MYStuff/MyDocs/ cftryexample.cfm Error: "
    "Information","web-0","11/20/01","16:27:49",,
    "Page: web_root/MYStuff/MyDocs/ cftryexample.cfm Error: Database"
    "Information","web-1","11/20/01","16:28:21",,
    "Page: web_root/MYStuff/MyDocs/ cftryexample.cfm Error: General Exception"
    "Information","web-0","11/20/01","16:28:49",,
    "Page: web_root/MYStuff/MyDocs/ cftryexample.cfm Error: "

     

Reviewing the code

The following table describes the code:

Code

Description

 

<cfset EmpID=3>
<cfparam name="errorCaught" default="">

 

Initializes the employee ID to a valid value. An application would get the value from a form or other source.Sets the default errorCaught variable value to the empty string (to indicate no error was caught).There is no need to put these lines in a cftry block.

 

<cftry>
<cfquery name="test" datasource="cfdocexamples">
SELECT Dept_ID, FirstName, LastName
FROM Employee
WHERE Emp_ID=#EmpID#
</cfquery>

 

Starts the cftry block. Exceptions from here to the end of the block can be caught by cfcatch tags.Queries the cfdocexamples database to get the data for the employee identified by the EmpID variable.

 

<html>
<head>
<title>Test cftry/cfcatch</title>
</head>
<body>
<cfinclude template="includeme.cfm">
<cfoutput query="test">
<p>Department: #Dept_ID#<br>
Last Name: #LastName#<br>
First Name: #FirstName#</p>
</cfoutput>

 

Begins the HTML page. This section contains all the code that displays information if no errors occur.Includes the includeme.cfm page.Displays the user information record from the test query.

 

<cfcatch type="MissingInclude">
<h1>Missing Include File</h1>
<cfoutput>
<ul>
<li><b>Message:</b> #cfcatch.Message#
<li><b>Detail:</b> #cfcatch.Detail#
<li><b>Filename:</b> #cfcatch.MissingFileName#
</ul>
</cfoutput>
<cfset errorCaught = "MissingInclude">
</cfcatch>

 

Handles exceptions thrown when a page specified by the cfinclude tag cannot be found. Displays cfcatch variables, including the ColdFusion basic error message, detail message, and the name of the file that could not be found.Sets the errorCaught variable to indicate the error type.

 

<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>
<cfset errorCaught = "Database">
</cfcatch>

 

Handles exceptions thrown when accessing a database. Displays cfcatch variables, including the ColdFusion basic error message, the error code and SQL state reported by the databases system, and the detailed error message.Sets the errorCaught variable to indicate the error type.

 

<cfcatch type="Any">
<cfoutput>
<hr>
<h1>Other Error: #cfcatch.Type#</h1>
<ul>
<li><b>Message:</b> #cfcatch.Message#
<li><b>Detail:</b> #cfcatch.Detail#
</ul>
</cfoutput>
<cfset errorCaught = "General Exception">
</cfcatch>

 

Handles any other exceptions generated in the cftry block.Since the error can occur after information has displayed (in this case, the contents of the include file), draws a line before writing the message text.Displays the ColdFusion basic and detailed error message.Sets the errorCaught variable to indicate the error type.

 

</body>
</html>
</cftry>

 

Ends the HTML page, then the cftry block.

Using the cfthrow tag

You can use the cfthrow tag to raise your own, custom exceptions. When you use the cfthrow tag, you specify any or all of the following information:

Attribute

Meaning

type

The type of error. It can be a custom type that has meaning only to your application, such as InvalidProductCode. You can also specify Application, the default type. You cannot use any of the predefined ColdFusion error types, such as Database or MissingTemplate.

message

A brief text message indicating the error.

detail

A more detailed text message describing the error.

errorCode

An error code that is meaningful to the application. This field is useful if the application uses numeric error codes.

extendedInfo

Any additional information of use to the application.

All of these values are optional. You access the attribute values in cfcatch blocks and Exception type error pages by prefixing the attribute with either cfcatch or error, as in cfcatch.extendedInfo. The default ColdFusion error handler displays the message and detail values in the Message pane and the remaining values in the Error Diagnostic Information pane.

Catching and displaying thrown errors

The cfcatch tag catches a custom exception when you use any of the following values for the cfcatch type attribute:

  • The custom exception type specified in the cfthrow tag.
  • A custom exception type that hierarchically matches the initial portion of the type specified in the cfthrow tag. For more information, see the next section, Custom error type name hierarchy.
  • Application, which matches an exception that is thrown with the Application type attribute or with no type attribute.
  • Any, which matches any exception that is not caught by a more specific cfcatch tag.
    Similarly, if you specify any of these types in a cferror tag, the specified error page displays information about the thrown error.
    Because the cfthrow tag generates an exception, a Request error handler or the Site-wide error handler can also display these errors.
Custom error type name hierarchy

You can name custom exception types using a method that is similar to Java class naming conventions: domain name in reverse order, followed by project identifiers, as in the following example:

<cfthrow
type="com.myCompany.myApp.Invalid_field.codeValue"
errorcode="Dodge14B">

This fully qualified naming method is not required; you can use shorter naming rules, for example, myApp.Invalid_field.codeValue, or even codeValue. 
This naming method is not just a convention; ColdFusion uses the naming hierarchy to select from a possible hierarchy of error handlers. For example, assume that you use the following cfthrow statement:

<cfthrow type="MyApp.BusinessRuleException.InvalidAccount">

Any of the following cfcatch error handlers would handle this error:

<cfcatch type="MyApp.BusinessRuleException.InvalidAccount">
<cfcatch type="MyApp.BusinessRuleException">
<cfcatch type="MyApp">

The handler that most exactly matches handles the error. In this case, the MyApp.BusinessRuleException.InvalidAccount handler runs. However, if you used the following cfthrow tag:

<cfthrow type="MyApp.BusinessRuleException.InvalidVendorCode

the MyApp.BusinessRuleException handler receives the error.
The type comparison is not case sensitive.

When to use the cfthrow tag

Use the cfthrow tag when your application can identify and handle application-specific errors. One typical use for the cfthrow tag is in implementing custom data validation. The cfthrow tag is also useful for throwing errors from a custom tag page to the calling page. 
For example, on a form action page or custom tag used to set a password, the application can determine whether the password entered is a minimum length, or contains both letters and number, and throw an error with a message that indicates the password rule that was broken. The cfcatch block handles the error and tells the user how to correct the problem.

Using the cfrethrow tag

The cfrethrow tag lets you create a hierarchy of error handlers. It tells ColdFusion to exit the current cfcatch block and "rethrow" the exception to the next level of error handler. Thus, if an error handler designed for a specific type of error cannot handle the error, it can rethrow the error to a more general-purpose error handler. The cfrethrow tag can only be used in a cfcatch tag body.

The cfrethrow tag syntax

The following pseudocode shows how you can use the cfrethrow tag to create an error-handling hierarchy:

<cftry>
<cftry>
Code that might throw a database error
<cfcatch Type="Database">
<cfif Error is of type I can Handle>
Handle it
<cfelse>
<cfrethrow>
</cfif
</cfcatch>
</cftry>
<cfcatch Type="Any">
General Error Handling code
</cfcatch>
</cftry>

Although this example uses a Database error as an example, you can use any cfcatch type attribute in the innermost error type. 
Follow these rules when you use the cfrethrow tag:

  • Nest cftry tags, with one tag for each level of error handling hierarchy. Each level contains the cfcatch tags for that level of error granularity.
  • Place the most general error catching code in the outermost cftry block.
  • Place the most specific error catching code in the innermost cftry block.
  • Place the code that can cause an exception error at the top of the innermost cftry block.
  • End each cfcatch block except those in the outermost cftry block with a cfrethrow tag.

Example: using nested tags, cfthrow, and cfrethrow

The following example shows many of the discussed techniques including nested cftry blocks and the cfthrow and cfrethrow tags. The example includes a simple calling page and a custom tag page:

  • The calling page does little more than call the custom tag with a single attribute, a name to be looked up in a database. It does show, however, how a calling page can handle an exception thrown by the custom tag.
  • The custom tag finds all records in the cfdocexamples database with a matching last name, and returns the results in a Caller variable. If it fails to connect with the main database, it tries a backup database.
The calling page

The calling page represents a section from a larger application page. To keep things simple, the example hard-codes the name to be looked up.

<cftry>
<cf_getEmps EmpName="Jones">
<cfcatch type="myApp.getUser.noEmpName">
<h2>Oops</h2>
<cfoutput>#cfcatch.Message#</cfoutput><br>
</cfcatch>
</cftry>
<cfif isdefined("getEmpsResult")>
<cfdump var="#getEmpsResult#">
</cfif>

Reviewing the code

The following table describes the code:

Code

Description

 

<cftry>
<cf_getEmps EmpName="Jones">

 

In a cftry block, calls the cf_getEmps custom tag (getEmps.cfm).

 

<cfcatch type="myApp.getUser.noEmpName">
<h2>Oops</h2>
<cfoutput>#cfcatch.Message#</cfoutput><br>
</cfcatch>

 

If the tag throws an exception indicating that it did not receive a valid attribute, catches the exception and displays a message, including the message variable set by the cfthrow tag in the custom tag.

 

<cfif isdefined("getEmpsResult")>
<cfdump var="#getEmpsResult#">
</cfif>

 

If the tag returns a result, uses the cfdump tag to display it. (A production application would not use the cfdump tag.)

The custom tag page

The custom tag page searches for the name in the database and returns any matching records in a getEmpsResult variable in the calling page. It includes several nested cftry blocks to handle error conditions. For a full description, see Reviewing the code section, following the example:Save the following code as getEmps.cfm in the same directory as the calling page.

<!--- If the tag didn't pass an attribute, throw an error to be handled by
the calling page --->
<cfif NOT IsDefined("attributes.EmpName")>
<cfthrow Type="myApp.getUser.noEmpName"
message = "Last Name was not supplied to the cf_getEmps tag.">
<cfexit method = "exittag">
<!--- Have a name to look up --->
<cfelse>
<!--- Outermost Try Block --->
<cftry>

<!--- Inner Try Block --->
<cftry>
<!--- Try to query the main database and set a caller variable to the result --->
<cfquery Name = "getUser" DataSource="cfdocexamples">
SELECT *
FROM Employee
WHERE LastName = '#attributes.EmpName#'
</cfquery>
<cfset caller.getEmpsResult = getuser>
<!--- If the query failed with a database error, check the error type
to see if the database was found --->
<cfcatch type= "Database">
<cfif (cfcatch.SQLState IS "S100") OR (cfcatch.SQLState IS
"IM002")>

<!--- If the database wasn't found, try the backup database --->
<!--- Use a third-level Try block --->
<cftry>
<cfquery Name = "getUser" DataSource="cfdocexamplesBackup">
SELECT *
FROM Employee
WHERE LastName = '#attributes.EmpName#'
</cfquery>
<cfset caller.getEmpsResult = getuser>

<!--- If still get a database error, just return to the calling page
without setting the caller variable. There is no cfcatch body.
This might not be appropriate in some cases.
The Calling page ends up handling this case as if a match was not
found --->
<cfcatch type = "Database" />
<!--- Still in innermost try block. Rethrow any other errors to the next
try block level --->
<cfcatch type = "Any">
<cfrethrow>
</cfcatch>
</cftry>

<!--- Now in second level try block.
Throw all other types of Database exceptions to the next try
block level --->
<cfelse>
<cfrethrow>
</cfif>
</cfcatch>
<!--- Throw all other exceptions to the next try block level --->
<cfcatch type = "Any">
<cfrethrow>
</cfcatch>
</cftry>

<!--- Now in Outermost try block.
Handle all unhandled exceptions, including rethrown exceptions, by
displaying a message and exiting to the calling page.--->
<cfcatch Type = "Any">
<h2>Sorry</h2>
<p>An unexpected error happened in processing your user inquiry.
Please report the following to technical support:</p>
<cfoutput>
Type: #cfcatch.Type#
Message: #cfcatch.Message#
</cfoutput>
<cfexit method = "exittag">
</cfcatch>
</cftry>
</cfif>

Reviewing the code

The following table describes the code:

Code

Description

 

<cfif NOT IsDefined("attributes.EmpName")>
<cfthrow Type="myApp.getUser.noEmpName"
message = "Last Name was not supplied to the cf_getEmps tag.">
<cfexit method = "exittag">

 

Makes sure the calling page specified an EmpName attribute. If not, throws a custom error that indicates the problem and exits the tag. The calling page handles the thrown error.

 

<cfelse>
<cftry>

 

If the tag has an EmpName attribute, does the remaining work inside an outermost try block. The cfcatch block at its end handles any otherwise-uncaught exceptions.

 

<cftry>
<!--- Try to query the main database and set a caller variable to the result --->
<cfquery Name = "getUser" DataSource="cfdocexamples">
SELECT *
FROM Employee
WHERE LastName = '#attributes.EmpName#'
</cfquery>
<cfset caller.getEmpsResult = getuser>

 

Starts a second nested try block. This block catches exceptions in the database query. If there are no exceptions, sets the calling page's getEmpsResult variable with the query results.

 

<cfcatch type= "Database">
<cfif (cfcatch.SQLState IS "S100") OR (cfcatch.SQLState IS "IM002")>
<cftry>
<cfquery Name = "getUser" DataSource="cfdocexamplesBackup">
SELECT *
FROM Employee
WHERE LastName = '#attributes.EmpName#'
</cfquery>
<cfset caller.getEmpsResult = getuser>

 

If the query threw a Database error, checks to see if the error was caused by an inability to access the database (indicated by an SQLState variable value of S100 or IM002). If the database was not found, starts a third nested try block and tries accessing the backup database. This try block catches exceptions in this second database access.If the database inquiry succeeds, sets the calling page's getEmpsResult variable with the query results.

 

<cfcatch type = "Database" />

 

If the second database query failed with a database error, gives up silently. Because the Database type cfcatch tag does not have a body, the tag exits. The calling page does not get a getEmpsResult variable. It cannot tell whether the database had no match or an unrecoverable database error occurred, but it does know that no match was found.

 

<cfcatch type = "Any">
<cfrethrow>
</cfcatch>
</cftry>

 

If the second database query failed for any other reason, throws the error up to the next try block.Ends the innermost try block

 

<cfelse>
<cfrethrow>
</cfif>
</cfcatch>

 

In the second try block, handles the case in which the first database query failed for a reason other than a failure to find the database. Rethrows the error up to the next level, the outermost try block.

 

<cfcatch type = "Any">
<cfrethrow>
</cfcatch>
</cftry>

 

In the second try block, catches any errors other exceptions and rethrows them up to the outermost try block. Ends the second try block.

 

<cfcatch Type = "Any">
<h2>Sorry</h2>
<p>An unexpected error happened in processing your user inquiry.
Please report the following to technical support:</p>
<cfoutput>
Type: #cfcatch.Type#
Message: #cfcatch.Message#
</cfoutput>
<cfexit method = "exittag">
</cfcatch>
</cftry>
</cfif>

 

In the outermost try block, handles any exceptions by displaying an error message that includes the exception type and the exception's error message. Because there was no code to try that is not also in a nested try block, this cfcatch tag handles only errors that are rethrown from the nested blocks.Exits the custom tag and returns to the calling page.Ends the catch block, try block, and initial cfif block.

Testing the code

To test the various ways errors can occur and be handled in this example, try the following:

  • In the calling page, change the attribute name to any other value; for example, My Attrib. Then change it back.
  • In the first cfquery tag, change the data source name to an invalid data source; for example, NoDatabase.
  • With an invalid first data source name, change the data source in the second cfquery tag to cfdocexamples.
  • Insert cfthrow tags throwing custom exculpations in various places in the code and observe the effects.

Get help faster and easier

New user?