Creating a distributed data application

A Flex client application uses a client-side DataService component to receive data from, and send data to, the server-side Data Management Service. Data travels to and from Data Management Service destinations over a protocol-specific message channel. A DataService component can fill a client-side ArrayCollection object with data and manage synchronization of the ArrayCollection object's data with the versions of data in other clients and on the server. You can create DataService components in MXML or ActionScript.

A DataService component requires a valid Data Management Service destination that you configure in the services-config.xml configuration file or a file that it includes by reference. For information about Data Management Service destinations, see Configuring the Data Management Service.

Subtopics

Creating a DataService component
Filling and releasing data from an ArrayCollection
Working with single data items
Connecting and disconnecting
About the DataStore object
Handling errors
Controlling whether clients receive pushed changes
Controlling pushed changes
Providing authorization information

Creating a DataService component

A DataService component manages the interaction with a server-side Data Management Service destination. You can create a DataService component in MXML or ActionScript.

The following example shows MXML code for creating a DataService component. The DataService component's destination property must reference a valid server-side Data Management Service destination.

<?xml version="1.0"?>
<!-- fds\datamanagement\DataServiceMXML.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:DataService id="ds" destination="contact"/>
</mx:Application>

The following example shows ActionScript code for creating the same DataService component:

<?xml version="1.0"?>
<!-- fds\datamanagement\DataServiceAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp();">
    <mx:Script>
        <![CDATA[
            import mx.data.DataService;
            public var ds:DataService;
            
            public function initApp():void {
                ds = new DataService("contact");
            }
        ]]>
    </mx:Script>
</mx:Application>

When you create a DataService component in ActionScript, you must import the mx.data.DataService class and declare a variable of type DataService, for which you set the value to a new DataService object.

Filling and releasing data from an ArrayCollection

When you call a DataService component's fill() method, you fill an ArrayCollection object with the data from a Data Management Service destination. You can create an ArrayCollection object in MXML or ActionScript. The ArrayCollection API provides a set of methods and properties for manipulating a set of data; for information, see Using Data Providers and Collections.

To release an ArrayCollection object that you filled, you call the DataService component's releaseCollection() method. If you call the fill() method again on the same ArrayCollection object with the same parameters, it fetches a fresh copy of the data. If you call the fill() method again with different parameters, it releases the first fill and then fetches the new one.

The first parameter of a fill() method is the id value of the ArrayCollection to fill. The values of any additional parameters depend on the type of server-side destination that you call.

For example, when you call a destination that uses the Java adapter with a custom assembler, the arguments following the id of the ArrayCollection could be the arguments of a corresponding server-side method that is declared in the destination. For a destination that uses the Hibernate object-relational mapping system, the arguments following the id of the ArrayCollection are Hibernate-specific values that depend on the Hibernate features that the destination is configured to use. The following example shows a fill() method for calling a Hibernate destination that uses the Hibernate Query Language (HQL):

myService.fill(myCollection, "flex:hql", ["from Person p where p.firstName = :firstName", parameterMap]);

For more information, see Configuring the Data Management Service.

The following example shows code for creating and filling an ArrayCollection object in MXML. The Application component's creationComplete event listener is set to the DataService component's fill() method, so the contacts ArrayCollection is filled when the application is loaded.

<?xml version="1.0"?>
<!-- fds\datamanagement\FillArrayCollectionMXML.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="ds.fill(contacts);">
    <mx:DataService id="ds" destination="contact"/>
    <mx:ArrayCollection id="contacts"/>
</mx:Application>

The following example shows code for creating and filling an ArrayCollection in ActionScript. The DataService component's fill() method is called in the initApp() method, which is specified as the Application component's creationComplete event listener.

<?xml version="1.0"?>
<!-- fds\datamanagement\FillArrayCollectionAS.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp();">
    <mx:Script>
        <![CDATA[
            import mx.data.DataService;
            import mx.collections.ArrayCollection;
            
            public var ds:DataService;

            [Bindable]
            public var contacts:ArrayCollection;
            
            public function initApp():void {
                contacts = new ArrayCollection();
                ds = new DataService("contact");
                ds.fill(contacts);  
            }
        ]]>
    </mx:Script>    
</mx:Application>

Populating a data provider control with distributed data

