Section 11.3. Role of Remoting in FlashCom Applications

11.3. Role of Remoting in FlashCom Applications

FlashCom is not the most effective environment for storing and manipulating data. Managing large and complicated data structures is better handled by a filesystem or a relational database management system (RDBMS). FlashCom is designed for sharing real-time multimedia information and data across multiple users. Using data, however, is a common need for most applications, and it is important to understand when and how to implement remoting to solve a given problem. As a general rule, if the data should be shared by multiple users, then the remoting implementation should be built in FlashCom. The FlashCom Server has the ability to cache the results from a remoting request into a shared object, which can then be easily distributed to all the listening clients . Using the FlashCom Server to gather the remote data and cache the results will dramatically reduce the load required by the remote server. On the other hand, there are important cases in which remoting should be implemented by the Flash client, such as when personal or private information is involved.

The following sample application demonstrates various examples of when and how to implement remoting. The application is a messaging system that provides users with the ability to maintain a profile and a friend list, have private conversations with another user , and have group conversations with multiple users. The application code and files are too numerous to include here, so only the remoting-specific sections are highlighted and explained. However, the entire application can be downloaded from the book's web site.

The first screen the user sees is the login screen with the option to create a profile. Since the user is not part of the system, she needs to create a profile. The creation of a user profile is a private action and should be handled strictly between the Flash client and the remote server. Once the user data is collected, the application sends it to the remote server to add the user to the system. Example 11-5 shows the client-side Flash ActionScript that handles the user registration event when adding a user's profile to the database.

Example 11-5. Adding a user's profile
 #include "NetServices.as" NetService.setDefaultGatewayUrl("http://www.yourhost.com/flashservices/gateway"); function register (userObj) {   var remote_conn = NetServices.createGatewayConnection( );   var messengerService =            remote_conn.getService("com.oreilly.pfcs.chapter11.fcsmessenger");   var response = new Object( );   // Handle the results.   response.onResult = function (result) {     // The server could return -1 if the action failed.     if (result > -1) {        _root.gotoAndStop("Login");              // Send the user to the login screen     }   };   // Catch any errors   response.onStatus = function (error) {      Alert.show(error.description, error.type); // Create a modal alert window   };   messengerService.addUser(response, userObj); } 

The register( ) method accepts an object as its argument. The userObj parameter would store all the local user properties that need to be collected by basic form elements (username, address, telephone number, etc.). The remote addUser( ) method would take the user properties and insert them into the database, successfully registering the user into the system. The onResult( ) handler could then proceed to the login screen by moving the playhead to the Login frame label.

Once the user has established her profile, she needs to log into the application. There are several different techniques to implement the login system. In Example 11-6, the user object is passed off to the FlashCom server; it builds the authentication mechanism in SSAS. This is a convenient approach if your application doesn't require any trusted security measures, because the client can simply establish a connection with the FlashCom Server and let the server manage validation of the user credentials needed to log on.

Example 11-6. Logging the user into the application
 load("netservices.asc"); //   trim( )   removes whitespace from the beginning and end of a string. function trim (str) {   if (typeof str != "string") return "";  // Make sure   str   is a string   str = str.replace(/^\s*/, "");          // Trim leading spaces   str = str.replace(/\s*$/, "");          // Trim trailing spaces   str = str.replace(/\n/g,  "");          // Remove new lines   str = str.replace(/\r/g,  "");          // Remove carriage returns   str = str.replace(/\t/g,  "");          // Remove tabs   return str; } application.onAppStart = function ( ) {   userList_so = SharedObject.get("private/userList");   application.gatewayURI = "http://www.yourhost.com/flashservices/gateway";   application.service = "com.oreilly.pfcs.chapter11.fcsmessenger";   NetServices.setDefaultGatewayUrl(application.gatewayURI); }; application.onConnect = function (client, user) {   if (typeof user == "undefined"  ! user.userName) { // Validate the user obj     application.rejectConnection(client, {msg: "Invalid user object."});     return false;   }   user.userName = trim(user.userName);   if (user.userName.length == 0) {     application.rejectConnection(client, {msg: "Invalid or empty user name."});     return false;   }   var conn = NetServices.createGatewayConnection( );   var messengerService = conn.getService(application.service);   var loginResponse = new Object( );   loginResponse.onResult = function (userProfile) {     if (userProfile == -1) {       application.rejectConnection(client,         {msg: "The username and password could not be verified"});       return false;     }     var item = userProfile.getItemAt(0);     var tempUser = userList_so.getProperty(item.userid);     if (tempUser) {       application.rejectConnection(client,         {msg: "Only one simultaneous login is allowed"});     }     user.password = "";     // Make sure the password is cleared     delete user.password;   // Delete the password     user.web = item.web;     if (!item.hide_email) {       user.email = item.email;     }     user.firstname = item.firstname;     user.lastname = item.lastname;     user.arrival  = new Date( );     user.__ID__ = item.userid;     client.user = user;     userList_so.setProperty(item.userid, user);     application.acceptConnection(client);   };   messengerService.login(loginResponse, user.userName, user.password); }; 

