I am in the process of converting a Flex application currently backed by Adobe ColdFusion 8 and LiveCycle Data Services to one that is backed by Railo 3.1.2 and BlazeDS. In so doing, I ran into an interesting issue that I thought might be helpful to record in case anyone else runs up against it.
The conversion from ColdFusion to Railo was, mostly, seamless. However, when I began connecting the Flex UI to Railo/BlazeDS, I hit a snag.
The problem I encountered was with remote calls that passed one or more parameters to the server. In every such instance, Railo responded with an error that went a little something like this:
FaultEvent fault=[RPC Fault faultString="flex.messaging.MessageException: invalid call of the function MYFUNCTIONNAME (/path/to/my/remote/cfc/remoteservice.cfc), first Argument (ARG) is of invalid type, can't cast Object type
[Struct] to a value of type [numeric|string|etc.]." faultCode="Server.Processing" faultDetail="null"]
messageId="DDCBCF4C-90AC-E431-6195-3020C9C24765" type="fault" bubbles=false cancelable=true eventPhase=2]
The issue turned out to be a key difference in how ColdFusion and Railo (or LCDS and BlazeDS) handle named parameters passed to the remote method as an object. Consider the following remote method invocation from our Flex application:
remoteBlogObject.getBlog( { blog_id:_blogID, start:_start, end:_end } );
Our Flex developers create an object with a key/value pair for each parameter the remote CFC method requires and send that along with the call.
ColdFusion 8/LCDS takes this object and converts it, in the case of the example above, to three distinct parameters (blog_id, start, end) which then get passed to the CFC's method.
Railo, on the other hand, receives this same object and converts it to a java.util.Map; the Java object on which a CFML struct is based. As a result, Railo sends a single parameter, typed as a struct, to the CFC's method. The struct sent to the method by Railo/BlazeDS does, in fact, contain the right keys (blog_id, start, and end) and values, just not as separate parameters.
While there are certainly more options, we opted to tackle this issue in one of two ways: (1) Change all the remote CFC methods to expect a single parameter (type="struct") or (2) Update the remote calls from Flex to not pass an object; rather, just pass in the parameters.
Thankfully, our team decided to go with option 2 as this approach required less overall code refactoring than option 1 and, more importantly, makes our Flex remoting calls consistent and usable with ColdFusion 8, ColdFusion 9 and Railo (maybe OpenBD, too?).
Side note: While the automagic conversion employed by ColdFusion seems helpful on the surface, I can't help but think it's more detrimental than good. If I'm passing a generic object ( {giggity:_giggity} )from a remote method, I would expect this same object to be an object (or struct in CFML) when it gets to my CFML server. I'd certainly be interested to know what other people think of this sort of "assistance", especially given the increasing interest in both a standardized CFML and open-source CFML engines.
Think it's also worth noting that railo (and maybe CF, havn't tried) requires the cfargument tag to be able to parse your values when your passing paramaters like this.
It might be obvious but I was just passing the argumentsCollection to a subsequent function and was getting fustrated to see my arguments were not present.
Cheers!
For what it's worth, when calling cfc from Flex, I usually skip explicitly referencing the named parameters and just specify them by position. It seems to do the trick and ought to not suffer from compatibility iddues.