ColdFusion to Flex Remoting: UPPERCASE Rage!
How are developers handling the passing of Value Objects from ColdFusion to Flex using AMF?
Here is my situation: I am using ColdFusion as I believe that it was originally intended --- for rapid application development. The difference here being that the application is actually being built in Flex and ColdFusion is being used to manage the data coming from the server. I don't know Java and when I have to get work done without a Java developer available, I turn to my good friend ColdFusion to help me out. ColdFusion makes it easy for me to get my entire Flex application completed (well, as completed as possible) before the Java developers have touched their keyboards. Other than the specific problem I am about to describe, it appears to be working out for me.
I am quite certain that I am not the first person to run into this, and it seems like there should be a better solution than the ones that I have seen. On the ColdFusion side, I have a Employee.cfc that extends Person.cfc that extends User.cfc. I would like to make a call to my main CFC file passing a UUID and have that method return an Employee Value Object.
When I create the Value Object in a CFC and pass it to Flex all of the properties in the value object are in UPPERCASE. I could make all of my property names in my ActionScript Value Object UPPERCASE, but why the heck would I want to do that?!? I am baffled at why if I set something in a CFC to "id" I get it returned to me in Flex as "ID". For that matter, I should be able to make my property appear as "firstName" and have it return to me that way. I am pretty sure that there is a very technical reason for this, but damn... just damn.
So, I do have alternatives.
Since the query in the controlling CFC returns to Flex a perfectly formed Struct inside an ArrayCollection, I could just loop through the ArrayCollection and cast each Struct into a Value Object. The problem here is that 1) when I ask for one object, I should expect to get one object and not one object inside and array, and 2) when/if this project's back-end is converted to Java (which in this case is a certainty) I'll have to go in and change everything (and this is a problem, too, with the CFC solution. I am never going to get a Java developer to create a Value Object file that has properties in UPPERCASE. It's like screaming!)
Then, there is the option of creating a Struct from the Query and passing that along to Flex. I get what I want on the Flex side, but it totally ruins the object-oriented goodness on the ColdFusion side of things.
This is probably only bothering the Flex developers out there like me, but it's an problem I would like for Adobe to solve. Right now, since I know that this project's back-end will be created in Java eventually, I think I will be going with the last option of converting the Query item to a Struct. That is, unless someone comments here with an option I have not seen. Is there a better option? Is there a setting in ColdFusion 8 that will change this?
2843 Views



Comments
Long time, No Coffee! I'm in Raleigh, now, but I still visit ATL every other weekend (Girlfriend).
When Coldfusion installs by default, there's just one Services-Config in the Flex Folder. If I remember right, the destination attributes are specified within this XML file.
Within...
C:\ColdFusion8\wwwroot\WEB-INF\flex\Services-Config.xml
...you only need to change the <property case> node values to true for the value types you want to lowercase. I loathe the uppercase formatting of the struct or column, so I always force to lowercase. I don't know of a way to camelCase the columns or or Struct names, but I'm content with the readability of lower-cased column names and object names.
I also likes all values returned to Flex forced to lowercase. My rationale:
All column names are lowercased in Flex, if it's returned from CF (loginEventResponse.usersinfoobject.firstname=Gary).
All public variables in Flex are camelCase
All Private variables in Flex are __camelCase
I find the aforementioned logic is the best way to differentiate where values arrived from.
By default, all columns are uppercased in Flex. Find and change the following, and reboot:
<property-case>
<!-- cfc property names -->
<force-cfc-lowercase>true</force-cfc-lowercase>
<!-- Query column names -->
<force-query-lowercase>true</force-query-lowercase>
<!-- struct keys -->
<force-struct-lowercase>true</force-struct-lowercase>
</property-case>
Suggestion: There's a compiler argument to export the service config files from Flex, but I forget the argument. I run with my Services-config with the following:
<services>
<service-include
file-path="remoting-config.xml" />
<service-include
file-path="proxy-config.xml" />
<service-include
file-path="messaging-config.xml" />
<service-include
file-path="data-management-config.xml" />
</services>
DB
http://tinyurl.com/ywsm5y
http://tinyurl.com/24oak
At first I just did the cfc -> as3 thing, by making sure that my cfproperties matched case and order to my as3 vo. But what I've been doing lately is creating structs with this syntax myStruct['myProperty']=x that syntax preserves case, the myStruct.myProperty=x becomes MYPROPERTY.
As an added hack, if you define myStruct['__type__']="my.cfc.type", cf will convert it to the correct actionscript VO for you.
This does use udocumented features, so it might be a bad idea in the long run, but I was finding that creating arrays of actual CFCs was WAY to expensive, with this method I can return an array of 20000 automagically converted structs to as3 vo's in just under two seconds...
These are pretty complex composed struct/vos they have multiple other struct/vos. If I tried to populate and return 20,000 actual cfcs (or Transfer TO's) the server would crash or take like an hour.
This has been working great for me, but like I said the ['__type__'] thing is undocumented, but I think the case thing is...
if you look at this example...
<cfset myStruct = StructNew() />
<cfset myStruct.foo = "bar" />
<cfset mystruct['woo'] = "yay" />
<cfdump var="#myStruct#" />
foo will be set in uppercase
woo will be set in the case you specify.
apologies if this is off track, but as we came across it recently i thought i'd share :)
You can save heartache by using the Adobe ColdFusion Eclipse plugins, and right clicking the CFC (or AS3 VO) and having it make the class for the 'other side' for you.
The only problem I found with that method is it matches the dB casing (our DBA uses uppercase for first letter of all words, including first letter). When I get my data back from the dB, I like to have camelCase throughout, so I have to go back through and change all of the casing (cfproperty, "this", and getters and setters). As long as I change everything, it's not a big deal, but if something is missed, it can be a bit of a pain.
Depends how you generate your cfproperty tags - we use Reactor, and set an alias for fields where we need to change it, then generate the VO from reactor.project.name.to.thingTo
Flex and Coldfusion absolutely do automatically put values into the correct properties of value objects when they go in either direction, subject to you having the right meta data in place at both ends. If this isn't working out for you, ask on CF-Talk or something, including the two classes source code.
- The inability of the the gateway to translate ColdFusion objects correctly, it did not go up the inherritance chain to find properties.
- The slowness of instantiating components.
We now have a ColdFusion component that creates java copies on the fly and loads those. So a query is converted to an array of these java value object instances and then send back to the flash player.
In order for the flash player's AMF-deserializer to recognise the given objects as a specific type you need to use the following code:
registerClassAlias("package.ClassName", ClassName)
In Flex you can just put this above your class definition:
[RemoteClass(alias="package.ClassName")]
The above things will tell the AMF serializer/deserializer to convert to the correct type. If a 'registered' class instance is sent to the ColdFusion server it will automagically be converted to the correct type.
As for the database column names, we have a component that stores references at application init to the column names. We use that component to get the correct case from query's.
I hope this information helps, mail me if you need more info on this.
Greetz Erik
Instead of using structs, you can use ColdFusion Bean Objects and pass an array of these Bean objects to flex.
This array of coldfusion bean objects will be imported to flash as an array of your vo. This also will work the other way.
The hardest part of this is getting everything set up but once you do it will make your life so much easier.
Check out the new RDS CRUD wizard.
http://livedocs.adobe.com/coldfusion/8/htmldocs/he...
It's been a while since i've done this and I was looking for better information on this, but this should be a decent start.
1. Create Value Object cfc using cfproperty to specify the data and the data types you wish to send over.
2. use myStruct["typedVariableName"] = 100 to have a variable go across as strongly typed object.
3. the myStruct["__type__"] is a supported feature for flex remoting... use this as this is faster than CreateComponent("component","path.to.your.Component")
This does not seem to work with AMF3
Greetz Erik