Home  >  

Example of Flex 3 and ColdFusion 9 ORM (2)

Author photo
AddThis Social Bookmark Button
In my previous blog entry I demonstrated how easy it was to mix ColdFusion 9's new ORM features with a fancy (ok, simple) Flex front end. I left off the application in a rather simplistic state. On the server side, I had designed a ColdFusion CFC to interface with the Art table. On the client side, Flex used a simple datagrid and Flash Remoting to fetch the data via a service component. Our data model was just a set of properties, string and numeric based, and nothing more. In this entry, I'm going to demonstrate how we can being to work with slightly more complex data. I'll demonstrate how to work with related data in our Art table and how Flex can handle this more complex result.

Let's begin by looking at the Art entity again:

component persistent="true" {
  	property name="id" fieldtype="id" column="artid" ormtype="integer" generator="native";
  
  	property name="name" column="artname" ormtype="string";
  	property name="description" ormtype="string";
  	property name="price" ormtype="float";
  	property name="largeimage" ormtype="string";
  	property name="mediaid" ormtype="integer";
  	property name="issold" ormtype="integer";
  
}

For the most part, the properties of the Art entity are simple, but notice the mediaid property. This is actually a pointer to another table, Media. How difficult would it be to set up our entity to define this relationship? Let's begin by creating an entity for media. This table is incredibly small - it has a primary key and a mediatype column that represents the name of the media. Here is the ColdFusion Component I used to define the entity:

component persistent="true" {
 	property name="id" fieldtype="id" column="mediaid" ormtype="integer" generator="native";
 	property name="type" column="mediatype" ormtype="string";
}

Notice that I've aliased the mediatype column to just media. Why? Purely personal reasons. I don't think "Media.MediaType" makes sense to me. "Media.Type" just feels tighter. So we've got a Media entity. This by itself is enough for ColdFusion 9 and ORM to map to the table. But how do we link up our Art objects to their respective Media? All we need to do is change the media property:

property name="media" fieldType="many-to-one" cfc="media" fkcolumn="mediaid" remotingFetch="true" missingrowignored="true";

As I said in the previous entry, I don't want to cover every little bit of ORM details when the docs do a good job of it already, but at a high level, what this property now says is....

First, this is a relationship, not a column.

Second, the relation is many-to-one, which means there are many of this thing compared to one of the other. Or to be more specific, there are many art objects linked to one media.

Third - we tell ColdFusion which entity our relationship links to. In this case, it's the Media component we just made.

Fourth - we need to explain which foreign key (column) within the art table links us to media. That's done with the fkcolumn attribute.

Let's skip remotingFetch for now. The final argument, missingrowignored, simply handles the fact that some art objects don't have a value for media.

The end result is that we can now ask for an art object and ORM will handle getting a related media object. No SQL - no mess. Nice and simple.

So now let's head back to the Flex side. Previously our datagrid wasn't fleshed out at all. For my first change I'm going to add specific datagrid columns. I'll use this to specify headers for my data and provide a way to handle using my new media data.

<mx:DataGrid id="artGrid">
	<mx:columns>
		<mx:DataGridColumn headerText="Name" dataField="name" />
		<mx:DataGridColumn headerText="Media" labelFunction="doMediaLabel" />
		<mx:DataGridColumn headerText="Description" dataField="description" />
		<mx:DataGridColumn headerText="Price" dataField="price" />		
		<mx:DataGridColumn headerText="Sold" labelFunction="doSoldLabel" />
	</mx:columns>
</mx:DataGrid>	

</mx:Application>

I've specified that for my Media and Sold columns, I will use a label function to handle the display. The doSoldLabel function is just a quick check on the boolean value:

private function doSoldLabel(item:Object,column:DataGridColumn):String {
 	if(item.issold == 1) return "Yes"
 	else return "No"
}

Yep, I know I could write that even shorter, but I like keeping this readable when I'm working on a project. But what about media? By default my ORM data is returned an array of objects. When I specified that art had a related entity, media, by default it actually gets stripped off when returned. This is a good thing. Because entities could have quite a few relationships, by default they won't be returned over Flash Remoting. I have to specifically ask for the relationship to be returned. That's where my remotingFetch="true" comes into play. While this works for our simple example, be aware that this could cause quite a bit of data retrieval in more complex situations. In my case, my relationship is one way. I've said that art has media, but not that media has art. I may add that relationship later on. If I do, I'll have to rethink how I return the data.

With that said - because I've specified that media can be retuned over remoting, I have access to it in the rest of my data as a simple value. My doMediaLabel function can simply be:

private function doMediaLabel(item:Object,column:DataGridColumn):String {
 	return item.media ? item.media.type : "";
}

