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?

 

Comments (17) | Print | Send | del.icio.us | Digg It! | Linking Blogs
2843 Views

Comments

Jo?o Fernandes's Gravatar Does your Employee.cfc have the cfproperty tag for each field and the alias attribute set?
# Posted By Jo?o Fernandes | 11/8/07 2:54 PM
David Buhler's Gravatar Hi Leif,

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
# Posted By David Buhler | 11/8/07 7:29 PM
David Buhler's Gravatar Here's the LiveDoc with some mention of the property-case:

http://tinyurl.com/ywsm5y
http://tinyurl.com/24oak
# Posted By David Buhler | 11/8/07 7:33 PM
Gareth's Gravatar Also, I found that if you are using getters and setters, that they must also match the cfproperty tags (and your corresponding Actionscript object) or it won't "know" that the objects actually match. I had been puzzling over why when I passed my object from AS to CF that it worked, all the way through the CF object it was fine, but as soon as it got passed back to AS, it was a brand, new object again. Just make sure every case where you're setting your variables (cfproperty, this.my_variable_name_here, getters and setters, etc.) matches and it should pass it back and forth fine. The only time I found where it will always return uppercase is if you have a returntype of "query" inside your cffunction calls. There doesn't seem to be any way around that (at least other than then method you describe)
# Posted By Gareth | 11/8/07 9:21 PM
Jon Messer's Gravatar This was driving me nuts too.

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...
# Posted By Jon Messer | 11/8/07 11:24 PM
Ciqala Burt's Gravatar i'm not sure if this is helpful at all but recently a colleague of mine noticed that the way you set data inside a struct affects the casing of the key used.

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 :)
# Posted By Ciqala Burt | 11/9/07 7:46 AM
Tom Chiverton's Gravatar This is almost always because your cfproperty tags or AS3 meta data is wrong.
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.
# Posted By Tom Chiverton | 11/9/07 8:21 AM
Gareth's Gravatar @Tom
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.
# Posted By Gareth | 11/9/07 8:33 AM
Tom Chiverton's Gravatar @Garath
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
# Posted By Tom Chiverton | 11/9/07 8:37 AM
Gareth's Gravatar Well, fine! :) We've been using the FlexBuilder CFC wizard then making tweaks to the files as needed. I'll have to check out Reactor...from Alagad, correct?
# Posted By Gareth | 11/9/07 8:45 AM
FlexableCoder's Gravatar I have to agree, this is something that drove me crazy. what's even worse is that flex doesn't automatically put these items in to the correct classes on the flex side. The best way i found to deal with it is to create an object translator that takes the value objects from the coldfusion/webservice side and then puts them into the cooresponding classes on the flex side. FlexBuilder 3 has a wizard that will do this for you (and create all of the appropriate classes on the flex side) the downside of this is that every time the backend web service changes, you have to re-run the wizard. what a pain. Anyway, the object translator that i wrote takes care of the issue. what it does is essentially matches up one object to the other and makes all of the cases correct, so the coldfusion uppercase issue becomes a non-issue. anyway, if you are interested, i've posted info about it on my blog.
# Posted By FlexableCoder | 11/9/07 5:55 PM
Tom Chiverton's Gravatar @FlexableCoder
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.
# Posted By Tom Chiverton | 11/12/07 7:04 AM
Erik's Gravatar I have worked with Value Objects alot. The major problems that I came across was not the case, it were:

- 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
# Posted By Erik | 11/14/07 6:09 AM
Jason Foust's Gravatar This is an old flash issue and using Structs was the way to get around it. Fortunately, flex and CF play a lot better together.

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.
# Posted By Jason Foust | 3/19/08 3:30 PM
Hem Talreja's Gravatar There are three things you can do.

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")
# Posted By Hem Talreja | 6/4/08 1:58 PM
Erik's Gravatar "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
# Posted By Erik | 6/5/08 4:55 AM
Jo?o Fernandes's Gravatar Erik, it only works with CF8. __type__ 'hack' was introduced first for making LCDS fills faster and then they extended the support to remoting.
# Posted By Jo?o Fernandes | 6/5/08 8:59 AM