6.3 When to Use Server-Side ActionScriptServer-Side ActionScript is a powerful addition to the developer's arsenal, but it is not always the best way to create Flash Remoting services. It is merely a convenience for Flash ActionScript developers to create server-side services without having to learn another language. That said, however, there are also some pluses to creating SSAS services. For example, if you are running JRun 4 and need a simple service and don't want to get your Java programmers to create a Java source file, compile it, and deploy it, you can write your service in SSAS and simply upload it to the proper folder. In addition, you might find that a particular service requires an ActionScript object to be sent to the server, manipulated on the server, and sent back to the client. This can be done using a language such as CFML, but using SSAS makes this much simpler. Chapter 4 showed the process of transferring ActionScript objects back and forth from client to server. |
6.4 Datatype Conversions
Most datatypes in SSAS are interchangeable with client-side ActionScript datatypes. The notable exception is the client-side
Object
type, which is actually an object of type
ASObject
on the server (an extension of the Java class
java.util.HashMap
). For that reason, when you access properties of an ActionScript object that you have passed to the server, you have to use the
get( )
and
put( )
A resultset created with a CF.query( ) method on the server is automatically transformed into a RecordSet object in Flash. This is taken care of behind the scenes by the Flash Remoting adapter on the server and the RecordSet class on the client. |
6.5 Handling Errors with try/catchServer-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
}
To
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 QueryMany 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 DebuggingUsing 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 FinallyThe 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 ObjectsYou 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
|