Skip to content

Synchronizing Data

An offline application uses an offline store (on-device copy of the back-end data) to ensure that data is always accessible, even when the device is offline.

You can make changes to the offline store, then synchronize with the back end. The offline store needs to synchronize with the back end from time to time to ensure correctness, completeness and accuracy of data.

Download (Updating the Offline Store)

The offline store is updated with latest data from the back end when the device is online by performing a download. The timing of performing download is at the discretion of the application developer. For example, depending on the application:

  • Give the application user control over the timing of the download
  • Download at the beginning and end of the day
  • Download when the application opens
  • Download every 15 minutes
  • Download after every upload

Because it might run for a long time, you can invoke a download process only asynchronously, and such a process usually runs in background.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Download can only be called asynchronously.
// The first parameter is the success handler and the second 
// parameter is the failure handler with exception encountered
// as the parameter
offlineODataProvider.download(
    () -> {
        // Proceed to use the offline store after download is successfully completed,
        // for example notifying UI for appropriate action
        ...
    },
    (error) -> {
        // Handle the error, for example logging the error or retrying download
        ...
    }
);

Upload (Updating the Back End)

An application can make changes to the local offline store with OData requests, which are stored in a request queue. Changes made by requests that are queued but have not yet been sent to the back end are reflected in the offline store.

An upload can be performed when a device is online, which sends requests executed against the offline store to the back end.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Upload can only be called asynchronously.
// The first parameter is the success handler and the second
// parameter is the failure handler with exception encountered
// as the parameter
offlineODataProvider.upload(
    () -> {
        // Proceed to use the offline store after upload is successfully completed,
        // for example notifying UI for appropriate action
        ...
    },
    (error) -> {
        // Handle the error, for exapmle examining ErrorArchive for requests that failed.
        ...
    }
);

The failure handler is invoked only if there are communication errors during upload. The upload is treated as successfully completed if there aren't any communication errors, although some requests may fail by the back end. To determine whether any requests have failed, you can examine the ErrorArchive. In addition, implement a callback delegate by subclassing the abstract class OfflineODataDelegate. The callback method updateFailedRequest() is invoked once for every failed request. This callback delegate can be passed in as a parameter to an OfflineODataProvider instance.

Note

Local entities are not updated during an upload, and you can perform multiple upload operations without calling a download. It is a good practice (although not required) to perform an upload before a download to make sure that local changes are pushed to the back end.

Cancelling Synchronization

You can use cancelUpload() and cancelDownload() to cancel a data synchronization (upload/download) operation and retry at a later time, for example, if there are network bandwidth issues or other reasons that the current synchronization might fail.

Schema Upgrades

During download, a schema upgrade of the offline store if performed if change of back-end OData service metadata is detected.

Metadata changes are generally expected to be additive, meaning the OData model is altered by adding entity types or properties, but not by removing entity types or properties. This lets you successfully replay the operations in the request queue on the new schema. If the changes to OData model are not additive, then a new application compatible with the new model would need to be deployed.

Background Updates

Background updates are possible but require the application developer to ensure that upload and download operations are called in a manner that enables them to continue in the background.

Remove Entities After Upload

Offline applications sometimes require the ability to create entities or media streams that can be removed from the device once they have been successfully uploaded to the back end. A common scenario here is if a user has the permission to create entities that won't necessarily be assigned to him or her. This can be achieved by passing in an OfflineODataRequestOptions instance with removeCreatedEntityAfterUpload set to true when creating an entity or media stream.

Note

Before the create request is uploaded, subsequent operations can be performed on the entity or media stream created with the removeCreatedEntityAfterUpload option, including requests to directly modify the entity or media stream or requests to reference it (create a relationship to it).

After the entity or media stream has been successfully uploaded, subsequent requests on the entity or media stream are not permitted (since the entity or media stream has been removed). In this case, a 404 Not Found error is returned since the entity or media stream is not in the offline store.

Remember

  • Relationships to entity or media stream created with the removeCreatedEntityAfterUpload option -– Any relationships created to or from entities or media streams created with the removeCreatedEntityAfterUpload option are automatically removed from the offline store when the entity or media stream is removed.
  • Errors during upload –- The entity or media stream created with the removeCreatedEntityAfterUpload option remains on the device if the POST request fails, or if any request that references the entity or media stream fails.

Sample Code

The following example illustrates how to create a new entity that should be removed after upload.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Declare a new event
Event event = new Event(false);

// Set properties for the event
...

// Set offline specific request options
OfflineODataRequestOptions options = new OfflineODataRequestOptions();
options.setRemoveCreatedEntityAfterUpload(true);

// Create the event with the given options
eventService.createEntity(event, HttpHeaders.empty, options);