To populate a data provider control with distributed data, you can use data binding to bind a managed ArrayCollection object to the data provider control's dataProvider property. When you set the associated DataService component's autoCommit property to true, changes to data in the DataGrid are automatically sent to the Data Management Service destination.

The following example shows an ArrayCollection object that is bound to a DataGrid control's dataProvider property:

<?xml version="1.0"?>
<!-- fds\datamanagement\PopulateDataGrid.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="ds.fill(contacts);">
    <mx:DataService id="ds" destination="contact"/>
    <mx:ArrayCollection id="contacts"/>
    <mx:DataGrid id="dg" dataProvider="{contacts}" editable="true">
        <mx:columns>
            <mx:DataGridColumn dataField="contactId" headerText="Id"
                editable="false"/>
            <mx:DataGridColumn dataField="firstName" headerText="First Name"/>
            <mx:DataGridColumn dataField="lastName" headerText="Last Name"/>
        </mx:columns>
    </mx:DataGrid>
</mx:Application>

Sending changes from a managed ArrayCollection object

By default, a DataService component's commit() method is automatically called when data changes in the ArrayCollection object that it manages. You can also call the commit() method manually and set a DataService component's autoCommit property to false to allow only manual calls to the commit() method.

The following example shows a manual update operation on an item in an ArrayCollection object that is managed by DataService component:

<?xml version="1.0"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp();">

<mx:Script>

<![CDATA[

import mx.data.DataService;

import mx.collections.ArrayCollection;

import samples.customer.Customer;

...

public function initApp():void {

var customers:ArrayCollection = new ArrayCollection();

var customerService:DataService = new
DataService("customers");

customerService.autoCommit = false;

var customer:Customer = customers.getItemAt(4);

customer.name = "CyberTech Enterprises";

customerService.commit();

}

                    ...

]]>

</mx:Script>

</mx:Application>

The DataService component creates a single update message that includes the change to the customer.name property. This message is sent to the destination when the DataService component's commit() method is called.

The following example shows two manual update operations on an item in an ArrayCollection object that is managed by a DataService component:

...
var customer:Customer = customers.getItemAt(4); 
var oldName:String = customer.name;
customer.name = "CyberTech Enterprises"; 
customer.name = oldName;
customerService.commit();
...

The DataService component attempts to log two updates that cancel out each other. When the value of the customer.name property is changed to "CyberTech Enterprises", the DataService component creates a single update message. On the subsequent change back to the old name by using customer.name = oldName, the original update message for the customer's name is removed. The result is that nothing is sent when the commit() method is called.

The following example shows the addition and removal of a customer to an ArrayCollection object that is managed by DataService component.

<?xml version="1.0"?>
<!-- fds\datamanagement\AddRemoveItem.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="initApp();">
    <mx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.data.DataService;
            import samples.customer.Customer;           
            public function initApp():void {
                var customers:ArrayCollection = new ArrayCollection(); 
                var customerService:DataService = 
                  new DataService("customers");
                customerService.autoCommit = false;             
                customers.addItemAt(new Customer(), 4);
                // Remove the previously added customer.
                customers.removeItemAt(4); 
                customerService.commit();
            }
        ]]>
    </mx:Script>
</mx:Application>

The DataService component attempts to log two updates that cancel out each other. When the addItemAt() method is called, the DataService component creates a create message for the customers destination. On the subsequent call to removeItemAt(4), the previous create message is removed. Nothing is sent when the commit() method is called.

NOTE

 

Calling an ArrayCollection object's setItemAt(x) method is equivalent to calling the removeItemAt(x) method and then calling the addItemAt(..., x) method.

In all of the previous examples, the DataService component uses only the identity of the item specified to determine if a new update cancels pending updates. The following example also shows this type of behavior:

...
var customer:Customer = new Customer("1099"); 
customer.name = "CyberTech Enterprises";
// At location 4 in the list, a customer object with identity 1099 exists.
customers.setItemAt(customer, 4);
customerService.commit();
...

In this example, the DataService component does not send any changes to the server even though a new Customer object is created and the value of its name property is changed.

Working with single data items

The mx.data.DataService class has several methods for working with individual data items. The following table describes these methods:

Method

Description

createItem()

Lets you create a new data item without working with an ArrayCollection. An example of when this method is useful is a call center application where a customer fills in a form to create a single ticket item. In contrast, call center employees would have to see all the ticket items, so their application would fill an ArrayCollection with data items.

getItem()

