Greg's Blog

helping me remember what I figure out

Flash Remoting and CFCs

| Comments

For the last day or so I have been trying to wrap my head around two of Macromedia’s product features: ColdFusion MX’s CFCs and Flash remoting. And what does this mean? Well you can write a ColdFusion Component(CFC) and get Flash to call it then in turn work on the result returned from said CFC. It took me a while to get into it, mainly because of my lack of familiarity with the Flash MX. So we are going to start off this series by looking at some of the pre-requisite, then create a CFC and return a result. Next we’ll build a simple Flash form that submits it’s input to the CFC using Flash remoting and in turn displays the result from the CFC.

Pre-requisits

Ok to get started you’ll need the following:

  • ColdFusion MX
  • Flash MX
  • Flash remoting
  • Dreamweaver MX (or whatever your favourite editor is)

All of these are available for trial downloads, if you don’t already have them.

ColdFusion Components (CFCs)

In the most simple terms a CFC is a logical group of functions or single function housed in a component. And this is how one might look:

<cfcomponent>
<cffunction name=”thisFunction” access=”public” returntype=”string” hint=”this function when invoked takes an argument and returns a string”>
<cfargument name=”nameField” required=”true” type=”string” hint=”submitted string to be worked on” />
<cfset thisResult = “Hello ” & nameField />
<cfreturn thisResult />
</cffunction>
</cfcomponent>

So we have our opening and closing cfcomponent tags and it’s name is determined by the file name you give it. So in this case we are returning a string so let’s call the component returnString, which means that it’s file name will be returnString.cfc.

Next we have the cffuntion tags, which is where you define the function name or method that is called, set it’s access type, the return type that will be sent back to the calling application and finally you can give it a hint. Giving it a hint is a very useful feature as it allows you auto-document your components and functions. To view the documentation of a CFC, simply call it in your browser, eg: http://localhost:8500/returnString.cfc (this assumes that you saved the component in the root of you web server).

The cfargument tag defines a parameter submitted to the function. Think of it as the cfparam of CFCs. You can specify whether it is required, what it’s expected type is, give it a hint and few other attributes. Again the auto-documenting aspect is nice, but more importantly it allows you tighter control over the inputs by validating the type of variable submitted.

Once these attributes have been set you can get to invoking the component. In this example we are simply concatenating the submitted value with another string and then setting this combination to a variable called thisResult.

cfreturn is used to return the variable to the calling application.

Invoking CFCs

So you now have a rough idea of what a CFC is, but what do you do with? That is how do you put it to good use? Even better how do you use it? Well you will have to call it, or more precisely invoke it. Below is the code for invoking our previously created component.

<cfinvoke component=”returnString” method=”thisFunction” returnvariable=”thisResult”>
<cfinvokeargument name=”nameField” value=”you” />
</cfinvoke>
<cfoutput>#thisResult#</cfoutput>

