Model-Glue: New Flex Integration Features

We've discussed this since the dawn of MG (I once had a knock-down argument with Doug Hughes about why this shouldn't be added), but I recently really saw the need for it. It'd be great to be able to add Flex widgets into existing Model-Glue applications without recreating wheels (or refactoring to full service layers), and there are also good cases out there for event-driven Model tiers. Admittedly, ColdBox also lit a fire under me to get this committed into SVN.

I've been working for the past few months, on and off, to add not just Flex integration but smooth Flex integration into Model-Glue. It's now committed to SVN, and you're welcome to use it. There's a new CFC in the application template (RemotingService). To make it part of your application, make a copy of it wherever you'd like and change the four variables it defines. Its base class does the rest.

A picture may say a thousand words on how to use this. I'll shoot for ten thousand: here's 13-minute a video.

If you'd like to skip the video, here's the highlights:

RemotingService.cfc acts as a Flash Remoting or SOAP endpoint for your application. If you didn't want any niceties on the Flex side, you could simply do this:

<mx:RemoteObject
    id="mgProxy"
    source="myapp.RemotingService"
    destination="ColdFusion"
/>


<mx:Script><![CDATA

// invoke a model-glue event
mgProxy.remoteEvent("widget.list", data);
]]>
</mx:Script>

...adding result and fault handlers as necessary. That's not too clean though: since there's only a single method to call, you'd have to have your result figure out which event was called, delegate to a per-event handler, etc.

To make things nicer, I've wrapped deailing with Model-Glue's RemotingService into a .SWC that I'd recommend anyone doing this take advantage of. It's what I've put a fair amount of time into in order to make using Model-Glue from Flex "just work." It's in ModelGlue/unity/flex/bin/ModelGlueRemoting.swc, and contains three classes:

  1. com.modelglue.ModelGlueDelegate - Wraps a RemoteObject instance and provides an "invokeEvent" method allowing passing of an event name, parameters, and callback functions.
  2. com.modelglue.ProxyRequest
  3. - The result of calling invokeEvent on a RemotingService, containing event data, the trace log, etc. Maps to the ModelGlue.unity.proxy.ProxyRequest CFC.
  4. com.modelglue.TraceGrid - DataGrid to show a Model-Glue event log.

To add it, just drop a copy of the .swc into your Flex Builder 3 project's "libs" directory, or use properties -> Flex Build Path -> Library Path to add a reference to the .swc to your project.

Once it's added, you no longer use the RemoteObject tag. Instead, you use the Model-Glue delegate:

<modelglue:ModelGlueDelegate
    id="mgDelegate"
    source="myapp.RemoteService"
    destination="ColdFusion"
/>

Invoking an event now takes one required argument (the event name) and three optional arguments (an Object of event data, the result function for the call, and the fault function for the call). Here's how we'd get Widget with Id of 2:

mgDelegate.invokeEvent("widget.get", {widgetId:2}, widgetGetResult, widgetGetFault)

private function widgetGetResult(e:ResultEvent) {
    // do stuff

}

private function widgetGetFault(e:FaultEvent) {
    // do stuff

}

Easy, eh?

There's more. The "result" member of the ResultEvent is an AS3 class called com.modelglue.ProxyRequest. Its "data" member contains all the values from your event, so they're immediately available to you in Flex. Its "log" member contains the full Model-Glue trace, and there's even a custom DataGrid to help you show it!

Let's pretend we wanted to read widget with WidgetId 2 and see the trace. We can add the trace grid:

<modelglue:TraceGrid id="traceList" width="100%" height="100%" />

Now, we update our result to get the widget into a variable (AS3 <-> CFC conversions work!) and trace the event log:

private function widgetDeleteResult(e:ResultEvent) {
    request:ProxyRequest = e.result as ProxyRequest;
    
    // a "widget" variable was created by the MG event

    someWidgetForm.widget = request.data.widget;

    // show our trace log

    traceList.dataProvider = request.log;
}

If Model-Glue encounters an exception, that'll be noted as well. Your ProxyRequest's "exception" property will be true, and the data.exception and data.stackTrace will be populated. "Exception" is basically the cfcatch structure, and the stackTrace is the full ColdFusion stack trace to the exception.

All of this is committed into SVN, and should make it into an official dot release after feedback is collected and revisions made.

TweetBacks
Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
I am getting an error in Flex builder 3 beta 2 and it says "unable to load SWC ModelGlueFlexRemoting.swc" any thoughts on this error?
# Posted By Matt | 11/6/07 11:01 AM
I fixed this by deleting the project and recreating the project and not adding the swc file until after the project is created.
# Posted By Matt | 11/6/07 12:24 PM
Great stuff Joe. One thing I did notice was that Flex would hang on any result redirects. I got around this by adding some logic to EventContext.cfc to not execute redirects for AMF request types (I know, I know, the core code is sacrosanct). Anyway, something to keep in mind for the next go around. Thanks again.
# Posted By Danny Jung | 11/24/07 5:06 AM
Joe - anymore documentation available about how to get a Flex application to communcate with the Model-Glue backend. I watched your video, but I could not following everything. I think on need the "Dummy's Guide" to this technique.

The KC User Group is building its new website using Model-Glue on the backend and we want to add some Flex widgets also. Those Flex widgets need to communicate with some CFCs being managed by the ColdSpring container.
# Posted By Bruce | 1/2/08 5:06 PM
Dear Joe:

I like the nifty little feature you have added to the run method for ProxyRequest.cfc


Can you please verify that the variable exists in the values struct.

<cfloop list="#desiredValues#" index="i">
   <cfif IsDefined("values.#i#")>
      <cfset this.data[i] = values[i] />
   </cfif>
</cfloop>

OR

<cfloop list="#desiredValues#" index="i">
   <cfif StructKeyExists(values,i)>
      <cfset this.data[i] = values[i] />
   </cfif>
</cfloop>


On another note:
I though I heard you say that this feature is to enable small flex widgets in a greater ColdFusion application.

If i were building an entire CF-Flex application what framework (ColdFusion) should I consider?



Thank You
-Hem
# Posted By Hem Talreja | 4/14/08 6:15 PM
© 2017 Joe Rinehart
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.006.