ColdFusion 9.0 Resources |
Handling errors in UDFsColdFusion provides several techniques to handle errors in UDFs:
The technique you use depends on the circumstances of your function and application and on your preferred programming style. However, it is best for most functions to use the second or third technique, or a combination of the two. Displaying error messagesYour function can test for errors and use the WriteOutput function to display an error message directly to the user. This method is useful for providing immediate feedback to users for simple input errors. You can use it independently or in conjunction with either of the other two error-handling methods. For example, the following variation on a “Hello world” function displays an error message if you do not enter a name in the form: <cfform method="POST" action="#CGI.script_name#"> <p>Enter your Name: <input name="name" type="text" hspace="30" maxlength="30"> <input type="Submit" name="submit" value="OK"> </cfform> <cfscript> function HelloFriend(Name) { if (Name is "") WriteOutput("You forgot your name!"); else WriteOutput("Hello " & name &"!"); return ""; } if (IsDefined("Form.submit")) HelloFriend(Form.name); </cfscript> Reviewing the codeThe following table describes the code:
Providing status informationIn some cases, such as those where the function cannot provide a corrective action, the function cannot, or should not, handle the error directly. In these cases, your function can return information to the calling page. The calling page must handle the error information and act appropriately. Consider the following mechanisms for providing status information:
Each of these methods can have variants, and each has advantages and disadvantages. The technique that you use depends on the type of function, the application in which you use it, and your coding style. The following example, which modifies the function used in A user-defined function example, uses one version of the status variable method. It provides two forms of error information:
The TotalInterest functionAfter changes to handle errors, the TotalInterest function looks like the following. Code that is changed from the example in A user-defined function example is in bold. <cfscript> function TotalInterest(principal, annualPercent, months, status) { Var years = 0; Var interestRate = 0; Var totalInterest = 0; principal = trim(principal); principal = REReplace(principal,"[\$,]","","ALL"); annualPercent = Replace(annualPercent,"%","","ALL"); if ((principal LE 0) OR (annualPercent LE 0) OR (months LE 0)) { Status.errorMsg = "All values must be greater than 0"; Return -1; } interestRate = annualPercent / 100; years = months / 12; totalInterest = principal*(((1+ interestRate)^years)-1); Return DollarFormat(totalInterest); } </cfscript> Reviewing the codeThe following table describes the code that has been changed or added to the previous version of this example. For a description of the initial code, see A user-defined function example.
Calling the functionThe code that calls the function now looks like the following. Code that is changed from the example in A user-defined function example is in bold. <cfset status = StructNew()> <cfset myInterest = TotalInterest(Form.Principal, Form.AnnualPercent,Form.Months, status)> <cfif myInterest EQ -1> <cfoutput> ERROR: #status.errorMsg#<br> </cfoutput> <cfelse> <cfoutput> Loan amount: #Form.Principal#<br> Annual percentage rate: #Form.AnnualPercent#<br> Loan duration: #Form.Months# months<br> TOTAL INTEREST: #myInterest#<br> </cfoutput> </cfif> Reviewing the codeThe following table describes the code that has been changed or added:
Using exceptionsUDFs 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 in UDFsUse try/catch blocks to handle exceptions in a UDF under the same conditions that any other ColdFusion application uses try/catch blocks. These conditions 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, have your application prevent, rather than catch, exceptions caused by invalid application data. For example, the application can 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:
Generating exceptions in UDFsIf 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> |