And... that's it. My front end now correctly shows the related media data for my pieces of art. I've not shown you the artService component again because... it didn't change! I really just had to flesh out the definition at the ORM level and nothing more. Hopefully your getting an idea of how powerful ORM can be. Imagine if you were a Flex programming with minimal server side experience. As you can see so far - the code I've used is pretty simple. Even better - not a lick of SQL in site. On the Flex side the fact that my server is using ORM isn't evident at all.

I spent a few more minutes making the table a bit nicer (including rendering the image), and came up with the following:

Screen shot 2010-03-11 at 9.58.19 PM.png

Here is the final MXML for the view above. Any comments or suggestions are welcome. For the next entry we will take things a bit further.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="init()">

<mx:RemoteObject id="artService" destination="ColdFusion" source="ormtest.model.artservice">
	<mx:method name="getArt" result="getArtResult(event)" fault="generalFault(event)" />
</mx:RemoteObject>

<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;

private function init():void {
 	artService.getArt()
}		

private function getArtResult(resultEvt:ResultEvent):void {
 	artGrid.dataProvider = resultEvt.result
 	
}

private function generalFault(faultEvt:FaultEvent):void {
 	mx.controls.Alert.show('Fault event '+faultEvt.toString())
}

private function doMediaLabel(item:Object,column:DataGridColumn):String {
 	return item.media ? item.media.type : "";
}

private function doSoldLabel(item:Object,column:DataGridColumn):String {
 	if(item.issold == 1) return "Yes"
 	else return "No"
}

]]>
</mx:Script>

<mx:DataGrid id="artGrid">
	<mx:columns>
		<mx:DataGridColumn headerText="Name" dataField="name" />
		<mx:DataGridColumn headerText="Media" labelFunction="doMediaLabel" />
		<mx:DataGridColumn headerText="Description" dataField="description" />
		<mx:DataGridColumn headerText="Price" dataField="price" />		
		<mx:DataGridColumn headerText="Image" dataField="largeimage">
			<mx:itemRenderer>
			<mx:Component>
			<mx:Image source="{'/cfdocs/images/artgallery/'+data.largeimage}" width="200" height="100"/>
			</mx:Component>
			</mx:itemRenderer>
		</mx:DataGridColumn>
		<mx:DataGridColumn headerText="Sold" labelFunction="doSoldLabel" />
	</mx:columns>
</mx:DataGrid>	

</mx:Application>

Read more from Raymond Camden. Raymond Camden's Atom feed cfjedimaster on Twitter

Comments

6 Comments

CFer said:

Thanks for another helpful tutorial Ray.

I would be interested to see how you can detect whether an image exists or not with Flex so it doesn't show broken images for records I added.

Also - regarding the "remotingFetch" - I tried changing it to "False" and it still works - so I am not quite sure I got the point you made about it but I guess I need to dig into the docs.

Raymond Camden said:

1) It is definitely possible to handle broken images in Flex. I did it a while ago- unfortunately I tend to use Flex in spurts so I forget. ;) However, this gives me great ammo for a follow post, a 2.1 entry. Cool with you?

2) Now that is odd - I wonder if CF cached it though. Did you run it at ALL with the value to true? If so, run a quick ormReload and see if it still works.

Simon Lenoir said:

Hi Raymond,

Nice Post.

Could you please provide an example for editing a field directly in the datagrid, let's say change the art description, and send the modified art object back to CF ORM to be saved ?
________

Another more complex code I try to do is to get an object Artist (1 artist has many arts) with an array arts = something like this in Artist.cfc:

property name="arts" fieldtype="one-to-many" fkcolumn="art_id" cfc="art" remotingfetch="true";

Then get the entityLoadByPK("Artist",1)> to have one Artist with an array of his arts.

From this arts array I populate an editable DataGrid = something like:

And finally I would like to send the Artist object (not the art item inside the array) directly to CF to be smartly handled by ORM...

Thanks

Simon

Raymond Camden said:

Yes, I'd definitely like to show editing - in fact, it probably makes sense for the next step.

krlcafe said:

property name="arts" fieldtype="one-to-many" fkcolumn="art_id" cfc="art" remotingfetch="true"; indir

Bernd Marschner said:

Thanks for the explanations and tips for Flex 3 and ColdFusion. We used this in one of our recent projects for a Samsung mobile related site. The projects manager was a german and he always told us: "Ihr müsst die Bilder mit Flex richtig einbinden, damit die Samsung Handy Seite endlich fertig wird. Samsung Handys ohne Vertrag müssen gut auf der Seite aussehen, damit die Leute es auch kaufen und telefonieren können. Also müsste ihr Flex für unsere Seite verwenden"

Since he recommended Flex we checked back with some
Tutorials on Insideria and fixed the issues with images. Good that it is working now.

Leave a comment


Type the characters you see in the picture above.


Tag Cloud

Technical Speakers

Who is the best technical speaker you have seen?

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.