The login process is slightly more complicated than registering a new user. In application.onAppStart( ) , we initialize the necessary objects and properties for later. The userList_so shared object is used to ensure that only one login is allowed per user at a time. Once the user has established a connection and we have verified that she has provided the proper login credentials, the script writes an item to the shared object indicating that the user is present. When the user disconnects, the script removes the user record from the shared object so she will be able to log in again.

The first part of the application.onConnect( ) method validates the user object and verifies that a username was passed. Once we know that at least something was passed for the user object and username, we need to verify the user's credentials with the database:

 var conn = NetServices.createGatewayConnection(  ); var messengerService = conn.getService(application.service); messengerService.login(loginResponse, user.userName, user.password); 

Finally, the onResult( ) method checks the results from the login( ) action, adds the additional information to the user object, and accepts the user's connection. The remote procedure verifies the user's credentials and returns either the entire user record or -1 if the process failed. In the handler if the result is -1, we reject the connection:

 if (userProfile == -1) {   application.rejectConnection(client,     {msg: "The username and password could not be verified"});   return false; } 

The rest of the handler grabs the actual RecordSet item, checks to see if the user is already logged in, and adds the missing profile information to the user object.

Using this process to validate a user's credentials and log the user into a FlashCom application is a convenient approach because it creates a logical, linear flow of information. The user information is packaged and shipped to the FlashCom Server. The FlashCom server validates the information with the application server and accepts or denies the connection accordingly .

Because FlashCom doesn't natively support Secure Sockets Layer (SSL) connections and the credentials are sent in clear text over the network, this method doesn't offer any security, only a convenient means to establish a verified connection with a user. Other methods of authentication typically require the Flash client to validate credentials directly with an authenticating server first, then contact the FlashCom Server separately to connect to an application. Using this approach allows you to use SSL encryption for the information over the network. See Chapter 18 for more information.

Now that the user has been authenticated and logged in to the FlashCom Server, we need to request the friend list. The friend list will be similar to a buddy list used in an instant messaging client. The user can request to add and remove friends from his own list. The user can also see whether each friend is online and be notified if the friend's online status changes. To accomplish this, we use an approach similar to the login process. The Flash client requests the friend list from the FlashCom Server. The FlashCom Server grabs the actual list from the database and loops through all the friends to check whether they are currently online.

From the client scripts, we initiate the sequence by using the NetConnection.call( ) method:

 conn.call("getFriendList", null); 

The server-side script defines the getFriendList( ) method to request the list from the server and checks to see which friends are online:

 Client.prototype.getFriendList = function (  ) {   var conn = NetServices.createGatewayConnection(  );   var messengerService = conn.getService(application.service);   var response = new Object( );   var theClient = this;   response.onResult = function (friendList) {     var len = friendList.length;     for (var i = 0; i < len; i++) {       var item = friendList.getItemAt(i);       item.online = userList_so.getProperty(item.userid) == null;     }   theClient.call("receiveFriendList", null, friendList);   };   messengerService.getFriendList(response, this.user.userid); }; 

The getFriendList( ) method makes the request to the server for the list of friends for the passed userid . Once the results have been returned from the method, the handler loops through all of the results and finds the friends who are online by looking for them in the userList_so shared object. If the friend's userid is present in the shared object, then she is currently online.

Notice that the getFriendList( ) method does not simply return the friendList , but it uses the Client.call( ) method to call the receiveFriendList( ) method on the client. Remoting calls are asynchronous, so the return statement would execute long before the results were actually returned from the server.

The last two remote methods, addFriend( ) and removeFriend( ) , are implemented in a similar way. The addFriend( ) method should be sent through FlashCom, because the user who added the friend would like to see if the friend is currently online. The removeFriend( ) method doesn't need to involve the FlashCom Server at all because it simply removes the friend from the list.

Of course, the possible applications are many and varied, but this gives you the basis for understanding how and when to use remoting in a typical scenario. Remember to see the book's web site for the full example files.



Programming Flash Communication Server
Programming Flash Communication Server
ISBN: 0596005040
EAN: 2147483647
Year: 2003
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net