Flex2 External Interface Bug
Lest I lead people to believe I am a complete Flex fanatic with my previous posts, I thought it was time to post about a brickwall that we have not yet been able to conquer (and maybe someone will happen to read it and have an answer).
At work I use and love DWR. One component of our flagship product suite was initially a Javascript/Html interface that used DWR to communicate with our Java 1.5/Spring/Hibernate back-end. We decided to give Flex2 an honest, lengthy trial run as a potential replacement for the interface technology for this component.
When the decision was made to give this a shot, we had man-months of back-end functionality built and exposed via DWR. It simply did not make sense to rewrite this code. Further, there was no alternative to DWR that I liked as much. I refuse to believe FDS is worth its ridiculous price tag (I’d rather save 40k per server for additional engineers, additional disk arrays and more servers thank you) and all of the open source options I evaluated paled in comparison to DWR. We spent a man-week or so and built a communication layer that allowed to us to use DWR much as we were with Javascript inside of our Actionscript. This communication layer used the ExternalInterface API of Flex2 in some clever ways.
Now to the point of this whole post: we recently discovered what appears to be a pretty substantial bug in ExternalInterface. I’ll use JSON notation to demonstrate. It took us some time to realize what was going on.
Inside of the Javascript communication layer I can receive an object from DWR that looks exactly like this in Firebug:
mainObject = {
id: “1234″,
name: “mainObject Name”,
mainControl: “mainObject Control”,
subObject: {
id: “abcd”,
name: “subObject Name”,
subControl: “subObject Control”
}
}
Further, I can trace this with Firebug line for line right up through the point at which it is handed off as a parameter to a method exposed on ExternalInterface.
Now on the Actionscript3 side of things I have my breakpoint and debugger ready to stop immediately after reception of this object on the other side of the ExternalInterface. When it arrives it now looks like this:
mainObject = {
id: “abcd”,
name: “subObject Name”,
mainControl: “mainObject Control”,
subObject: {
id: “abcd”,
name: “subObject Name”,
subControl: “subObject Control”
}
}
Notice what happened:
- All same named properties are set to the values of those properties on the subObject. The values on the mainObject were completely overwritten!
- The differently named properties (mainControl and subControl) retained their correct values.
This a huge deal. To continue down this Flex2/DWR path we would have to refactor dozens and dozens of value objects to ensure no value objects that are nested inside of each other share property names and all future development would have to be done with this awareness as well.
This seems like a show stopping bug and that is why deep down I have to believe we are simply doing something odd with our implementation. Has anyone else encountered this issue or have any idea as to why we would be experiencing it? I don’t have any more code I can run a debugger on to try and figure this out.
I’ve got a post on the flexcoders list but our experience with that list has typically been that difficult questions are met largely with silence.
Tim Beynart said,
May 2, 2007 at 11:42 am
I come from a Flash application development background. One reason you may not have gotten much response about this is the standard approach to Flash Player data handling. Usually when a decisioon is made about data transfer, the choices are XML of some flavor or the binary AMF format. External Interface is reserved for local JavaScript communication like passing events back and forth form the player to the browser environment. In other words, it is rare that anyone would be using Javascript as a proxy to a remote service and therefore would not be passing complex objects through EI. There is a distinct possibility that you are the first developer to find this bug.
I understand from your blog that you have moved on, but this may explain the echo chamber you faced with your issues… good luck!
Seb said,
August 7, 2007 at 8:31 am
I am very interested by using Flex with a DWR beckend.
Do you know if this bug has been corrected in Flex 3 beta ?
gtuhl said,
August 7, 2007 at 8:44 am
Hey Seb,
Thanks for commenting. Matt, a Flex PM commented on another one of my posts here:
http://blog.gtuhl.com/2007/03/28/flex2-opinions/#comment-23
Here is the relevant piece:
—————
The ExternalInterface bug is in the Player and we have it opened to fix in the next major Player release. I am investigating whether we could push that up sooner, though I realize you’ve already moved on and it won’t make a difference for you guys but could for others.
—————
So it turns out to not be an issue with Flex specifically, it is an issue with the Flash Player. Unfortunately it seems this would mean not only would the bug need to be fixed and a patch released, but any users of your code would have to update their Flash Players.
You could also just be very careful with property names to ensure they don’t repeat within a complex object but it seems this would carry a high chance of an accidental, possibly hard to debug issue in your software.
Good luck with your project and DWR,
Joe
Paul Mignard » Blog Archive » Wow - it’s been a long month… said,
December 9, 2007 at 8:01 pm
[...] sentence) expert but I couldn’t not find a consistent way to make these work and the only place I could find that made it work wasn’t really happy with it and eventually abandoned it. So [...]
Keshav Prasad said,
January 17, 2008 at 3:11 am
Hi gtuhl,
I am a web developer working on flex. I am right now working on executing a DWR function from javascript in my flex application. After reading your post, I got an idea of making DWR calls from javascript by calling that related js function frm .html file generated by the .mxml file.
But, the DWRengine.execute method is not getting executed.
this is the function i wrote and i am calling from flex usign ExternalInterface.call
function dwr_call()
{
alert(”Inside DWR+CALL”);
DWREngine._execute(’../WEB-INF/dwr’, ‘documentUtil’, ‘getAllDocumentTemplates’, {
callback:function(data)
{
if (data) {
alert(data);
}
},
errorHandler:function(errorString, exception)
{
}, async:true
});
}
and the flex_dwr.mxml
import flash.external.*;
public function callWrapper():void {
var s:String;
if (ExternalInterface.available) {
var wrapperFunction:String = “dwr_call”;
s = ExternalInterface.call(wrapperFunction,ti1.text);
} else {
s = “Wrapper not available”;
}
trace(s);
}
Any Suggestions or help
Thanks in Advance,
Keshav.