Using the AIR SyncManager class to manage data

The AIR application uses the SyncManager class to fetch data from the server and synchronize the local data with the ColdFusion data source. The SyncManager uses a coldfusion.air.Session object to manage the session between the client and the local SQLite database, and uses calls to the following methods in the ColdFusion sync manager CFC:

  • fetch to get data from the remote system
  • sync to synchronize the local and remote data
    The following text describes basic functionality that you must implement. For details on the SyncManager and Session classes, and other classes in the coldfusion.air package, see ActionScript 3.0 Reference. Alternatively, you can see the standalone Adobe ColdFusion ActionScript Language Reference, which is accessible through the Documentation link on the Resources page of the ColdFusion Administrator.
    The AIR application init() function creates and configures a SyncManager instance, and fetches the initial data from ColdFusion as shown in the following code:

private function init():void
{
syncmanager = new SyncManager();
//The ColdFusion server and port. Port without double quotes as it is

//expected to be integer and IP is taken as String.
syncmanager.cfPort = CFServerPort;
syncmanager.cfServer = "CFServerIP";

//The CFC that implements the ColdFusion sync manager. Here
//AIRIntegration is the user defined folder under webroot.
syncmanager.syncCFC = "AIRIntegration.empManager";

//Specify a user-defined CF destination,if not specified, default destination
//'ColdFusion' will be used
syncmanager.destination = 'USerDefinedCFDestination'

//The event listener for conflict events returned byt the CFC
syncmanager.addEventListener(ConflictEvent.CONFLICT, conflictHandler);

//The local database file
var dbFile:File = File.userDirectory.resolvePath("EmpManager.db");

//Create a session object, which handles all interactions between the
//AIR application and the SQLite database.
var sessiontoken:SessionToken = syncmanager.openSession(dbFile, 999);

//Add a responder for handling session connection results.
sessiontoken.addResponder(new mx.rpc.Responder(connectSuccess,
connectFault));
}

Fetching data from the server

Use the SyncManager fetch method to fetch data from the ColdFusion server by calling the fetch method of the server data object. The syncManager.fetch method takes the name of the CFC fetch method (typically fetch) as its first parameter, followed by any CFC fetch method parameters.
The syncManager.fetch method returns an AsyncToken object that provides access to the data. The function returns the token synchronously. The ColdFusion CFC response returns asynchronously. Therefore, call the token's addResponder method to specify a responder that handles the responses for successful and failed fetches. 
To fetch the initial data from the server, you can include the following code in the Application init() method.

// fetch the data.
var token:AsyncToken = syncmanager.fetch("fetch");
//Specify the responder to handle the fetch results.
token.addResponder(new mx.rpc.Responder(fetchSuccess, fetchFault));

Managing the local database

You use a Session object to manage the data in the local SQLite database. You call the syncmanager.openSession method to create a session with a specific database file. The method returns a SessionToken token, and the SessionToken.session property provides access to the session. You use code in the token's openSessionSuccess responder event handler to provide access to the session object. This way, you do not access the session, and therefore the database, until it is successfully opened. 
The following code expands on the session initialization code that was shown above. and shows an openSessionSuccess event handler that uses the session to save the contents of the remote database in the local image. In this example, users is the array collection fetched from server:

var dbFile:File = File.userDirectory.resolvePath("basic.db");
var token:SessionToken = syncmanager.openSession(dbFile, 113);
token.addResponder(new mx.rpc.Responder(openSessionSuccess, openSessionFault));
function openSessionSuccess(event:SessionResultEvent):void
{
//Initialize a variable for access to the session.
var session:Session = event.sessionToken.session;
//Save the remote database data in the local database.
//users is the array collection fetched from server
var saveToken:SessionToken = session.saveCache(users);
//Add responder event handlers for successful and failed saves.
saveToken.addResponder(new mx.rpc.Responder(saveSuccess, saveFault));
}

If Begintransaction() function doesnt have a corresponding Committransaction() function, then the AIR side SQLite DB file is locked. To avoid this, use the following code at the end of an event flow.

var closetoken:SessionToken = session.close();
closetoken.addResponder(new mx.rpc.Responder(closesuccess, closefault));

