6.5 Handling Errors with try/catch

Server-Side ActionScript contains the try/catch/finally construct of ECMAScript. If you have used JavaScript, Java, or ColdFusion before, you may be familiar with this construct, which is missing from client-side ActionScript. You use it like this:

try {
  // Code here
} catch(exception) {
  // Error handling code here
} finally {
  // Do this in either case
}

A try/catch/finally construct says, "Try to execute the code inside the try block. If there is an error (exception), execute the code in the catch block. In either case, execute the code in the finally block."

To demonstrate, look at this SSAS code:

function getProducts ( ) {
  var sql = "SELECT ProductID, ProductName FROM Products";
  try {
    var myResults = CF.query("northwind", sql);
  } catch (e) {
    sendEmailAdmin(e);
    throw("There was an error connecting to the database");
  }
  return myResults;
}

In this case, the query to the database is wrapped in a try/catch block. This allows us to capture any error when connecting to the database and perform some additional steps. In this case, we've called an imaginary function called sendEmailAdmin( ) that resides in the same file, allowing us to send a notification email to the administrator that an error occurred. After sending the email, we create our own error using the throw keyword. When we throw an error, we are in control of what is sent to the Flash movie. We can use this to send a code or an error message of our own rather than a system error message. When you use throw, the onStatus event is sent to the Flash movie, so the myResults resultset would not be returned in this case.

6.5.1 Retrying the Query

Many times, there are things that you can do on the server to circumvent an error or gracefully handle an error. We could have tried to execute another query to a backup data source on another server within the catch block:

function getProducts ( ) {
  var sql = "SELECT ProductID, ProductName FROM Products";
  var myResults;
  try {
    myResults = CF.query("northwind", sql);
  } catch (e) {
    try {
      myResults = CF.query("backupServer", sql);
     } catch (e) {
       sendEmailAdmin(e);
       throw("There was an error connecting to the database");
     }
  }
  return myResults;
}

We could have also read the information from a static text file on the server, retrieved it from an XML document, or inserted some static code to return to the Flash movie in order to allow the person viewing the Flash movie to keep on working. The point is that we are in control of what happens to the error on the server side. Errors that can be handled gracefully on the server are errors that don't have to be handled by Flash.

6.5.2 Debugging

Using try/catch can also benefit you while you are debugging an application. Look at the following code:

function updateProducts (Product) {
  var sql = "UPDATE Products SET ProductDesc=" + Product.get("ProductDesc");
  sql += ", ProductName=" + Product.get("ProductName");
  sql += " WHERE ProductID = " + Product.get("ProductID");
  try {
    CF.query("northwind", sql);
  } catch (e) {
    throw "Error in updateProducts: sql=" + sql; // debugging info
  }
  return true;
}

If you run this example, it causes an error because there are no quotes around the ProductDesc and ProductName fields. Suppose you send a Product record to this function that looks like this:

myService.updateProduct({
   ProductID:33,
   ProductDesc:"Test product description",
   ProductName:MyProduct"});

The error thrown back to the Flash movie would look like this: "Error in updateProducts: sql=UPDATE Products SET ProductDesc=Test product description, ProductName=MyProduct WHERE ProductID=33".

You can now pinpoint the problem. You can fix your code by adding single quotes around the values for the ProductDesc and ProductName fields:

function updateProducts (Product) {
  var sql = "UPDATE Products SET ProductDesc='"+Product.get("ProductDesc") + "'";
  sql += ", ProductName='" + Product.get("ProductName") + "'";
  ...
}

6.5.3 Finally

The finally construct allows you to execute a code block regardless of whether there was an error. This can be useful for freeing resources that are used in the script, as in this example:

function writeLinesToFile (myArray) {
  var success = true;
  try {
    writeMyFile(myArray);
  } catch (e) {
    success = false;
  } finally {
    closeMyFile( );
  }
  return success;
}

The finally construct is optional and therefore not always used in try/catch constructs.

6.5.4 Custom Exception Objects

You can also create your own exception objects, which can act as error types for your remote services. For example, a validation service might contain exception objects that you set up for each type of validation. An object that accepts a valid email address is shown in Example 6-4.

Example 6-4. The EmailAddress.asr service with custom exceptions
// The exception object
function EmailAddressException (address) {
  this.value = address;
  this.message = " is not a valid email address";
  this.toString = function ( ) {
    return this.value + this.message;
  };
}

// The email address object
function EmailAddress (email, name) {
  var theExpression = /^[A-Za-z0-9\_\-]+\@[A-Za-z0-9\_\-]+.*\.\w{2,6}$/;
  if (theExpression.test(email)) {
    this.address = email;
    this.name = name;
  } else {
    throw new EmailAddressException(email);
  }
}

function validateEmail (email, name) {
  var myEmailObject;
  try {
    myEmailObject = new EmailAddress(email, name);
  } catch (e) {
    if (e instanceof EmailAddressException) {
      return e.toString( );
    } else {
      return "Undefined error";
    }
  }
  return myEmailObject;
}

This example checks for an exception of type EmailAddressException (our own error type). If the error is of that type, we return the error message that is part of the EmailAddressException object. If another type of error occurs, we send back an "Undefined error" message. Note that in this example all errors are trapped. If it were a complex service with many different validation types, you might have different exception types.

The Flash Remoting adapter effectively implements a try/catch construct: successful calls to a remote method return the onResult event, and errors return the onStatus event. Using try/catch explicitly within SSAS just gives you a little finer control over how your errors are handled.

The try/catch construct is important when executing Java code within Server-Side ActionScript, as discussed in the next section.



    Part III: Advanced Flash Remoting
     
    ASPTreeView.com
     
    Evaluation has ХНЕЙјexpired.
    Info...