Add application code to check for and recover from from SAP Mobile Server failures.
It is highly recommended that you add a catch call to all synchronize methods (synchronize(), begingSynchronize(), and so on) within your applications to allow the application to recover if SAP Mobile Server fails and needs to be restored from an older database. If not, you may have to reinstall the application manually for all users so they can resynchronize with SAP Mobile Server.
See Restoring from an Older Backup Database File (Data Loss) in the System Administration Guide for information about SAP Mobile Server recovery.
public class MyApplicationCallback : Sybase.Mobile.DefaultApplicationCallback { bool callFlag = false; public override void OnConnectionStatusChanged(int connectionStatus, int errorCode, string errorMessage) { //Error 580 indicates that the application appears registered to the device but // not in the server. If true, the application reregisters with the server if (errorCode == 580 && callFlag) { callFlag = true; Thread registerThread = new Thread(new ThreadStart(reregister)); registerThread.Name = "reregister"; registerThread.Start(); } } private void reregister() { System.Console.WriteLine("RegisterApplication..."); Application.GetInstance().RegisterApplication(); System.Console.WriteLine("RegisterApplication done"); } }
public class MyApplicationCallback : Sybase.Mobile.DefaultApplicationCallback { bool callFlag = false; public override void OnConnectionStatusChanged(int connectionStatus, int er rorCode, string errorMessage) { //Error 580 indicates that the application appears registered to the device but // not in the server. If true, the application reregisters with the server if (errorCode == 580 && !callFlag) { System.Console.WriteLine("OnConnectionStatusChanged: got errorCode580"); callFlag = true; Thread registerThread = new Thread(new ThreadStart(reregister)); registerThread.Name = "reregister"; registerThread.Start(); } } private void reregister() { System.Console.WriteLine("RegisterApplication..."); Application APP1 = Application.GetInstance(); APP1.ApplicationCallback = new MyApplicationCallback(); ConnectionProfile cp = MyDatabase.GetSynchronizationProfile(); cp.AsyncReplay = false; cp.EnableTrace(false); cp.Save(); MyDatabase.SetApplication(APP1); Console.WriteLine("####SetApplication OK..."); ConnectionProperties props = APP1.ConnectionProperties; props.ServerName = Host; props.PortNumber = Port; LoginCredentials login = new LoginCredentials(Username, Credential); props.LoginCredentials = login; Console.WriteLine("####RegisterApplication..."); Application.GetInstance().RegisterApplication(); while (APP1.ConnectionStatus != ConnectionStatus.CONNECTED) { Thread.Sleep(1000); Console.WriteLine("Wait for connected, sleep 1 second"); } System.Console.WriteLine("RegisterApplication done"); } }
catch (Exception ex) { if (ex is Sybase.Persistence.SynchronizeException) { Sybase.Persistence.SynchronizeException syncException = (Sybase.Persistence.SynchronizeException)ex; //If an error during sycnhronization is encountered close the connection, //address the exception, delete the client database, reregister/subscribe/resync if (syncException.ErrorCode == Sybase.Persistence.SynchronizeException.SQLE_UPLOAD_FAILED_AT_SERVER) { TestDB.CloseConnection(); TestDB.DeleteDatabase(); System.Console.WriteLine("Sync again"); TestDB.RegisterCallbackHandler(_ch); TestDB.Subscribe(); TestDB.Synchronize(); } } }
public void Synchronize() { try { Console.WriteLine("-- asynchronize --"); AsyncCallbackHandlerHARA callback = new AsyncCallbackHandlerHARA(); GenericList<ISynchronizationGroup> syncGroups = new GenericList<ISynchronizationGroup>(); syncGroups.Add(AsyncOpReplayDB.GetSynchronizationGroup("default")); callback.userContext = Environment.TickCount + ""; AsyncOpReplayDB.RegisterCallbackHandler(callback); AsyncOpReplayDB.BeginSynchronize(syncGroups, callback.userContext); Console.WriteLine("BeginSyncronize"); int waitCount = 0; while (!callback.asyncDone()) { if (waitCount++ > maxWaitTime) { break; } try { Thread.Sleep(1000); } catch (Exception e) { Console.WriteLine("exception=" + e.ToString()); } } if (callback.errorMessage != null) { Console.WriteLine("callback errorMessage=" + callback.errorMessage); throw new Exception(callback.errorMessage); } callback.userContext = null; Console.WriteLine("-- asynchronize done --"); } catch (Exception ex) { Console.WriteLine("Exception message is: {0}", ex.Message); } } } class AsyncCallbackHandlerHARA : DefaultCallbackHandler { private volatile bool asyncCompleted = false; private volatile bool asyncUploaded = false; public volatile String userContext = null; public volatile String errorMessage = null; public bool asyncDone() { return asyncCompleted; } public void RecoverClientDatabase() { System.Console.WriteLine("RecoverClientDatabase start"); AsyncOpReplayDB.CloseConnection(); AsyncOpReplayDB.DeleteDatabase(); AsyncOpReplayDB.CreateDatabase(); AsyncCallbackHandlerHARA callback = new AsyncCallbackHandlerHARA(); GenericList<ISynchronizationGroup> syncGroups = new GenericList<ISynchronizationGroup>(); syncGroups.Add(AsyncOpReplayDB.GetSynchronizationGroup("default")); callback.userContext = Environment.TickCount + ""; AsyncOpReplayDB.RegisterCallbackHandler(callback); AsyncOpReplayDB.BeginSynchronize(syncGroups, callback.userContext); System.Console.WriteLine("RecoverClientDatabase done"); } public override SynchronizationAction OnSynchronize (GenericList<ISynchronizationGroup> groups, Sybase.Persistence.SynchronizationContext context) { Console.WriteLine("-- AsyncCallbackHandlerHARA OnSynchronize --"); Exception ex = context.Exception; if (ex is Sybase.Persistence.SynchronizeException) { Sybase.Persistence.SynchronizeException syncException = (Sybase.Persistence.SynchronizeException)ex; if (syncException.ErrorCode == Sybase.Persistence.SynchronizeException.SQLE_UPLOAD_FAILED_AT_SERVER) { RecoverClientDatabase(); } } ... return SynchronizationAction.CONTINUE; } }
Public void sync() { … _rh = new TextResponseHandler(); MyDatabase.RegisterCallbackHandler(_rh); oqe.Create(); MyDatabase.SubmitPendingOperations(); //at this point, server is restored to the state client registered and did not subscribe //client wake up and new operations if (APP.ConnectionStatus != ConnectionStatus.CONNECTED) { APP.StartConnection(100); Thread.Sleep(2000); } if(MyDatabase.IsSubscribed()) { MyDatabase.Unsubscribe(); // waiting for dowload data complete _rh.WaitForMessage("UnsubscribeFailure", "UnsubscribeSuccess"); System.Console.WriteLine("Unsubscribe is called"); MyDatabase.Subscribe(); System.Console.WriteLine("Subscribe is called"); _rh.WaitForMessage("SubscribeSuccess"); } oqe = new ASADataTypesOQE(); … }
oqe.Create(); MyDatabase.SubmitPendingOperations(); lst = ASADataTypesOQE.FindAll(); Console.WriteLine("ASADataTypesOQE has records: " + lst.Size()); foreach (ASADataTypesOQE itm in lst) { Console.WriteLine("ID: " + itm.Id + " | Name: " + itm.Ctext); } //at this point, server is restored to the state client registered and subscribed //client wake up and new operations if (!MyDatabase.IsSubscribed()) { MyDatabase.Subscribe(); //waiting for dowload data complete _rh.WaitForMessage("ImportSuccess"); }