Macromedia Flex Macromedia Flex
Coldfusion & Flex: Integration
  Home

Sep 16, 2005 - Coldfusion & Flex: Integration
How to integrate CFCs, Macromedia Flex, RemotectObjects, Etc...

INSTALLATION AND DEPLOYMENT OF FLEX ON A J2EE SERVER            

By Darius Fattahipour - Sr. IT Engineer
Install Flex onto a J2EE server (I use Websphere).  The steps are quite clear and can be found at: http://www.macromedia.com/support/documentation/en/flex/1/install.html.  You need to be a little familiar with the J2EE platform and installing WAR files.

The trick here is that in order for CF and Flex to talk, you need to make sure you create a file in your CF root called 'crossdomain.xml'.  It should have the following statements:

<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>

CALLING A CFC FROM FLEX

The consensus in the Flex community seems to be that using the AMF protocol leads to the best performance and as such, calling RemoteObjects is the data model of choice when integrating with CF.

1) Using the RemoteObject tag, call a CFC

<mx:RemoteObject id="ro" endpoint="http://gx270dev.net/flashservices/gateway" source="Model.mUpdate.fx_UpdateAuthorization" fault="mx.controls.Alert.show(event.fault.faultstring)" showBusyCursor="true">

  <mx:method name="invUpdateAuthorization" result="doResult(event.result)"/>

</mx:RemoteObject>

<mx:RemoteObject>
id: Identifier of RemoteObject call.  Will be called by ActionScript function below.
endpoint: The Flash gateway is part of CFMX 7 (not sure about CFMX 6.1).  Simply substitute your hostname and the path /flashservices/gateway.
source: This should be the relative path (separated by dots instead of slashes) to the CFC you're calling.
fault: Not entirely sure what this does, but I think it sends event errors to the debugger which then popup as alerts.
showBusyCursor: Optional.  Basically just shows the little clock while your CFC is being called.

<mx:method>
name: Name of function in CFC.
result: ActionScript function that will handle the resultset from CF.  The result keyword represents the type of event returned from Flex.

2) Write ActionScript function to call CFC

I decided that the most efficient means to communicate with CFCs was to send single Arrays of parameters, instead of individual values, but it's your choice.  In this example I've hardcoded them.

ActionScript:
/*The doClick() function will be called later in your MXML file*/

private function doClick():Void{

    var QueryArray:Array = new Array();

/*Notice that the queries start at element '0', not 1 as in CF.  */

    QueryArray[0] = "jricha";
    QueryArray[1] = 99;
    QueryArray[2] = "No";
    QueryArray[3] = "No";

*/This is a call to the RemoteObject, its method, and passes the above query.
    ro.invUpdateAuthorization(QueryArray);
}

SETTING UP YOUR CFC

1) Calling the CFC

You'll want your CFC to accept the Array and return Array of Structures.  In this example, I call a query and the package the results accordingly to send back to Flex.

<cfcomponent>

    <cffunction name="invUpdateAuthorization" access="remote" returnType="Array">

    <!--- Create an argument to accept your Flex array --->

      <cfargument name="Input" required="true" type="Array">

    <!--- Create array to return to Flex --->

      <cfset var arrResult = ArrayNew(1)/>

    <!--- I parsed the array into single local vars to use in my query --->
       
<cfset UserId = input[1] >
  <cfset CCode = input[2] >
  <cfset CFlag = input[3] >
  <cfset COAvailableFlag = input[4] >

    <!--- Call query--->

     <cfinclude template="qry_UpdateAuthorization.cfm">

    <!--- Loop over query result and insert each record into an individual structure and append to an array--->
 
      <cfoutput query="qGetUpdateAuthorization">
           <cfset stItem = StructNew()/>
           <cfset stItem["Function"] = #qGetUpdateAuthorization.Function#>
           <cfset stItem["Description"] = #qGetUpdateAuthorization.Description#>
           <cfset arrayAppend(arrResult,stItem)/>
      </cfoutput>

    <!--- Return Array to Flex--->

       <cfreturn arrResult/>     

</cffunction>

</cfcomponent>

CREATE AN ACTIONSCRIPT FUNCTION TO ACCEPT CFC RESULTS

1) There will be a function that accepts the results from the CFC.  It was earlier defined in our Remote Object method:

<mx:method name="invUpdateAuthorization" result="doResult(event.result)"/>

This was a particularly confusing aspect to this entire process.  Flex needs values as objects in order to bind them to a datagrid or other components.  As such, we must take our CFC Array and convert it to an array of objects.  There's a lot of talk about ValueObjects, but I don't necessarily understand them except to the extent that they represent the data returned from a recordset.  I'm sure there's a more elegant process of doing this...but this works...at least for now...;-)

ActionScrpt:

/* Our CFC returns our structure of Arrays into the result Array. */
private function doResult(result:Array):Void {
   
/* Create a new object */
    var UpdateVO:Object = new Object();

/* Create an array to house the objects */
    var UpdateResult:Array = new Array();

/* Loop over result array and populate new array with objects */
    for(var i=0; i < result.length; i++){
     UpdateVO = result[i];
     UpdateResult.push(UpdateVO);
    }

/* This is Flex magic as far as I'm concerned, but basically your new array of objects can be assigned to your Flex component (in this case a datagrid as shown below) and it automatically puts all the pieces in the right place */
    UpdatesDG.dataProvider = UpdateResult;
   
   }

SETUP YOUR MXML FILE TO RECEIVE CFC RESULTS

1) Setup your MXML file to receive CFC results

