Adobe ColdFusion 8

Using exceptions

UDFs written in CFScript can handle exceptions using the try and catch statements. UDFs written using the cffunction tag can use the cftry, cfcatch, cfthrow, and cfrethrow tags. Using exceptions corresponds to the way many functions in other programming languages handle errors, and can be an effective way to handle errors. In particular, it separates the functional code from the error-handling code, and it can be more efficient than other methods at runtime, because it does not require testing and branching.

Exceptions in UDFs have the following two dimensions:

  • Handling exceptions generated by running the UDF code
  • Generating exceptions when the UDF identifies invalid data or other conditions that would cause errors if processing continued

Handling exceptions in UDFs

A UDF should use try/catch blocks to handle exceptions in the same conditions that any other ColdFusion application uses try/catch blocks. These are typically circumstances where the function uses an external resource, such as a Java, COM, or CORBA object, a database, or a file. When possible, your application should prevent, rather than catch, exceptions caused by invalid application data. For example, the application should prevent users from entering a zero value for a form field that is used to divide another number, rather than handling exceptions generated by dividing by zero.

When ColdFusion catches an exception, the function can use any of the following methods to handle the exception:

  • If the error is recoverable (for example, if the problem is a database time-out where a retry might resolve the issue), try to recover from the problem.
  • Display a message, as described in Displaying error messages.
  • Return an error status, as described in Providing status information.
  • If the UDF is defined using the cffunction tag, throw a custom exception, or rethrow the exception so that it will be caught by the calling ColdFusion page. For more information on throwing and rethrowing exceptions, see Handling runtime exceptions with ColdFusion tags.

Generating exceptions in UDFs

If you define your function using the cffunction tag, you can use the cfthrow and cfrethrow tags to throw errors to the page that called the function. You can use this technique whenever your UDF identifies an error, instead of displaying a message or returning an error status. For example, the following code rewrites the example from Providing status information to use the cffunction tag and CFML, and to throw and handle an exception if any of the form values are not positive numbers.

The lines that identify invalid data and throw the exception are in bold. The remaining lines are equivalent to the CFScript code in the previous example. However, the code that removes unwanted characters must precede the error checking code.

<cffunction name="TotalInterest">
    <cfargument name="principal" required="Yes">
    <cfargument name="annualPercent" required="Yes"> 
    <cfargument name="months" required="Yes">
    <cfset var years = 0>
    <cfset var interestRate = 0>
    <cfset var totalInterest = 0>

    <cfset principal = trim(principal)>
    <cfset principal = REReplace(principal,"[\$,]","","ALL")>
    <cfset annualPercent = Replace(annualPercent,"%","","ALL")>
    
    <cfif ((principal LE 0) OR (annualPercent LE 0) OR (months LE 0))>
        <cfthrow type="InvalidData" message="All values must be greater than 0.">
    </cfif>

    <cfset interestRate = annualPercent / 100>
    <cfset years = months / 12>
    <cfset totalInterest = principal*
            (((1+ interestRate)^years)-1)>
    <cfreturn DollarFormat(totalInterest)>
</cffunction>

The code that calls the function and handles the exception looks like the following. The changed lines are in bold.

<cftry>
    <cfset status = StructNew()>
    <cfset myInterest = TotalInterest(Form.Principal, Form.AnnualPercent,
        Form.Months, status)>
    <cfoutput> 
        Loan amount: #Form.Principal#<br>
        Annual percentage rate: #Form.AnnualPercent#<br>
        Loan duration: #Form.Months# months<br>
        TOTAL INTEREST: #myInterest#<br>
    </cfoutput>
<cfcatch type="InvalidData">
    <cfoutput>
        #cfcatch.message#<br>
    </cfoutput>
</cfcatch>

</cftry>