1. BASES CONCEPTUALES
1.2 PREGUNTA DE INVESTIGACIÓN
4.2.2 Gestión Integral del Riesgo
4.2.2.5 Amenaza del Volcán Cerro Machín
<CFTRY> tag. <CFTRY> allows the developer to try a piece of code before
committing to that action. Figure 2.4 shows a logical diagram of the flow of a
<CFTRY> block. A simple example is using <CFTRY> to test a query before
using the result set.The query executes within <CFTRY> tags. However, should an error occur (for example, the database server is down, the network connection is down, or the table name is misspelled), the resulting error is caught by a
<CFCATCH> tag, and the preprogrammed action between the <CFCATCH>
tags is executed.This prevents the code outside of the <CFTRY> block from ref- erences a result set that does not exist.
The <CFCATCH> tag is very flexible in the types of exceptions it traps.Table 2.1 provides a complete list of the types of exceptions that <CFCATCH> handles.
Figure 2.3The Built-In CFAS Error Templates in the Administrator
Figure 2.4The Flow of the <CFTRY> Tag
Error occurred Is there a handler?
Log the error and print to screen
Execute the code in the handler No
Table 2.1Basic Type Attributes of <CFCATCH>
Type Description
Any Default if no type is specified. Catches any error that might be thrown, including those that might be out of your ability to manage (out-of-memory, or other OS, server-related errors). Useful in catching errors that do not fall into one of the other predefined categories. If used, you should always place it last when used with other types so that they have a chance to process.
Application Catches custom exceptions thrown by the <CFTHROW> tag with the Application type specified.
Database Catches database-related errors, such as not being able to con- nect, or a incorrect column name, a record being locked, etc. Expression Catches expression errors caused when attempting to eval-
uate CFML code. Things such passing function parameters that don’t make sense or referencing a variable that has not been instantiated yet will cause errors of the expression type. Lock Catches locking failures such as when you use a <CFLOCK>
and there is a chance of it exceeding its TimeOut value. MissingInclude Catches those times when your <CFINCLUDE> tag points to
an include file in the wrong directory or that hasn’t been cre- ated yet.
Object Catches the errors that are thrown when using a
<CFOBJECT> tag, or the function CreateObject(), or when
attempting to access any methods or properties of an object that might not exist.
Security Catches errors thrown by one of the security-related ColdFusion tags; for example, <CFAUTHENTICATE>.
Template Catches any general application page errors that might occur when processing a <CFINCLUDE>, <CFMODULE>, or
<CFERROR> tag.
Custom Catches custom exception types thrown with <CFTHROW>.
Trying code before it is executed should occur with queries, file includes, or any type of routine that accesses resources external to the CFAS. CFTRY-
CFCATCH allows the developer to provide alternate resources for queries, file
end for the ColdFusion Web site. However in the event that there was a problem with the SQL server (which does happen), an MS Access database was kept in reserve and all queries were pointed at a datasource that was kept as a variable in the Application.cfm file.The code to instantiate the datasource variable was enclosed in <CFTRY> blocks that would point to whichever datasource name was working, giving access to the database in the event of a database error with the SQL server.This allows the Web site to continue to function, and the users to continue with their activities unencumbered by technology problems behind the scenes. Figure 2.5 shows a method similar to that discussed here, except instead of changing the datasource as a variable, a different <CFQUERY> block is executed.
A common practice is to use the <CFINCLUDE> tag to dynamically build pages for the Web site; I typically accomplish this by passing the file I want included in the URL string. As mentioned previously, however, the URL string is completely open to modification, so my <CFINCLUDE> tags are all enclosed inside <CFTRY> blocks. Should someone modify the URL string to call a page that does not exist, the Web site will not throw an error message; instead, it simply includes a default page of some type. Another common practice of mine is to use <CFTRY> to protect my queries, just in case someone is able to modify a query, and I would rather not throw an error—or if someone accidentally turns the database server off.
Figure 2.5Using <CFTRY>/<CFCATCH> to Query an Alternate Datasource
<CFTRY>
<CFLOCK TYPE="READONLY" SCOPE="APPLICATION" TIMEOUT="10"> <CFSET VARIABLES.DataSource =
Duplicate(APPLICATION.DataSource)>
<CFSET VARIABLES.BackUpDataSource = Duplicate(APPLICATION.BackUpDataSource)>
</CFLOCK>
<CFQUERY DATASOURCE="#VARIABLES.DataSource#" NAME="qGetData"> SELECT FirstName, LastName
FROM Customers WHERE Active = 1 </CFQUERY>
<CFCATCH TYPE="Database">
<CFQUERY DATASOURCE="#VARIABLES.BackUpDataSource#" NAME= "qGetData">
SELECT FirstName, LastName FROM Customers
WHERE Active = 1 </CFQUERY>
</CFCATCH> </CFTRY>
Figure 2.5 had several security-minded code practices in use in the first few lines (note that some lines are wrapping). Assigning the Application-scoped variables to variable-scoped variables within <CFLOCK> tags alleviates a potential risk of corrupting the global variables, as well as possible memory leak issues, that are known to occur when working with Application variables. Notice that the
<CFSET> code that creates local variables for the values of the global variables
is not written as <CFSET VARIABLES.Varname = APPLICATION.VarName>. Use the Duplicate function to create a complete, autonomous clone of a variable instead of creating pointers to the original. Duplicating the variable is preferred to assigning the value of the original variable with pound signs, because of the processor implication of pound signs under load. Most importantly, by placing the locks around the global variables and assigning the values to local variables, the global variables are protected and secure from accidental changes.
Using the <CFTRY>/<CFCATCH> block to query the database allows the application to fall back to an alternate database, and allows the Web site to con- tinue functioning despite having database-related problems.
Going one step farther than the code in Figure 2.5 would involve alerting the developer,Webmaster, or similar administrative person to the problem. If for whatever reason the database server did not sound an alert, the code in Figure 2.5 would continue using the alternate database indefinitely. Because <CFCATCH> blocks are not limited to the amount of code contained within, the developer could easily place a marker variable of some sort (perhaps a simple variable being set to “1” or “0” depending on which datasource was used), followed by code that checks the value of the marker and acts accordingly based on the value. Moreover, the developer could have included the <CFLOG> tag within the
<CFCATCH> block to write directly to the application.log file, or included a <CFMAIL> tag to e-mail the administrator an alert to the problem.There are
countless ways to alert someone to an error without causing the user to suffer. One of the most impressive features of the try/catch methodology is the flexible nature of the tags—<CFTRY> tags can be nested n levels within each other.The same <CFTRY> tag can handle any or all of the error types listed in Table 2.1 within the same block of code, as illustrated in Figure 2.6. Developers can create their own error code hierarchy, and Web sites are made much more stable by removing a major weakness: dependency on outside resources. Obviously, a Web site that is database driven will not work as well when the database is unavailable. However, even if all the developer can do is gracefully explain to the user that the site is not working, rather than throw a big black- and-white ColdFusion error at them, then that is better than nothing.
Figure 2.6Nested <CFTRY>/<CFCATCH> Tags
<CFTRY> <CFTRY> <CFTRY> ... Some Code ... <CFCATCH TYPE="Database"> ... Some Code ... <CFRETHROW> </CFCATCH> </CFTRY> <CFCATCH TYPE="MissingInclude"> ... Some Code ... <CFRETHROW> </CFCATCH> </CFTRY> <CFCATCH TYPE="Any"> ... Some Code ... </CFCATCH> </CFTRY>
Figure 2.6 is a good example of the dynamic possibilities available to devel- opers using <CFTRY>, <CFCATCH>, and <CFRETHROW>. As listed in Table 2.1, there are specific errors that <CFCATCH> identifies: database, lock, application, object, and so forth.These types are very broad indeed. For example, the “database” type of error could be anything from a misspelled column name or invalid SELECT syntax, to the database server being down, just to name a few possibilities. By nesting try/catch code, the developer can test for specific types of database errors within a <CFCATCH>, and if not the desired type of error, bubble it up for another <CFCATCH> to try.
<CFTHROW> and <CFRETHROW>
Figure 2.6 also introduced the <CFRETHROW> tag, which as you might have guessed, has a cousin: the <CFTHROW> tag (its attributes are listed in Table 2.2). The <CFRETHROW> tag, as illustrated by the code in Figure 2.6, allows a
<CFCATCH> block to pass on an error that it has just caught.This allows one <CFCATCH Type=“Database”> block of code to look for SQL syntax errors,
and another <CFCATCH Type=“Database”> block to look for data type mis- match errors, and so forth. <CFRETHROW> allows you to develop completely dynamic nth level error trapping. As we’ve discussed, <CFTRY>/<CFCATCH> code blocks can be nested to create dynamic error-trapping routines.