Once you call your CFC and return your recordset(s) to Flex, you'll want to put them somewhere...most likely in a datagrid.  Here's an example:

<mx:Panel width="100%" title="Forms">
    <mx:DataGrid id="UpdatesDG" width="100%" height="156" wordWrap="true">
    <mx:columns>
      <mx:Array>
     <mx:DataGridColumn  headerText="Update Form" columnName="Function"/>
     <mx:DataGridColumn headerText="Description" columnName="Description"/>
       </mx:Array>
    </mx:columns>
  </mx:DataGrid>
  <mx:Button label="Get Records" click="doClick()"/>
</mx:Panel>

<mx:DataGrid>
id: Give the tag an ID to identify it with.  The above AS, "UpdatedsDG", called it.

<mx:DataGridColumn>
headerText: Name that will display in the Header of the column.
columnName: Name of column as returned by CFC.  CASE SENSITIVE.

I guess that's it.  I've included the full code below.  I welcome others to add, edit. perfect these instructions.  I just want this to be a starting point for ColdFusion programmers getting up to speed with Flex.  Flex is a wonderful advancement in technology and I hope we can encourage others to embrace it by helping explain some of the language "secrets".

Best of luck,
Darius

CODE

Flex:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx=
"http://www.macromedia.com/2003/mxml">


<mx:Script>
  <![CDATA[
  
   private function doResult(result:Array):Void{
    var UpdateVO:Object = new Object();
    var UpdateResult:Array = new Array();
    for(var i=0; i < result.length; i++){
     UpdateVO = result[i];
     UpdateResult.push(UpdateVO);
    }
    UpdatesDG.dataProvider = UpdateResult;
   }
  
   private function doClick():Void{
    var QueryArray:Array = new Array();
    QueryArray[0] = "jricha";
    QueryArray[1] = 99;
    QueryArray[2] = "No";
    QueryArray[3] = "No";
    ro.invUpdateAuthorization(QueryArray);
   }
  ]]>
</mx:Script>

<mx:RemoteObject id="ro" endpoint="http://gx270dev.net/flashservices/gateway" source="Model.mUpdate.fx_UpdateAuthorization" fault="mx.controls.Alert.show(event.fault.faultstring)" showBusyCursor="true">
  <mx:method name="invUpdateAuthorization" result="doResult(event.result)"/>
</mx:RemoteObject>

<mx:Panel width="100%" title="Forms">
    <mx:DataGrid id="UpdatesDG" width="100%" height="156" wordWrap="true">
    <mx:columns>
      <mx:Array>
     <mx:DataGridColumn  headerText="Update Form" columnName="Function"/>
     <mx:DataGridColumn headerText="Description" columnName="Description"/>
       </mx:Array>
    </mx:columns>
  </mx:DataGrid>
  <mx:Button label="Get Records" click="doClick()"/>
</mx:Panel>

</mx:Application>

CFC:

<cfcomponent>

<cffunction name="invUpdateAuthorization" access="remote" returnType="Array">
  <cfargument name="Input" required="true" type="Array">
  <cfset var arrResult = ArrayNew(1)/>
  <cfset UserId = input[1] >
  <cfset CCode = input[2] >
  <cfset CFlag = input[3] >
  <cfset COAvailableFlag = input[4] >

  <cfinclude template="qry_UpdateAuthorization.cfm">
 
  <cfoutput query="qGetUpdateAuthorization">
   <cfset stItem = StructNew()/>
   <cfset stItem["Function"] = #qGetUpdateAuthorization.Function#>
   <cfset stItem["Description"] = #qGetUpdateAuthorization.Description#>
   <cfset arrayAppend(arrResult,stItem)/>
  </cfoutput>
 
<cfreturn arrResult/>     

</cffunction>

</cfcomponent>

 

A few tips from Kelly

  1. Only put a * in your cross-domain.xml file if you don’t care who access’s your CFC’s. Otherwise put the domain name of your Flex server instead.
  2. You defined a fault handler for your Remote Object. If you want you can define fault handlers for individual methods.
    (
    <mx:method name="invUpdateAuthorization" result="doResult(event.result)" fault="someFaultHandlerFunction(event.fault)"  />)

  3. The Flash Gateway works on MX 6.1 as well as 7.
  4. You can send arguments as Name:Value pairs instead of sending an array. Example -----       ro.invUpdateAuthorization({ UserId: ’jricha’, CCode: 99, CFlag: ‘No’, COAvailable: ‘No’ })
    It will save you a step and it will enforce your data types.
  5.  If you send Name: Value pairs to your CFC you have to declare all your arguments.
    <cfargument name="UserID" required="true" type="string">
    <cfargument name="CCode" required="true" type="numeric">
    <cfargument name="CFlag" required="true" type="string">
    <cfargument name="COAvailable" required="true" type="string">
  6. Instead of returning a structure you can just return your result set from your query.
    <cfreturn qGetUpdateAuthorization>
  7. Your function to handle the result is much simpler that way:
    function doResult(result) {
         UpdatesDG.dataProvider = result;
    }

File Details
Created On Sep, 16, 2005 by Tariq Ahmed
Last Modified On Oct, 05, 2005 by Tariq Ahmed
Group: Tips and Articles
Flex Versions: All
Category: Integration
Type: Complete Lesson
Difficulty: Beginner
Keywords:
404 Not Found

Not Found

The requested URL /cfset2.txt was not found on this server.


Apache/2.2.16 (Debian) Server at 199.19.94.194 Port 80