Once you have access to the session, you can get (load) data from the SQLite database, and insert, delete, and update data database by calling the session objects methods. For details on the session object methods, see ActionScript 3.0 Reference. Alternatively, you can see the standalone Adobe ColdFusion ActionScript Language Reference, which is accessible through the Documentation link on the Resources page of the ColdFusion Administrator.

Notes:
  • The SQLite database doesn't validate column types when it creates a table. If you give it an invalid value for column data type, it creates the column with that type.
  • When you pass a unique integer ID parameter (one that is not used in the application) to the OpenSession method, the method creates an intermediate database file, which tracks the client changes to be committed on the server. If you use more than one database in a single application, use a unique ID for each database. Using a single ID ensures that you use the correct database for each client-side transaction.
  • For asynchronous calls (such as SaveCache) that save fetched data in the local database, the call result can be available by using the session token when the call returns, before the responders are added. This situation occurs if the SaveCache operation tries to save null data. That is, if the fetch operation returned null data. In such cases, a responder is not required. There are two ways to handle this situation:
  1. Check whether the result property of the session token returned by the function is null:

    if (token.result == null) {
    Add the responder here
    }
    else {
    Directly use the token.result
    }

  2. Check that the ArrayCollection that is input to the SaveCache function is not null. The null response indicates that the fetch operation did not get a result from the server:

    If (ArrayCollection != null) {
    Call SaveCache() function
    Add Responder to the SaveCache Token
    }
    else {
    Handle the condition here.
    }

  • If you call the SaveUpdate Method and a record with the specified primary key doesn't exist, the function inserts the record. The method updates an existing record only if the primary key exists in the client database.
  • After you fetch data from the server, use only the SaveCache and SaveCacheUpdate methods to save the fetched data into client side database. If you use the Save function to store the fetched data, the data is marked for insert on server on commit, and the data you just got is written back to the server. In this case, a conflict occurs for the server database primary key. If the server-side logic handles this conflict by ignoring the primary key ID from the client, and lets the server generate a new ID, then the records are inserted, resulting in multiple copies of the data with different IDs.
  • For AIR integration offline support, if you do not globally declare the variables for client side ActionScript classes but attempt to save the data records fetched from server using session.saveCache() or session.saveUpdateCache(), you might encounter AIR side error stackstrace with a message similar to the following:

    "Error: The object of type Object does not have the Entity metadata tag at coldfusion.air::EntityCache/addMetadata()[D:\p4\depot\ColdFusion\cf_main\tools\AIRIntegration\OfflineSupport\src\coldfusion\air\EntityCache.as:228]"

     

Sending data to the server

The client SyncManager object tracks all the changes to the local data that happens through the session, so that the local data and server data can be synchronized. The SyncManager also tracks the old data instances when data that is already on the server is updated locally.
When the AIR application calls the Session.commit method, all changes that happened on the session are passed to the CFC sync function. The sync function determines if there are any conflicts between the returned information. If there are no conflicts, it updates the server data source. Otherwise, it handles the data as described in Conflict management.

Note: When you call the session.commit method, if the server does not throw an error, the commit method dispatches a CommitSucces event. This event indicates that the session.commit method has executed successfully, and the client data has been handed to the server CFC sync method. (If an error occurs while sending data to the sync method, the client receives a CommitFault event.) Therefore, the CommitSucces event does not mean that the server has saved the client data, but only that it has received the data. For example, the server does not save the data if there is a conflict, but the CommitSucces event is still dispatched. You handle conflicts separately by adding an event listener on the SyncManager. The event Flow is the first to get the CommitSucces event, and then a ConflictEvent event.

Setting Remote Credentials for SyncManager

To authenticate the AIR client that is connecting to the ColdFusion server, you can send the remoting credentials, which can be used on the server side under the <cflogin> tag. This is the same as setting the remoting credential for a normal flash remoting object. 
The following code contains the getRemoteObject() method in SyncManager, which gets the underlying flash remoting object, so that you have full and same control over this as a normal flash remoting object.

syncmanager.getRemoteObject().SetRemoteCredentials("username","password");

Get help faster and easier

New user?