Handling data synchronization conflicts

When working with distributed data applications, there are often times when clients try to make data changes that conflict with changes that were already made. The following scenarios are core cases where data synchronization conflicts occur:

Conflict type

Description

Update with stale data

The server detects a conflict when a client commits changes because the data has changed since the client received the data.

Client is pushed changes when it has uncommitted conflicting changes

The client is in the midst of changing the data which conflicts with changes pushed to it from the server.

Delete with stale data

Server detects a conflict when the client tries to delete an item with a stale version of that object.

Client is pushed changes to an item is has deleted locally

A client has an uncommitted request to delete data when an update has just occurred to the same data, and a data message has been pushed to the client from the server.

Update to deleted data without client push

A client tries to update data that has already been deleted from the server.

Update to deleted date with client push

A client tries to update data that has already been deleted, and a data message has been pushed to the client from server. The client tries to send the update, but there is a conflict on client.

The following example shows a simple event handler that displays an Alert box on the client where a conflict occurs, and accepts the server version of the data:

...
public function useDS:void {
...

    ds.addEventListener(DataConflictEvent.CONFLICT, conflictHandler);        
...
}

public function conflictHandler(event:DataConflictEvent):void {
    var conflicts:Conflicts = ds.conflicts;
    var c:Conflict;
    for (var i:int=0; i<conflicts.length; i++) {
        c = Conflict(conflicts.getItemAt(i));
        Alert.show("Reverting to server value", "Conflict");
        c.acceptServer();
    }
}

For more information about the mx.data.Conflicts and mx.data.Conflict, and mx.data.events.DataConflictEvent classes, see the Adobe Flex 2 Language Reference.

When you use the Java adapter in your destination, you write a sync method in your assembler class that handles data synchronization and throws a DataSyncException if the previous version of the data does not match what is currently in the data resource. A DataSyncException results in a DataConflictEvent on the client. For more information about sync methods, see Using the fill-method and sync-method approach.

You can also let the user decide which version of data gets used when a conflict occurs, as the following code snippets show. PersonForm represents a custom component that displays all of the properties of the Person object assigned to its dataSource property.

// Conflict event handler:
function resolveConflictsHandler():void {
displayConflictsScreen();
}
...
<!-- Conflicts screen MXML code: -->
<PersonForm id="serverValue" editable="false" dataSource="{ds.conflicts.current.serverObject}"/> 

<PersonForm id="clientValue" dataSource="{ds.conflicts.current.clientObject}"/>

<PersonForm id="originalValue" dataSource="{ds.conflicts.current.originalObject}" editable="false"/>

<mx:Button label="Accept Server" click="ds.conflicts.current.acceptServer" />
<mx:Button label="Accept Client" click="ds.conflicts.current.acceptClient" />
...

Flex 2.01

Take a survey