Let Macromedia Flex Consume Your CFCs

In previous articles I've written about the power of integrating Flash and ColdFusion to build Rich Internet Applications (RIAs). In this paradigm Flash provides the user interface while ColdFusion is responsible for handling the business logic and sending data to Flash either through Flash Remoting or Web Service calls. In this article I'd like to shift focus a bit and provide a more programmatic approach to building RIAs. By this I mean using XML to create the Flash interface. The answer lies in Macromedia's Flex.

This article will walk you through a simple application that retrieves employee records from a database so the user can update them. This is by no means a new concept, but I'd like to try a different approach. Forget about HTML, or even Flash forms for that matter, and see what Flex has to offer. If you've done any ColdFusion component development then I want to challenge you to experiment with Flex as your presentation tier. We'll dig into this concept in greater detail but let's first configure the application.

Walking Through the Example Application
You can download the source code for the example application at www.db75.com/dev/mxdj/mxdj_0605.zip. Please refer to the Readme.txt file included in the zip archive. This file has all the information necessary to get the example application up and running.

Once you've deployed the files to their proper locations and updated flex-config.xml, you should be able to access EmployeeForm.mxml through its fully qualified name, i.e., http://localhost:8080/flex/EmployeeForm.mxml. Once Flex compiles this file you should see something similar to Figure 1.

Let's open EmployeeForm.mxml so we can walk through the code and get a general understanding of what's going on. You can review the mxml code in the following code.

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml"
creationComplete="getEmployeeList();">

<mx:Script>
<![CDATA[

var selectedEmployeeID:Number;
var selectedIndex:Number;

// Gets the list of employees and is bound to the combo box
function getEmployeeList():Void
{
employeeWS.getEmployeeList.send();
}

// Get the employee when the selection is made in the datagrid
function getEmployee(event):Void
{
selectedEmployeeID = event.target.selectedItem.EMP_ID;
selectedIndex = event.target.selectedIndex;
employeeWS.getEmployee(selectedEmployeeID).send();
}

// Update the employee info
function updateEmployee():Void
{
var employeeObj:Object = new Object();
employeeObj.first_name = first_name.text;
employeeObj.last_name = last_name.text;
employeeObj.email = email.text;
employeeObj.id = selectedEmployeeID;
employeeWS.updateEmployee(employeeObj).send();
employeeDG.replaceItemAt(selectedIndex,
{FIRSTNAME:employeeObj.first_name,
LASTNAME: employeeObj.last_name});
}
]]>
</mx:Script>

<mx:WebService
serviceName="EmployeeService"
id="employeeWS"
showBusyCursor="true"
fault="mx.controls.Alert.show('Error Loading Data');" />

<mx:Panel title="Employee Form">

<mx:DataGrid dataProvider="{employeeWS.getEmployeeList.result}" id="employeeDG"
width="100%" change="getEmployee(event);">
<mx:columns>
<mx:Array>
<mx:DataGridColumn columnName="EMP_ID" width="0" />
<mx:DataGridColumn columnName="FIRSTNAME" headerText="First Name" />
<mx:DataGridColumn columnName="LASTNAME" headerText="Last Name" />
</mx:Array>
</mx:columns>
</mx:DataGrid>

<mx:Form>

<mx:FormItem label="First Name">
<mx:TextInput id="first_name" width="200"
text="{employeeWS.getEmployee.result[0].FIRSTNAME}" />
</mx:FormItem>

<mx:FormItem label="Last Name">
<mx:TextInput id="last_name" width="200"
text="{employeeWS.getEmployee.result[0].LASTNAME}" />
</mx:FormItem>

<mx:FormItem label="Email">
<mx:TextInput id="email" width="200"
text="{employeeWS.getEmployee.result[0].EMAIL}" />
</mx:FormItem>

<mx:FormItem>
<mx:Button label="Update" click="updateEmployee();"/>
</mx:FormItem>

</mx:Form>

<mx:ControlBar />
</mx:Panel>
</mx:Application>

First off, when the application's creationComplete event has fired, we call the CFC and ask for a list of all employees. You'll notice that a WebService object is created and assigned the ID employeeWS. That's what we'll call the instance of this object throughout th e application. The WebService object also has a serviceName attribute, which is bound to a named entry in our flex-config.xml file:

<service name="EmployeeService">
<wsdl>http://localhost/mxdj/Employee.cfc?wsdl</wsdl>
<endpoints>
<endpoint>http://localhost/mxdj/Employee.cfc</endpoint>
</endpoints>
</service>

This adds the Web Service to Flex's whitelist of authorized services. For development purposes you can enable any service to be accessible through the proxy or bypass the proxy altogether.

When the getEmployeeList method of the CFC is called, we handle the result by binding it to the DataGrid control. In Flex this is called Databinding. This is a powerful concept and I definitely encourage you to learn more about it. Databinding can help minimize the amount of code you have to write as well as simplify your design.

Now that the DataGrid is populated let's click on an employee record and you'll see a few items (first name, last name, and email) appear in the form below. This is done using the DataGrid's change event. If you've dealt with change events in the Flash IDE you can appreciate the fact that Flex's approach is cleaner. Each time a record is selected the change event is fired and the appropriate method is designated to handle the event; in our case it's the getEmployee(event) method. This method asks the CFC to return the employee object that matches the ID sent from Flex. You may have noticed that the employee ID is actually in the DataGrid but hidden in a column with zero width. For demonstration purposes I decided to hide the ID but in certain situations it definitely makes sense to show it.

When the employee object is returned from the CFC you'll see the appropriate information displayed in the employee form. The form fields are bound to specific elements in the employee object. Whenever a result is returned, the form is automatically updated. You might notice the difference here compared to the way this has been approached using the Flash IDE. In most instances you'd have to set the value of the each text field explicitly in the result handler (i.e., first_name.text = result[0].first_name). Once again, Databinding makes this process cleaner. Click around on different employee records and you'll see the contents of the form change. Also notice that each time an employee record is selected the mouse cursor changes to an animated clock. This is done with the simple parameter showBusyCursor="true" on the WebService object.

The last feature we'll look at is how employee updates are handled. If you have an employee selected you can modify his first name, last name, or e-mail and click update. You'll see the update take effect instantly. When the update button is pressed a new employee object is created and then passed to the CFC, which in turn updates the database. Instead of retrieving the employee list again, we immediately update the selected entry in the DataGrid. This saves a roundtrip to the server, but leaves you with some work to do for a production environment. I mention this because we don't check that the update was successful before updating the DataGrid.

Conclusion
It's worth noting that with the small amount of code in Listing 1 we added a good deal of functionality and a very rich interface. It's hard to do this in any other technology with as little work, but the ease of use and rapid development comes at a hefty price tag. I can't say that Flex will be the answer to all your RIA woes, but it's definitely worth considering if you're involved in enterprise development. Before you balk at the price tag I recommend downloading the 60-day eval and giving it a run. Macromedia has also announced an Eclipse plug-in, code named Zorn, that enables Flex application development in one of the industry leading IDEs. When it comes to your next project, or if you're looking for a change, consider Flex.

© 2008 SYS-CON Media