If you were to include this code snipped in page called callFunction.cfm and requested in your browser (http://localhost:8500/callFunction.cfm) the result should be: Hello you. So what exactly happens:

  1. the browser calls the page
  2. the cfinvoke tag calls a component returnString
  3. looks for and executes the function/method called thisFunction
  4. The function takes the parameter nameField and does it’s bit and returns a string called thisResult
  5. finally we move to the output onto the page: Hello you

Note paths to components are relative. For example if you store your components in a sub folder to your webroot, called say components, then value for the attribute component in cfinvoke would be: component=”component\returnString”.

Well that’s that pretty much. You can now have a play with this little function, why not trying to get it to accepts a dynamic value, say based on a form submission??

The Flash form

I love the idea of using Flash and despite it’s accessibility issues, I do believe that it can offer a lot of benefits in terms of cross browser experience and in terms of feature richness of the interface. However every single time I open the Flash or Flash MX editor, I get the hibby jibbies and it takes me a while to re-orientate myself and cut and paste a lot of code until I get things figured out again. So posterity my mini form tutorial, because if I write it down I might actually remember it for once.

Once you have fired up Flash and opened a new .fla file. Start off with creating 4 layers and give them these names.

  1. Labels
  2. All actions
  3. Frame actions
  4. UI components

This movie will be comprised of two actions, the first will contain the form and the second will be a response page. So in the label layer, insert a key frame in the 6th frame and then another after the 10th. In frame one of this layer edit in the properties tab enter in frame label box: form and in frame 6 do the same again, but this time give it a label: response.

Next move to layer 4 or the one you labelled: UI components and insert another key frame in frame 6. Move back to the first frame and select the text tool. First we’ll create a label for our form field. Draw a small text box and type: your name:. Make sure that in the properties tab the text type is set to: solid text. Now draw another box along side it. This time however in the properties we’ll set the text type to: input text. Also make sure that the Show Border Around Text option has been selected in the properties tab. And finally give it an instance name so that we can latter reference it: nameField

Next we’ll add a button to this frame. Go to the Components tab and ensure that Flash UI Components is selected. From the options select Push button and drag it into the scene and place it under the two text boxes. Now select it using the Arrow Tool and edit the properties. Set the instance name to pb_submit, set the label to Press me and finally enter the value onClick in the click handler field.

Next move to frame 6 and delete any of the previous components may appear here (this happened to me when I inserted the key frame after adding the form elements). Draw another text box and enter the following text into it: Form submitted.

Now move up to the layer labelled: All actions. This layer will contain all the action script code for this movie. First make sure that this layer extends to the 10th frame (you can do this by inserting a key frame in frame 11 and then subsequently removing it). For the button we created previously, we gave the click handler a value of onClick. This is a function that the movie will call when the button is pressed. So you will need to create this function, go to the Actions tab (make sure that the you are in expert mode) and enter the following ActionScript in frame 1:

function onClick(btn) {
trace(“onClick ” + btn._name);
gotoAndStop(“response”);
}

This function takes the parameter btn, which is instance name we set previously (pb_submit). The first line of the function outputs a trace to your debug window, so that you can check that the function was called. the output should be: onClick pb_submit. Then we send the user to another frame, the one we labelled frame.

Next go to the layer called: Frame actions. Create the frame split we have done for the previous layers. Go to frame 1 and type: stop(); in the Actions tab. Do the same thing again for Frame 6. When run the movie this will stop the movie from moving through all the frames, instead it will halt and only continue when the button is pressed. Pressing CTRL+Enter to run the movie. Simply enter your name and click the button and you should be taken to a page that displays: Form submitted.

In your output window you’ll see the message: onClick pb_submit . This appear thanks to the trace call we added in the onClick function.

Creating an object in Flash

Next we’ll be creating an object that will capture the form input, so that we can easily pass the value to a CFC. In order to this we’ll need to first create an object using ActionScript. So head back to your Flash editor and look at the ActionScript in frame 1 of the “Frame actions” layer. In the action window you should only have stop();. Add the following function call before the stop() function, initData();. This is the function we’ll use to initialise the object where we will capture our form input. The entire code for Frame 1 should look like this:

initData();
stop();

The initData function we will add to Frame 1 of our “All actions” layer and add the following code:

function initData()
{
// make sure we only call initData once
if ( inited )
return;
inited = true;

// modeling the form choices with data

// set initial values
userData = new Object();
userData.nameField = “”;
trace (“object created”); }

In the first instance we check whether we have previously created the object. If yes just skip ahead and don’t do anything else. If on the other hand we haven’t then let’s create the object and set the default value to empty (“”). Please note that we are creating an object called userData and adding a key nameField to it. In my mind this looks exactly like a structure in ColdFusion and hence if you had other elements you wanted to capture you could add another key and store an additionally submitted value in it. The trace at the end is just there to re-assure us that the function was called and that the object was created.

The next step is to capture the submitted information in the object as so far we have only created it. OK head to frame 1 of the “All actions” layer and you will need to add the following function call: getSubmittedData(); to the previously created onClick() function. It should end up looking something like this:

function onClick(btn) {
trace(“onClick ” + btn._name);
getSubmittedData();
gotoAndStop(“response”);
}

The function will simply add the value submitted to the object we have previously initialised. So staying in the “All actions” layer in frame 1 and insert the following code between the two existing functions:

// get the data from the ui elements on page 1 function getSubmittedData()
{
userData.nameField = name_txt.text;
trace (“The value of the submitted field is:” + userData.nameField);
}

The trace will allow us to make sure that the submitted value has been stored into our object, that we can now pass to a CFC page.

Flash remoting…

Now the plan is to take said form input, i.e. your name and pass it to a component, which will do some stuff and return a result to the flash movie. Now the stuff I mentioned just a second ago, is actually the component appending your name to a string, which will be passed back to the end page, where a brief: “hello <your name>” will be displayed. Pretty clever… :) Anyway as you can imagine, you can get it to do all sorts of stuff and then in turn have the receiving ActionScript do something altogether different based on the result sent back.

