Setting Up Flash Remoting on Mac OSX Using ColdFusion MX7 and MySQL

In this tutorial I will run through the process I followed to get up and running with Flash Remoting utilising ColdFusion MX7 and a MySQL database on Mac OSX. I will not go into great detail on the installation instructions of ColdFusion MX7 and MySQL on Mac OS X due to there being some fantastic tutorials already accessible, links of which I have provided. In fact, I have provided a few links here as the process of getting JRun, ColdFusion MX7 and MySQL up and running was for me slightly tricky (then being a mac newbe) and therefore I thought it best to have too much information rather than not enough. Even though this is focused on the Mac OSX platform some of the principles may be utilised on the Windows platform, especially creating a database, ColdFusion component, ActionScript 2 class for remoting

The aim of this tutorial guide is to communicate with a MySQL database in Flash using Actionscript 2 and ColdFusion MX7. For this example we will be grabbing and displaying user login data i.e. username and password, however, this is not a tutorial on how to create a login application but could be extended to impliment one if desired. We will also be maintaining OOP practices my keeping all our AS2 coding logic in a class and dynamically accessing this class Object. You may want to read my previous tutorial Communication between classes in AS2 using EventDispatcher to see further information regarding classes and attaching them to the stage in the .fla. You will also learn how to create a simple ColdFusion component to query your datasource and access the MySQL database. There are many techniques on achieving this, I am mearly going to explain how I achieved the desired results. Once your up and running with ColdFusion and Flash Remoting in your Mac it is well worth the work, you will be able to step into the league of Rich Internet Applications and with Flex Builder 2 being so appealing this is something you do not want to push to the side, so lets get on…

First install the relevant software:

ColdFusion MX 7 on Mac OS X installation links:

http://corfield.org/index.cfm?fuseaction=articles.cfmxosx http://www.communitymx.com/content/article.cfm?page=1&cid=C5ACC

Ensure you have the Flash Remoting Components and the latest updater:

http://www.adobe.com/products/flashremoting/downloads/components/#flr_fl8 http://www.adobe.com/go/flr_updater/

MySQL on Mac OS X installation links:

http://www.entropy.ch/software/MacOSx/mysql/ http://dev.mysql.com/doc/refman/5.0/en/mac-os-x-installation.html http://www.adobe.com/devnet/dreamweaver/articles/php_macintosh.html http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_19170 http://developer.apple.com/internet/opensource/osdb.html

Create a new MySQL Database:

I tend to use CocoaMySQL to manage mySQL databases http://cocoamysql.sourceforge.net/. Its free and does what I need pretty much just fine. Just to note I also use MySQL administrator available from the official dev.mysql website and there are a whole range of other products out there. For the purpose of this tutorial I will be using the CocoaMySQL software. If you do not want to perform this process I have included my MySql database with all of the relevant information already included within the mysql folder located in the source files.

Load up CocoaMySQL following installation and enter your Host (localhost), User (root) and Password your created.

Connect to mysql image

Navigate to the Databases area and click the Add database button and name your new database (db) flashmac.

Add a database image

Under the Tables section click the Add table button and name it users.

Within the Structure option your presented with the option to add fields to your db, press Alt+Option+A together to create a new field, this will leave a flashing cursor in an empty text field, type id as your field name, give it a Type of int, length leave as default which is 11, unsigned/zerofill/binary leave blank, Null scroll to NO, then skip to Extra and scroll to the option of auto_increment which will display a alert asking which index you want to add for this field, choose PRIMARY KEY, the Key and Default options should be PRI and NULL respectively. Next create two more fields in the users table named username and password, both of Type varchar with Length of 35, Null should be NO and Extra is None. You can now click on the Content option near the top of the window and double click in each field to enter a test value for each field, I entered 1 for id, newtriks for username and flashmac for password. Your now finished with CocoaMySQL.

Field info image

Create a new ‘data source’ in ColdFusion MX7:

If you have followed the tutorials linked above you can navigate to the below URL to access your ColdFusion Administrator.

http://localhost:8101/cfusion/CFIDE/administrator/

Load up the ColdFusion Administrator, navigate using the menu system on the left to Data & Services > Data Sources.

Under Add New Data Source is a text field labeled Data Source Name, enter flashmac and scroll through the list box for the driver type Other and click the Add button.

Add a datasource image

You will then be presented with a screen titled Data & Services > Datasources > Other where you must enter a JDBC URL which will be the url to access the db we created earlier. Enter jdbc:mysql://localhost:3306/flashmac - localhost is the name of the database server, 3306 is the port number for the database connection and flashmac is the database name.