Lets you get a single data item from the item's identity. An example of when this method is useful is in a master-detail relationship, such as the relationship between an order and order items.

When you click on one of the order items in a DataGrid, you want to go back out to another destination and get a complete item that includes several more properties from another destination. This would let you bring a minimal amount of data for the order into the initial ArrayCollection and only get complete items on an individual basis when needed.

deleteItem()

Deletes an item which is managed using a createItem(), getItem(), or fill() method call. The delete is sent to the server as soon as the transaction is committed.

releaseItem()

Releases an item from management. This method should be called for each getItem() or createItem() call that you are finished with to prevent a memory leak on the client (and the server if autoSyncEnabled is set to true).

The following example shows a method that gets a specific data item when a DataGrid control changes. You get the item from the ResultEvent.result event. The identity value sent to the destination is companyId, which is set to the companyId of the currently selected item in the DataGrid control. The destination retrieves items based on their identity, which is specified in the destination definition in the configuration file.

    <mx:Script>
        <![CDATA[
...
            private function companyChange() {
                dsCompany.getItem({companyId: dg.selectedItem.companyId});        
            }
        ]]>
    </mx:Script>
...

Connecting and disconnecting

A DataService component starts out disconnected from its server-side destination. The first time you perform an operation, the DataService component tries to connect to the destination. If the operation succeeds, a result event is sent to the DataService component. If the operation fails, a fault event is sent. You can call the DataService.disconnect() method to force a connected client to disconnect; in this case, the DataService component keeps a copy of its managed data and automatically resubscribes to pick up changes when you reconnect.

You can also call DataService.release() method to release all managed objects fetched by a DataService component.

About the DataStore object

The Data Management Service keeps outgoing and incoming data changes in an object called DataStore, which can be shared by more than one DataService component. By default, two DataService components share the same DataStore object when there are associations between them or you manually set one DataService component's dataStore property to refer to the DataStore object of another DataService component.

When you call a DataService component's commit() method, it commits all of the changes for the DataStore object, which includes the changes for all DataService components that share that DataStore object. Similarly, when you change one DataService component's autoCommit property, the value is changed for all DataServices components that share the same DataStore object.

Handling errors

The DataService component dispatches fault events for errors that occur when processing an operation. This includes errors that occur when connecting to the server, as well as errors that are sent by an assembler class in response to processing an operation.

For more information, see the documentation for the mx.data.errors package in the Adobe Flex 2 Language Reference.

A DataService component automatically connects to a ChannelSet when it performs its first operation. When errors occur in your clients when processing a commit() request, the changes in the commit are put back into the uncommitted changes. You can choose to revert those changes by calling the DataService component's revertChanges() method with an item argument, or you can the revertChanges() method with no argument to revert all changes.

Controlling whether clients receive pushed changes

By default, the Data Management Service detects data changes made from Flex clients and the server push API and propagates those changes to other clients. You can change this default behavior for a specific destination by setting auto-sync-enabled to false in the destination configuration.

To turn on the auto-sync behavior for a specific ArrayCollection on the client side, set the DataService component's autoSyncEnabled property to true before you call its fill() method. Similarly, to retrieve a managed item from an individual reference, you set the DataService component's autoSyncEnabled property to true before you call its getItem() or createItem() method.

Changing the value of the autoSyncEnabled property does not affect existing managed objects on that client. It only affects fill(), getItem() and createItem() method calls you make after changing the value. This lets you to have managed instances with the autoSyncEnabled property set to true and others with the autoSyncEnabled property set to false from the same destination in the same client.

Controlling pushed changes

By default, when a client detects changes, the changes are immediately applied to the Data Management Service. You can turn this off for a given destination by setting a DataService component's autoMerge property to false. When pending changes come in, the mergeRequired property is set to true on the DataStore object. To merge the pending changes, you call the DataService.dataStore.merge() method. To avoid conflicts, you should merge changes before you modify any data locally on the client.

NOTE

 

A client does not make page requests while there are unmerged updates if a DataService component's autoMerge property is set to false, paging is enabled, and the page size is a non-zero value. You can test for this case by checking the value of the mergeRequired property of the DataService component or its associated DataStore object.

Providing authorization information

The DataService component's setCredentials() method lets you provide authorization information required by server-side security constraints. The logout() method removes those credentials. For more information on providing authorization information, see Securing destinations.


Flex 2.01

Take a survey