… In continuation from
part 1
Offline Interface
When building offline applications using Fiori Mobile, an interface file (offlineInterface.js) is added for ease of development. This file has wrapper methods for flush, refresh, sync (flush and refresh together), easy error handling and other utility functions.
Initialization
constructor |
Makes sure only one instance is present (Singleton) and initializes Application Endpoint and Default Store |
Input / Output |
Type |
Name |
Description |
parameter |
object |
oChildObject |
existing object, if created before |
parameter |
string |
sApplicationEndpoint |
service root |
parameter |
string |
sDefaultStore |
default offline store |
return |
object |
|
returns the offline interface object |
Offline Interface can be instantiated and used as follows:
var applicationep = this.getMetadata().getManifestEntry("sap.mobile").stores[0].serviceRoot;
var defaultstore = this.getMetadata().getManifestEntry("sap.mobile").stores[0].name;
var oOfflineInterface = new sap.smp.OfflineInterface (null, applicationep, defaultstore);
You can get the service root and default store name from manifest file as above and pass it to constructor to initiate. This initialization can be done in Component.js – init() function.
Sync, Flush & Refresh
sync() |
synchronizes the data between system and offline database for a given store. sync method combines the operations of flush and refresh methods. |
Input / Output |
Type |
Name |
Description |
parameter |
function |
fnCallbackSyncSuccess |
function to call after success of flush |
parameter |
function |
fnCallbackSyncError |
function to call after error in flush |
parameter |
string |
sStoreID |
ID of the offline store. If it is not passed, default store id is used. |
Example code:
//If the reference to OfflineInterface is there, then use it. If not, create new (OfflineInterface uses singleton pattern)
new sap.smp.OfflineInterface().sync(
function(error){
//show the error (business error, if present) on sync call back success
}, function(error) {
//show the error (technical error, if present) on sync call back failure
},
null //no need to pass if default store
);
flush() |
flushes the data from offline database to the system for a given store |
Input / Output |
Type |
Name |
Description |
parameter |
function |
fnCallbackSuccess |
callback function executed when the flush succeeds |
parameter |
function |
fnCallbackError |
callback function executed when the flush fails |
parameter |
string |
sStoreID |
ID of the offline store. If it is not passed, default store id is used. |
Example code:
//If the reference to OfflineInterface is there, then use it. If not, create new (OfflineInterface uses singleton pattern)
new sap.smp.OfflineInterface().flush(
function(error){
//show the error (business error, if present) on flush call back success
}, function(error) {
//show the error (technical error, if present) on flush call back failure
},
null //no need to pass if default store
);
refresh() |
refreshes the data from system to offline database for a given store |
Input / Output |
Type |
Name |
Description |
parameter |
function |
fnCallbackSuccess |
callback function executed when the refresh succeeds |
parameter |
function |
fnCallbackError |
callback function executed when the refresh fails |
parameter |
string |
sStoreID |
ID of the offline store. If it is not passed, default store id is used. |
parameter |
array |
aRefreshObjects |
[subset] - List of the names of the defining requests to refresh |
Example code:
//If the reference to OfflineInterface is there, then use it. If not, create new (OfflineInterface uses singleton pattern)
new sap.smp.OfflineInterface().refresh(
function(error){
//show the error (business error, if present) on refersh call back success
}, function(error) {
//show the error (technical error, if present) on refresh call back failure
},
null, //no need to pass if default store
null //if all the defining requests of a store needs to be refreshed
);
getLastFlush() |
returns the last flushed timestamp |
Input / Output |
Type |
Name |
Description |
return |
timestamp |
|
Date/Time of the last flush |
getLastRefresh() |
returns the last refreshed timestamp |
Input / Output |
Type |
Name |
Description |
return |
timestamp |
|
Date/Time of the last refresh |
Utility Functions
isDeviceOnline() |
Function to check if device is online
- While you can assume that the browser is offline when it returns a false value,
- you cannot assume that a true value necessarily means that the browser can access the internet.
- You could be getting false positives. |
Input / Output |
Type |
Name |
Description |
return |
boolean |
|
true if device is online |
isOfflineEnabledApp() |
checks whether the app is offline enabled - if the smp, registration, stores objects are initialized |
Input / Output |
Type |
Name |
Description |
return |
boolean |
|
true, if the app is offline enabled |
getServiceUrl() |
returns the service url for a given store id (or default store) |
Input / Output |
Type |
Name |
Description |
parameter |
string |
sStoreID |
ID of the offline store for which the service URL is requested |
return |
string |
|
return the service url |
Offline Error Handling
There are certain error situations related to offline use in Fiori. Handling of these errors shall be done in a consistent way by the application itself.
The method of error handling is different in online and in offline mode, therefore you need to be aware of the offline related scenarios.
In case of an online scenario you get an almost immediate response from the OData Producer for every request. The application provides various solutions to help you to handle situations, such as correcting a field or resending a request.
On the other hand, in an offline scenario the store doesn’t contain any kind of business logic and doesn’t do the same checks as the back end does. When the update of an entity happens locally but on the back end the same entity is already deleted, the offline queue is filled with requests that will all fail when the flush call is initiated. In some cases, you can check the preconditions of the entries on the client side, but apart from this the offline-enabled application must be prepared for handling error messages coming from the back end.
The failed requests are stored in the
ErrorArchive entity set dedicated to each offline store initialized on the device.
You can query the ErrorArchive collection the same way as any other OData collection by using, for example, the $filter $top query options to modify the search. Entries of the archive have to be deleted by the application after the issues have been resolved.
You have to make sure that a flush rejected by the OData producer is followed by a refresh call before any correction is made to clear the offline store from the wrong entities. If the Error Archive is up-to-date, then refresh is not necessary.
Technical Exception Handling
There are technical issues that are related to system errors or infrastructure failures. These can include server communication issues (for example, server is not reachable, there is a communication time out or broken connection) and runtime errors not related to the business data (for example, client side implementation errors, internal server errors, and runtime errors). These errors appear as an object in the error callback of the flush and refresh methods.
Business Logic Exception Handling
There can be issues that are detected by the business logic at the OData producer. These issues include invalid business object data (for example, forbidden property values and combinations, or missing mandatory properties) and forbidden or restricted operations on the business objects (for example, the object cannot be deleted or modified by the user, or there are authorization issues). These errors are stored in the Error Archive as mentioned above.
Conflict Handling
There might be conflicts between the back-end server and the local data set during the data synchronization, for example, the business object is already deleted or modified on the server by another user. It is necessary to define what options the Fiori apps shall provide to the end users to resolve these conflicts.
For those entities that can be modified by the application you need to implement OData ETag support.
Error handling using Offline Interface
When there are issues during flush operation, the errors are retrieved from error archive and stored in an array. You can get the error messages using the below function:
getErrorMessages() |
returns the error messsages array |
Input / Output |
Type |
Name |
Description |
return |
array |
|
array containing the error messages from the error archive. |
The structure of the ErrorArchive entity is described in the below link:
http://help.sap.com/saphelp_smp308sdk/helpdata/en/ff/35db37335f4bb8a1e188b997a2b111/content.htm
Example Code:
if (new sap.smp.OfflineInterface().getErrorMessages().length) {
new sap.smp.OfflineInterface().getErrorMessages().forEach(
function(oErrorMessage) {
//show the oErrorMessage.Message
}, this);
}
You can delete the error archive using the following function:
deleteErrorArchive() |
function that deletes messages in error archive |
Input / Output |
Type |
Name |
Description |
parameter |
array |
aErrorArchive |
Array containing the error messages from the error archive |
parameter |
function |
fnCallbackSuccess |
success callback function |
parameter |
function |
fnCallbackError |
error callback function |
Example Code:
if (new sap.smp.OfflineInterface().getErrorMessages().length) {
new sap.smp.OfflineInterface().deleteErrorArchive(
new sap.smp.OfflineInterface().getErrorMessages(),
function() { }, // success call back on delete error archive
function(oError) { } // failure call back on delete error archive
);
}
Offline Configuration
There are settings that can be changed for the offline application. For example, you can share data sets among the users of an offline-enabled application to improve performance. In this case, data from these collections can be cached on the server to decrease the time of data synchronization. By default, no data is cached on the server.
When an offline-enabled application is initialized, by default the server creates an offline database with initial content from the back end (using defining requests). Then, the database is pushed to the client application on the device.
Change the settings of the defining requests to share data among the users. To do so, define the settings in a configuration file and save it as a text file.
In the Fiori Mobile Admin Console, open the App Settings of your application, and on the Offline tab, select Import Settings and upload your configuration file.
Since all the necessary settings have default values, you only need this file if you want to override this behavior. Default values are not visible on the application configuration UI.
For more information about the application configuration file, see
http://help.sap.com/saphelp_smp3011sdk/helpdata/en/f5/a25877c16f4fc384c44fcf0b92dab8/content.htm?fra...
References:
https://blogs.sap.com/2015/07/19/getting-started-with-kapsel-part-10-offline-odata-sp09/
http://help.sap.com/saphelp_smp308sdk/helpdata/en/a7/d7b40c47024809aee453b3016650a3/content.htm?fram...