Flex Example: Populating Value Objects with web service XML

I am working on a little AIR application that stores data both locally (SQLlite) and on a web service (PHP/MySQL) that I’m building in parallel. When the app starts, it requests initial data to populate a pair of DataGrids in the AIR app. I’m sending a URLRequest against a URLLoader with simple params and getting back XML. I am then looping through the items in the returned XML and adding them to an ArrayColletion that acts as the data provider for each DataGrid in the UI.

To bridge the data, I’m storing each item in a value object, so it is easier to reference the item’s properties when viewing and modifying data chosen (and moved around) in the DataGrid. I’m using a nifty trick which seems to be working great for mapping the XML child’s value right to the value object property. Take a look and see if this works for you:

private function resultHandler(e:Event):void
{
	var resultXML:XML = XML(e.target.data);
	var items:ArrayCollection = new ArrayCollection();
	var item:itemVO;
	// Convert XML to ArrayCollection
	for each(var itemXML:XML in resultXML.item){
		item = new itemsVO();
		for each (var itemProp:XML in itemXML.children()) {
			//Use XML node name to reference matching property in value object				
			item[itemProp.name()] = itemProp;
		}
		items.addItem(item);
	}		
}

Of course, this only works if you create properties in your value object that match the xml nodes you are returned (or that are being returned) from the web service’s XML.

chuckstar

7 Comments

Tink

I’d set the properties individually to avoid any errors if the vo doesn’t match the node.

‘item[itemProp.name()]’ is a little flakey IMO, and I believe would be a little slower.

Generally I try and seal my vo’s up from the outside world to (i.e. views etc). If i knew it didn’t need to change I would pass the node into the constructor and assign the properties internally, only exposing them through getters.

Reply
chuckstar22

@Tink,

Thanks for your comments.

I know this solution breaks a few rules, but I was surprised it worked so well for me. I think it should only be used when the developer has FULL control of both the XML and AS code, assuring the available vo props always matches the node names. The properties of the vo are set through implicit getters/setters.

Can you explain why this solution might be slower? I don’t disagree, but are we talking long periods of time? Running this in my AIR app, I don’t see any lag.

Reply
Tink

I’m, not definite, but I think it would be a little slower due to the code having to be evaluated (i.e. string to property). If I’m correct it would still be minor, you’d need huge datasets to see any diff.

still think something like this is much tidier

var resultXML:XML = XML(e.target.data);
var items:Array = new Array();

for each(var itemXML:XML in resultXML.item)
{
items.push( new ItemsVO( itemXML ) );
}

var itemsCollection:ArrayCollection = new ArrayCollection( items );

I’d then get rid or the setter if the data wasn’t editable

Reply
Evan Gifford

To parse your example above using the open source AS3Commons serialization you can do this:

var converter:XMLConverter = new XMLConverter();
converter.register(“item”ItemVO);

var items:ArrayCollection = new ArrayCollection( converter.fromXML( inXML ) );

and back to XML:

var outXML:XML = converter.arrayToXML( items,”items” );

I want to bring attention to a project we developed and released open source with the AS3Commons project. It takes the concept of “fully automated XML deserialization” and provides a set of easy to use Classes to parse large XML files with a few lines.

The first issue we addressed is how to coerce string values in XML to native Actionscript types. The typical example is converting “true” to a Boolean – true, or “3.1415” to a Number – 3.1415. This is accomplished using code reflection and the AS3Commons Reflect package. The class will inspect the Actionscript Class and use a set of rules to coerce string values into the native values of the properties on the Object.

Other issues are – when converting AS3 value objects back to XML – which is accomplished with a couple lines of code – all attributes and CDATA are persisted from the original parsed XML structure.

Also, it is easy to create and register your own custom converters using the converter registery. For instance, there is one “extended” converter which will encode a ByteArray inline in XML using Base64 encoding. (Great for sending images/thumbnails along with a service call)

Spread the word!! 🙂

Example project to jump in:
http://as3-commons.googlecode.com/files/AS3C_XMLSerializationExample.zip

Project Links:
http://code.google.com/p/as3-commons/
http://www.as3commons.org/

-Evan

Reply
Evan Gifford

Oh, and also check out our benchmarks of using this technique. I find it very fast!

Reply
Tink

“Can you explain why this solution might be slower? I don’t disagree, but are we talking long periods of time? Running this in my AIR app, I don’t see any lag.”

Just for clarification from the horses mouth…

http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c3a0f5f19124318fc87b-7ffc.html

“Avoid using the square bracket operator, when possible.

Using the square bracket operator can slow down performance. You can avoid using it by storing your reference in a local variable. The following code example demonstrates inefficient use of the square bracket operator:”

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *