Dec 4 2006

Flex 2 and ColdFusion: Are VO's always the way to go?

Posted by Joe Rinehart at 7:32 AM
15 comments
- Categories: Flex and ColdFusion

I'm working on an in-house Flex application right now, and I'm hitting a point where I'm concerned about the load associated with creating large collections of Value Objects. Background:

When dealing in Flex, it's a good idea to deal in typed transfer objects between the Flex client and the Java/CF backend. By "typed transfer objects," I mean something like a Value Object instead of simply a structure or associative array.

My problem:

I've got this list of, say, recipes. When displayed as a list, I just need to show the recipe's name and author. Each user can create "variations" on a recipe, and the recipe object has a "variations" property that contains an ordered array of variants on that recipe.

The thing is, I only need to deal with Variants when dealing with the details of a recipe: when they're shown as a list, or search results, all I care about is the name of the recipe and maybe its author's name.

However, when they're shown as detail, I want to show a list of all of a given recipe's variants.

It's easy to do SQL to return everything at once:

SELECT
r.recipeId,
r.title,
v.title AS variantTitle
v.recipeId as variantId
FROM
recipe r
LEFT OUTER JOIN recipe v ON r.recipeId = v.originalRecipeId

However, my service facade then has to marshall many more VOs than is necessary for the list. Granted, I can cheat by creating a cache of VO's keyed by ID and cut down on the number created, but I'm still going to find situations where CF is going to want to create thousands of VOs in one request, and creating CFC's en masse just isn't CF's strong suit. FDS isn't an option here.

So, I'm stuck at this point where I almost want to return just a query, which comes across as an array of untyped Objects. Then, when someone views the details of a recipe, I'll go back to the server and load it.

Conclusion

I'm not too sure where I'll end up with this. I'm not a big fan of overoptimizing up-front: I'll probably just go the "swarm of VOs" route, and if it never causes a problem, I'll leave well enough alone.

Comments

Owen van Dijk

Owen van Dijk wrote on 12/04/06 8:27 AM