For the Driver Class com.mysql.jdbc.Driver, leave the Driver Name field blank, enter root for User Name and then your Password to access your MySQL database, click Submit.

Datasource details image

You should then see your new datasource in Connected Data Sources and above the page title Data & Services > Datasources should be a small green bulleted message stating ‘datasource updated successfully’. If not, go over the instructions again and ensure that in your database name is correct.

So we now have our database up and running with a new table and relevant field information and ColdFusion has the data source running and pointing to our database. So its on to Flash and Dreamweaver to start constructing our server and client side logic.

Setup a Site Definition in Dreamweaver 8:

i find it useful to create a site definition in Dreamweaver when creating an application that utilises the coldfusion server. You obviously need not bother and just save the files in a folder in the CF7 root and then type the localhost url to access the app, however, most of these applications are building blocks for a larger scale application and so building a site definition at this stage may save time and effort for you in the long run. Also to upload the tested application to a remote server becomes less laborious.

Load up Dreamweaver 8 (or whichever version you own) and press F8 or choose Window>Files, then navigate to the left hand side drop down list and click on Manage Sites. This will present you with a window with a New button on the top left hand side, click this and then enter the details as below:

1) Site name: flashmac_remoting

HTTP address: **http://localhost:8101/cfusion/flashmac_remoting/**

next> 2) Click Yes for server technology and choose ColdFusion from the list next> 3) Click Edit and test locally

**Macintosh HD:Applications:JRun4:servers:cf7:cfusion:flashmac_remoting:**

next> 4) http://localhost:8101/cfusion/flashmac_remoting/

 Click Test URL and expect: The URL Prefix test was successful

next> 5) Click no to remote server next> 6) Review the settings and click Done…

Building the ColdFusion component:

You should now find that the flashmac_remoting folder you created in your root is displayed in the files panel, obviously empty so let’s get creating our first ColdFusion component to get some content in there.

Choose File>New, choose Dynamic page from the Category list and select ColdFusion component.

Save this file as remoteMac_data.cfc into your flashmac_remoting folder. Next type:

1
<cfcomponent hint="Query flashmac example database">

This is a practice I maintained from learning CF7 (using the CFWACK bible by Ben Forta and Raymond Camden - so so highly recommended). Like Ronseal it does what it says on the tin, serves as a hint to all who read this script as to the components serving purpose, our cfc is querying the database for user details. Next we need to set our datasource that we created earlier remember we named it flashmac, we assign this to a simple variable we can refer to throughout our script which is ds, urm which stands for datasource :)

1
<cffunction name="db_access" access="remote" returntype="query" hint="Get all user details">

Ok so here is our main coldfusion method (or function) which we name db_access. , we set the access attribute as remote which means the method can be accessed as a Web Service. ColdFusion uses the returntype attribute query for data queries and performs a SQL operation retrieving defined results. We then define a simple hint for what this method actually does.

1
2
3
4
5
<cfquery datasource="#ds#" name="user_q">
SELECT *
FROM users
</cfquery>
<cfreturn user_q>

ColdFusion uses the tag for data queries and performs a SQL operation retrieving defined results. The SQL operation is fairly self explanatory, we want to select all ( * being the wildcard for all) values from the users table in the defined datasource. We set the datasource using the # signs which are referred to as number sign or gate and found on your mac by pressing alt & 3. As many of you may know, these identify a coldfusion instruction and surround all expressions, here it is an instruction to replace the string ds with our set variable flashmac. The name attribute is user_q and is identification for any body calling these query results, data is then provided by returning the method results via the tag.

Ok, lets test this all out, it is pointless going straight into flash and building an app unless we know the back end code is working correctly first, best practice guidelines say so you know, so as with any requests from my wife, I do as I am told and build a simple interface to test the component. I am not going into the test interface, its in the source so load up backend_test.cfm and save to your flashmac_remoting folder then File>Preview in Browser. You should see similar to the image below.

Job done, before we move on to the final hurdle its worth a mention that there are other techniques to create a cfc for grabbing data which may be worth a peek (1) using recordsets in Dreamweaver (2) also in Dreamweaver use the wizard based CFC creation. Nuff said, bring on the big guns….Flash step up!

Connecting with Flash 8 using Actionscript 2:

In flash create a new as file and save it to your flashmac_remoting folder, name it RemoteAccess.as, then save a new FLA file to the same location and name it remote_mac.fla. Lets start with the FLA which we will use to attach to the stage and instantiate our RemoteAccess object. All we are doing in this file is creating some of the visual components and kick starting our logic by creating a new instance, so name the one and only layer in the timeline actions, lock it and click the keyframe, bring up your actions panel (alt & F9) and type in the following:

1
2
3
4
5
6
// import the class
import RemoteAccess;
// Define object
var remote_mc:RemoteAccess;
// Attach instance of RemoteAccess object to stage and give an instance name
this.remote_mc = this.attachMovie("RemoteAccess", "remote_mc", this.getNextHighestDepth());

The comments kinda spell it out briefly but essentially we are importing the class we require so that we can utilise it, created a new instance of the object and name it remote_mc, at the same time we are attaching i to the stage using the attach movie clip method.

Here is a brief explanation of why I chose this method of working with the class we will create later. The RemoteAccess class extends the MovieClip class, we utilise some of the methods of MovieClip and also add some extra functionality to it, i.e. remoting, therefore we extend the MovieClip class. One method of attaching a class object to the stage is to assign the class to a movie clip in the library and attach that movie clip to the stage. You may also simply drag the MovieClip onto the Stage and assign an instance name in the Property inspector, this is simply my preference to perform the task using code.

So now we need to create the MovieClip, open the Library panel Window>Library and click the bottom left icon for New Symbol. Select Movie Clip and name it RemoteAccess which is the same name as the class we are attaching, click the Export for ActionScript and Export in first frame options in the Linkage section and type in RemoteAccess for the AS 2.0 class. If your class is in the same folder as the FLA as in our case then this is all fine, however, if you have saved the Class in you own package folder e.g. com.simonbailey.classes then you must but the full path to your class in the AS 2.0 class text field. Click OK.

MC symbol image

Next lets create a simple visual interface which we will attach to the stage in our class using actionscript. So again create a new Symbol, choose Movie Clip and name it display_mc, click the Export for ActionScript and Export in first frame options in the Linkage sections again and it should automatically populate the identifier field with the movie clips name. When you click ok the movie clip will be opened on the stage and we need to put 3 dynamic text fields onto the stage, font, text size, position and colour are not important, what is important is the instance names we give the text fields so we can reference them in our class. So, give one an instance name of username_txt, next password_txt and finally status_txt.

New to Flash Remoting for Flash MX 2004 is the Remoting Connector component. This can be accessed in the Components panel via Window>Components and it is under Data Components. To use this component, drag the Remoting Component onto the stage and then delete it (you will have to unlock the actions layer for it to be allowed onto the stage) this puts it into the library. The method of connecting to a remoting service using this component is to set all the parameters in the Component inspector.

We will not require this component as we are connecting to our service using ActionScript so we simply need to go to the menu Window >Common Libraries>Remoting (or Window>Other Panels>Common Libraries>Remoting) and drag the RemotingClasses library onto the stage, to take advantage of the NetDebug class you will also need to attach the RemotingDebugClasses to the Stage. Thats all we need to do in our FLA for now so lets move onto the empty class RemoteAccess that we created earlier.

Flash library image

I am not going to go into the technique of class construction here as there are loads of resources you can call upon to gain the relevant knowledge, I have commented most lines of code in the source and you can always go off and have a tinker yourselves once you have completed this tutorial. The beauty of classes or OOP is that you can reuse the classes again and again and as long as you build the classes loosely coupled i.e. not tied into a specific application so that it can be utilised across many. This class is not as loosely coupled as I would prefer due to me keeping the logic as clear and simple as possible, I have included at the bottom of this post a second example with a class completely independent enabling reuse in many different applications. For further information regarding Flash Remoting please view http://download.macromedia.com/pub/documentation/en/ flash_remoting/mx2004/usingflashremoting_en.pdf First we need to import all the necessary classes so that we can take advantage of their methods:

1
2
3
4
5
6
7
8
9
import mx.events.EventDispatcher;
import mx.remoting.debug.NetDebug;
import mx.remoting.PendingCall;
import mx.remoting.Service;
import mx.rpc.RelayResponder;
import mx.rpc.ResultEvent;
import mx.rpc.FaultEvent;
import mx.remoting.RecordSet;
import mx.utils.Delegate;

Next we need to define our class:

1
class RemoteAccess extends MovieClip

Declare our variables:

1
2
3
4
5
6
7
8
9
private static var GATEWAYURL:String = "http://localhost:8101/cfusion/flashservices/gateway";
private static var CFCURL:String = "flashmac_remoting.remoteMac_data";
private var inst:Service;
private var initialized:Boolean;
private var _remote_mc:MovieClip;
private var display_mc:MovieClip;
public var dispatchEvent:Function;
public var addEventListener:Function;
public var removeEventListener:Function;