So what we need to do know is take the object we previously created and pass it to the component. To this end we need to create a connection to the server and then once connected we will pass the object and wait for a result. So go back to the “Frame actions” layer and select frame 6. After the stop() function call, add a call to submitDetails(). And then back on over to the “All actions” layer and frame 1. There we will enter the submitDetails() function.

function submitDetails()
{
// Include the Required NetService class files
#include “NetDebug.as”
#include “NetServices.as”
#include “DataGlue.as”

// connect to the Flash Remoting service provider
if (isGatewayOpen == null) {
// do this code only once
isGatewayOpen = true;
// Make the Gateway connection
NetServices.setDefaultGatewayUrl(“http://localhost:8500/flashservices/gateway”);
gatewayConnnection = NetServices.createGatewayConnection();
submitForm= gatewayConnnection.getService(“your.path.submitForm”, this);
trace(“Connected”);
// CALL Web service: return the user input
submitForm.thisFunction(userData);
trace(“sent request”);
}
}

A lot of the work is done for us by including the NetServices.as and DataGlue.as action scripts (NetDebug.as is used for debugging). Based on some code I found over at Macromedia, I learned that the best way was to first check for a connection (check for the existence of a variable isGatewayOpen), if not then initiate the connection. These two lines do that for us:

NetServices.setDefaultGatewayUrl(“http://localhost:8500/flashservices/gateway”);
gatewayConnnection = NetServices.createGatewayConnection();

Initiate the connection. The next line: submitForm = gatewayConnnection.getService(“your.path.submitForm”, this);, is the one of interest. Here we create a connection to our CFC. The one thing of note is the path to your CFC. In my example: your.path.submitForm, would be represented by the following directory structure: <your webroot>\your\path\submitForm.cfc. So it is important that you map the location of your CFC in relation to your web server properly. Otherwise nothing will happen.

At this stage you may wonder how will I know? Well i have included a few trace statements, but that really won’t tell you anything other than success or failure. Success is good, but with just a message saying failure you are not going to get very far. Thankfully within Flash MX under Window > NetConnection debuger, you will find a tool that will give you some relevant feedback when it comes to figuring out why your connection failed or indeed how it succeeded.

Now you are ready to run the movie, submit a value via the form to your component. Both the output debugger window should display the following:

object created and populated
onClick pb_submit
your name
The value of the submitted field is: Greg
Connected
sent request

In your net debugger you should be able to find a line Result - Hello <your submitted value> [second from bottom if all executed well]. Problems that may occur are down to the flash file and the CFC not being in the same directory or the reference to the CFC being wrong in your connection call. Another reason I encountered was that the submitted value wasn’t found. Initially I thought that the value passed would be the object, i.e. userData. In actual fact though it is the field submitted that needs to be referenced in the function, hence use nameField.

This is all well and good, but the proof lies in the pudding so let’s output that result back into our closing page, where currently you only see form submitted once you launch the movie. To do this we’ll start by having to add the following code to the “All actions” layer in frame 1.

// :::: DEFAULT RESPONDERS ::::

function thisFunction_Result(thisResult) {
trace(“server responded: The result is ” + thisResult);

trace(“setting the field”);
// This function will be invoked by the server when it has finished processing
myResult.text = “The CFC replied with: ” + thisResult;
}

The above code is a default Flash remoting reponse function. You invoke it by creating a function of the format invokedFunction_Result(return variable). All I do here is set a trace to output a debug message with the resulting value and then display the result in text field. What text field? The one we will create now on frame 6 of the “UI components” layer. Select the frame and select the text tool. Draw a box and in the properties tab select Dynamic Text from the drop down menu. In the instance name field, specify myResult. There you go all done, launch the movie, submit a value and see the result on the next frame.

For convenience and possibly troubleshooting, here is a zipped archive with the completed code and flash movie. Most of the information I gleaned from numerous articles in the Flash Remoting Devlopment Center which are damn useful if you have the time to work through them.