We have a deep, nested object model with multiple VO's containing collections of one or more VO's. What we did is to check which information we absolutely needed 'on first load' (say getItems() and when we needed more information, we created a service ( say getCommentsByItemId(id) ) that returns an collection of CommentVO's for that ItemVO. In the result handler of that service i then 'fill' the empty VO with more data.
Sam Shrefler

Sam Shrefler wrote on 12/04/06 8:44 AM

I've done the same thing that Owen has said. I return a collection of ItemVO's with details not filled in (NULL). Then i have getDetail commands which further populate my ItemVO.

The question I've run into is as follows:

Lets use the recipe concept:
You have a RecipeVO. All recipes have the same common information. So you return a collection of RecipeVO's. My RecipeVO has a property "recipeType" that I'd like to be a typed object. For example (BakedRecipeVO, FrozenRecipeVO, AppetizerRecipeVO). Currently, I'm using a generic object and just stuffing in one of the above VO's.

I'm losing my typing anyway! Any thoughts on how to handle something like this?

Thanks

Sam
Johnny Boursiquot

Johnny Boursiquot wrote on 12/04/06 8:49 AM

I've come across similar situations in my dealings with flex/cf and have remained with always returning VOs. I use caching on the server side which has eased the load quite a bit. I concur with sticking to Value Objects and if that becomes a real problem for certain parts of your app, return queries.
Tom Chiverton

Tom Chiverton wrote on 12/04/06 9:02 AM

The benefits of returning (array of) VO outway almost all the objections.
If you find you really are returning 'thousends' of VO in each request, it is likely you are doing something wrong, as there is no way your end user can view thousends of things at once.
Joe Rinehart

Joe Rinehart wrote on 12/04/06 9:13 AM

Hey Tom,

Not to be contrary, but sure, there are plenty of situations for this to happen.

Let's pretend we're rewriting the iTunes store in Flex. A search result for "foo" may have 250 results, each a "song" displayed in a grid.

Each song has 1 album, each album has, let's say, 10 songs. To pull the whole tree down as a set of VO's that lets me click a single row in the grid and have a detail view display the song, its album information, and the other tracks on that album, that's 1*250 Search Results + 1*250 Albums + 10*250 related songs = 3000 VO's. Oi. At that point, you've got to use something akin to lazy loading (as others have described here), use an untyped query for search results and then query for details (kind of ugly), or create two different Song classes: SongSummary (for search result purposes) and Song (that contains fulls details and is loaded when detail is required).
Tom Chiverton

Tom Chiverton wrote on 12/04/06 9:23 AM

I think we're agreeing with each other Joe :-)
Sure, you *could* build an app that tried to send 3000 VOs at once. You'd find the CFC creation cost was a big factor here, and Do Something Else.
Joe Rinehart

Joe Rinehart wrote on 12/04/06 9:45 AM

Ah, ok. I thought you meant "doing something wrong" as in not providing enough filters, etc., and returning someone a lot more data than they wanted to deal with.

So, yes, we're in agreement. Sorry if I was flippant, I'm just now getting my first cup of coffee this morning.
Mark Drew

Mark Drew wrote on 12/04/06 11:12 AM

Joe
Did you have a look at my speed tests with Beans (or VO's) vs Java Beans (or Generic Beans)?

Maybe an easy way to go is using Java and then you CAN send thousands of objects over?
Patrick McElhaney

Patrick McElhaney wrote on 12/04/06 12:22 PM

I think getting a query for the list and then going back to the server for details makes sense, except for the fact that you don't want to deal with untyped objects.

Could you create something like a RecipeSummary class that only contains the details you need for your list (id, name, author)? Instead of a query, you would return an array of RecipeSummary objects.
Doug Keen

Doug Keen wrote on 12/04/06 12:34 PM

You could always create a VO object pool and borrow your VOs from that (thus avoiding the mass VO creation... you'd just have to populate them). The only tricky thing is returning those VOs to the pool when you're done; I don't know of any way to do a "post-FDS" action. You could have your object pool track "checkout times" and have a scheduled task return the VOs to the pool after some timeout period. Then the trick would be finding the magic timeout number that would return objects to your pool promptly, but wouldn't put you at risk of returning an object to the pool before you're done using it (as in a long-running request).
Douglas Knudsen

Douglas Knudsen wrote on 12/04/06 10:33 PM

Mark D, can you return a Java POJO to Flex and get all that fancy mapping to a AS object with a CF server? Me curious. Me thinks you will need FDS for this.

I had a thread on the CFCDev list on this subject. I got from this that returning lightweight data in XML was a good approach. From this can fetch a needed VO. CFC instantiation is costly.

DK
Mike Nimer

Mike Nimer wrote on 12/05/06 1:36 AM

Douglas K. - If you can, returning a query is better then an xml object. No need to do deSerialization or Serialization of the xml on the client and server..
Although a small dataset is a small dataset and you'll probably never notice the speed issues.

Joe - Granted, there is always 3 ways to do things. However, I would say that the advantages of VO's are worth it. With RIA apps the screen/app doesn't reload,
which means the user can make 1 big request and then spend the next 20 minutes working on the data and never go back to the server. So what's better 1 hit every 20 mins or lots or little hits.
Douglas Knudsen

Douglas Knudsen wrote on 12/05/06 8:05 AM

Mike, interesting, I usually hear best-practise from teh Flex world is to never return a query object from a CFC. Besides the whole case thing with the field names, its not consumable by other systems. What other opinions are about on this?

DK
Mike Nimer

Mike Nimer wrote on 12/05/06 10:37 PM

Perhaps in flex 1.5, however, it?s fine in flex2. In Flex2 query objects are automatically converted into a proper ArrayCollection of Objects. (note: if you send the arrayCollection back to CF it becomes an Array of structs, not a query). Also, don?t forget, you can force the case of queries and structs in the service-config.xml file.

To return a query or not, it's really an architecture argument not a functional argument. If you are using true "OO" then you may not want to return a queries (or other simple objects like arrays and structs for that matter). However, functionally there is no reason not to return query objects. It might actually be faster to use a query.

note: I personally always return CFC objects, but that?s because I like coding my flex apps using typed objects.
Robert Stark

Robert Stark wrote on 05/29/07 12:06 PM

Could someone give an example on how to transfer nested objects from Coldfusion to Flex. This is a very hard subject to find info on. I can do Simple Objects just fine. But I can't seem to be able to do nested objects. Any blogs or info about this would be helpful. Thanks

Write your comment



(it will not be displayed)