Build the constructor method which calls super() to inherit all the available functionality of the MovieClip class, we then declare a Boolean value of false for initialized which basically states we have not set up our interface yet via the init method. We utilise the EventDispatcher and need to initalise it here and reference it to our class as the broadcasting object (please view my tutorial on class communication for more information on the EventDispatcher class http://www.newtriks.com/?p=33. Finally call our init method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function RemoteAccess() 
  {
      
      // Call methods from MovieClip
      super();
      
      // Not yet set up visual interface
      initialized = false;
      
      // Initialize the eventDispatcher
      EventDispatcher.initialize (this);
      
      // Call the init() method
      this.init();
      
  }

The init method checks using a simple if statement if the boolean value of initialized is false it creates a new MovieClip object and gives it an instance name of remote_mc, this is the foundation building block for all visual architecture. We then attach to remote_mc our display_mc that we create in our FLA, give it an instance name of display_mc and position it to the centre of the stage (my movie clip is 182px by 182px and the registration point is in the top left hand corner hence my deducting 91px from the x & y coordinates). We then place the text “Calling Service” into our status_txt text field, flip the boolean value of initialized to true and move onto our loadUserDetails method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private function init():Void 
  {
      
      if( !initialized ) 
      {
          // Build visual interface
          
          // Create an empty MovieClip object with the instance name '_remote_mc'
          this._remote_mc = this.createEmptyMovieClip("_remote_mc", this.getNextHighestDepth());
  
          // Attach an instance of 'display_mc'
          display_mc = this._remote_mc.attachMovie
          ("display_mc", "display_mc", this._remote_mc.getNextHighestDepth());
  
          // Position the display MovieClip in centre of stage
          display_mc._x = (Stage.width/2)-91;
          display_mc._y = (Stage.height/2)-91;

          // Display content is loading in status text field
          display_mc.status_txt.text = "Calling Service... ";
          
          // All set up, set initialized to true
          initialized = true;
          
          // 
          loadUserDetails();
      }
  }

The getInstance method is initiated by the loadUserDetails method. Here is the main nuts and bolts for creating a gateway connection and reference to the remote service. This method returns an instance of a new Service object to the method that called it i.e. loadUserDetails. I have commented out the NetDebug class initialisation as we only really need to use it on first development of this application and problem solving, this is also beyond the scope of discussion within this tutorial so check this out for more info yo! http://livedocs.adobe.com/flashremoting/mx2004/ actionscript_api_reference/mx/remoting/debug/NetDebug.html.

Moving on, I have then written a simple if statement to check if there is already an instance named inst, no? well lets create one, we call our instance of the service object inst and the new Service expects 5 values, the first is the gatewayUrl parameter which we define in our declaration of variables at the top of the script, nice and easy access if we were to change the url at any stage this saves having to hunt through loadsa script. The url depends on the location of the application server running Flash Remoting, we are connecting to a ColdFusion service so it will be localhost and the relevant port, as per this tutorial ours is 8101 (most windows users will be the traditional 8500) then /cfusion/flashservices/gateway. We then declare null for the Log object, this is where the debugging messages are sent. We then want to actually connect to a service and we provide the service name here, once again it is declared at the top of the class script for easy access. The ColdFusion component we created named remoteMac_data contains all the information we want to interact with and translates to service functions in ActionScript, the containing folder is the service name, so if your component is stored in the webroot we just declare the service function name i.e. remoteMac_data. If it is contained within a subfolder like we have created, then we declare the subdirectory first using dot notation so we would declare flashmac_remoting.remoteMac_data. The final 2 null values represent connection and responder parameters for more information on these parameters please view the Service constructor class http://livedocs.adobe.com/flashremoting/mx2004/ actionscript_api_reference/mx/remoting/Service.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private function getInstance():Service
      {           
      
          // Initialize the NetDebug, comment out when not testing!
          //NetDebug.initialize();            
          
          // Return reference to singleton instance
          if ( inst == null )
          {
              // create a single instance of the singleton
              inst = new Service ( GATEWAYURL, null, CFCURL, null, null);
          }
          
          return inst;
      }

The loadUserDetails method creates a variable named service calling the getInstance method which then returns the Service instance therefore our variable service becomes a reference within this method for our newly instantiated service??? Oooh thats a little of a back and forth scenario, but read over it again and the simple aim is to comprehend that we can now reference the instance of our service within this method as service. So lets do that within the PendingCall, an object always returned from a call to a service function. The call is to the function created in the cfc named db_access. We name our new PendingCall object pc and expect it to handle our result from the service function call by setting the responder property of the PendingCall class to an object that impliments the mx.rpc.Responder interface. This sounds more complicated than it actually is, we have made a service function call (to the db_access function within the cfc) and the Responder says what to do with the result, if success then call the respond_Result method defined below, if it fails then call the respond_Fault method:

1
2
3
4
5
6
7
8
9
10
public function loadUserDetails():Void 
  {
      
      // Create new instance of the remoting service
      var service = getInstance();
      
      var pc:PendingCall = service.db_access();
      pc.responder = new RelayResponder( this, "respond_Result", "respond_Fault" );
      
  }

The respond_Result method is initiated with the service call and we receive our expected data from the db_access query. The query data is returned to Flash as a record set and ActionScript manipulates the information as a RecordSet Object. A record set is a two dimensional data table and is perfect for translating data returned from our database, columns are created for returned fields of a record i.e. id, username and password; and rows containing the records i.e. 1, newtriks, flashmac.
The respond_Result method is expecting an event object which is essentially our data, we then create a new record set and populate it with the event object data, job done.

All we have to finally do now is to filter through the data and assign it to our text fields, username_txt & password_txt. We defined rs as our record set object and if you look up http://livedocs.adobe.com/flashremoting/mx2004/ actionscript_api_reference/mx/remoting/RecordSet.html you will find our more information on the RecordSet method getColumnNames which we call plus all the other class methods at you disposal. getColumnNames returns an Array of all the columns so we can expect knowing our database structure that column 0 will be id, 1 will be username and finally 2 will be the password, note: please remember that flash starts from 0 and not 1 hence id is in column 0. Lets then loop through all the records in the record set using a static property of the RecordSet class items that returns an Array of all the records, perfect! The loop lasts as long as there are records by calculating the length of the array rs.items.length, and for each record we assign a variable record by using the getItemAt method of the RecordSet class. We only have one record and we simply want to assign elements of that record to a text field which is fine, however, for displaying more values i.e. more than one user, use one of the following components e.g. DataGrid, ListBox and TextArea, etc. Finally we assign the record to the relevant text field using record[cnames[1]] which is record - at index i (we only have one so it will = 1), cnames - column name, 1. Get the first record from column 1 which is our username column and will return - newtriks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private function respond_Result( re:ResultEvent ):Void 
  {
      
      // Clear status text field
      display_mc.status_txt.text = "";

      // We now have a recordset of data from the database.
      var rs:RecordSet = RecordSet(re.result);
      var cnames = rs.getColumnNames();
      
      // Dispatch event if anyone wants the data
      dispatchEvent ({ type:"onResult", target:this, rs_data:rs });
      
      for( var i=0; i<rs.items.length; i++) 
      {
          // Loop thru records and assign each one to a record variable
          var record = rs.getItemAt(i); 
          
          /* We only have one value and so we can display the single
           * values in text fields.  To display more values i.e. more
           * than one user, use one of the following components e.g.
           * DataGrid, ListBox, TextArea ...
           */
          
          // Column 0 is id
          // Column 1 is username
          // Column 2 is password
          display_mc.username_txt.text = record[cnames[1]];
          display_mc.password_txt.text = record[cnames[2]];
          
      }
  }

The respond_Fault method will be parsed a FaultEvent object which we can filter through and call what exactly the problem was in grabbing the data. We assign the faultstring property to our status_txt text field displayed in our display_mc. For more info on the FaultEvent class please see http://livedocs.adobe.com/flashremoting/mx2004/ actionscript_api_reference/mx/rpc/FaultEvent.html:

1
2
3
4
5
6
7
8
private function respond_Fault( fault:FaultEvent ):Void 
  {
      
      display_mc.status_txt.text = '';
      display_mc.status_txt.text =  "Problem with call: " ;
      display_mc.status_txt.text = "Error returned: " + fault.fault.faultstring;
      
  }

Final SWF image

I have not gone into great detail all areas as this became a much larger task than I originally anticipated. I hope it works for you, Flash Rmeoting, ColdFusion MX7 and MySQL did take a lot of work to get up and running and I know my fair share of people who have struggled, hopefully this should serve as a resource to get you up and running and start you on your way in developing RIA’s.

remoting source files

As promised above in this post I have also provided a loosely coupled class for remoting that I have written. This has no ties to this application or any other so can be utilised for any flash application you desire. I have included the source below along with a class which calls my custom remoting class and also an FLA as an example of usage for our login.

Newtriks remoting source 2

Other useful links:

http://livedocs.adobe.com/flashremoting/mx2004/actionscript_api_reference/mx/remoting/ http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_19170 http://www.talkingtree.com/blog/index.cfm?mode=entry&entry= 25AA9A56-45A6-2844-7A60CF5B3666D010

Comments