Blog to discuss Midnight Coders products features, ideas and trends in development of Rich Internet Applications

Monday, February 05, 2007

Let's talk about Flex Data Management...

We have been very busy working on a very cool and exciting subsystem for WebORB. The new module is our own implementation of the Data Management Services functionality from FDS. We already implement a subset of Flex Data Management Services, but decided to create an alternative. The new implementation is very different and, in my opinion, friendlier and easier to use from a developer perspective. Before I delve into the new data management system, let's review how FDMS works. Since WebORB already implements a subset of FDMS, the overview below applies to both WebORB and FDS unless noted otherwise.

One of the core concepts in FDMS (and the same is true with Remoting and Messaging) is the destination. A data destination represents a collection of operations applied to a data entity. A data destination is configured in WEB-INF/flex/data-management-config.xml and encapsulates a lot of important information:
  1. Server-side class responsible for processing data fetching (fill) and data synchronization (create, update, delete) operations. The class deals with value objects representing destination's entity.
  2. Identity description. Provides a definition of the entity properties representing entity's identity.
  3. Association information. Destination's entity may be correlated to other entities. This configures the relations and cardinality. (Note: this applies only to FDS, WebORB's FDMS implementation does not support associations).
  4. Paging configuration. Specifies if the data returned by (1) is pageable and configures page size.
  5. Data management function declarations for (1). This is an optional configuration item. If (1) does not implement a particular interface, fill and sync methods must be declared in the destination.
Below is a sample data destination definition taken from the WebORB distribution:

<destination id="contact">
<adapter ref="dotnet-dao" />
<properties>
<source> Weborb.Examples.DataManagement.ContactAssembler </source>
<scope>application</scope>

<metadata>
<identity property="contactId"/>
</metadata>

<network>
<session-timeout>20</session-timeout>
<paging enabled="true" pageSize="2" />
<throttle-inbound policy="ERROR" max-frequency="500"/>
<throttle-outbound policy="REPLACE" max-frequency="500"/>
</network>

<server>
<fill-method>
<name>loadContacts</name>
</fill-method>

<fill-method>
<name>loadContacts</name>
<params>System.String</params>
</fill-method>

<sync-method>
<name>syncContacts</name>
</sync-method>
</server>
</properties>
</destination>


Configuration shown above defines the "contact" destination. The destination is mapped to the Weborb.Examples.DataManagement.ContactAssembler class. The class contains the loadContacts and syncContacts methods responsible for loading data from the server and performing data updates (see the source code below):

[ReturnType( "samples.contact.Contact" ) ]
public object
loadContacts()
{
ContactDAO dao = new ContactDAO();
return dao.getContacts();
}

public void
syncContacts( ChangeObject change )
{
if( change.IsUpdate )
doUpdate( change );
else if( change.IsCreate )
doCreate( change );
else if( change.IsDelete )
doDelete( change );
}

private void doUpdate( ChangeObject co )
{
ContactDAO dao = new ContactDAO();
dao.update( (Contact) co.NewVersion, (Contact) co.OldVersion );
}

private void doCreate( ChangeObject co )
{
ContactDAO dao = new ContactDAO();
Contact contact = dao.create( (Contact) co.NewVersion );
co.NewVersion = contact;
}

private void doDelete( ChangeObject co )
{
ContactDAO dao = new ContactDAO();
dao.delete( (Contact) co.OldVersion );
}

As you can see from the code above, all top level functions exposed through the destination delegate to a Data Access Object (DAO) class. The DAO class is the one that implements the actual database integration, includes all the queries and connection management. It is also responsible for entity object materialization and serialization.

The diagram below shows the relationship between the entity class (Contact), DAO class (ContactDAO) and the class exposed through the data destination:



Now that you have an idea of what's going on on the server, let's review the client-side:

The key component on the client is the mx.data.DataService class. The class does not come with the Flex SDK and is available only with the FDS distribution. To connect to a data destination create a DataService instance as shown below:
// connect to the "contact" data destination
var ds:DataService = new DataService( "contact" );
The client side uses ActionScript counter part to the server's Contact class. When the server code returns a Contact object, it is mapped to a client-side representation of the same value object.

To retrieve a list of contacts from the server, use the fill() method:
ds.fill( myCollection );
The method call above populates the myCollection object (which must be an instance of mx.collections.ListCollectionView) with a collection of contact objects returned from the server's loadContacts() method shown above.

To create a new contact record, instantiate the client-side Contact class, populate it with data and then invoke DataService's createItem as shown below:
var myContact:Contact = new Contact();
myContact.name = "James Bond";
myContact.phone = "5551212";
ds.createItem( myContact );
To delete an existing contact use the deleteItem method();
ds.deleteItem( myContact );
The DataService API is quite rich and offers a lot of possibilities. You can see the API documentation here.

This should give you a high level overview of the Flex Data Management Services. In the next post, I will describe the issues with the FDMS approach and the reasons for creating an alternative implementation in WebORB.

0 Comments:

Post a Comment

<< Home