Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
claudiapacheco
Product and Topic Expert
Product and Topic Expert

The SMP 3.0 OData SDK SP05 introduced the concept of store, which is an abstraction for services that can be consumed via OData protocol. There are two type of stores: online and offline. The methods for creating, updating, deleting and querying data are the same for both stores, however there are some differences. Let's get you started with the Offline store.

IMPORT LIBRARIES AND RESOURCES

Your android project must include the following libraries under libs folder

  • AfariaSLL.jar
  • ClientHubSLL
  • ClientLog.jar
  • Common.jar
  • Connectivity.jar
  • CoreServices.jar
  • DataVaultLib.jar
  • E2ETrace.jar
  • HttpConvAuthFlows.jar
  • HttpConversation.jar
  • maflogger.jar
  • maflogoncore.jar
  • maflogonui.jar
  • mafuicomponents.jar
  • mafsettingscreen.jar
  • MobilePlace.jar
  • ODataAPI.jar
  • odataoffline.jar
  • ODataOnline.jar
  • perflib.jar
  • Request.jar
  • sap-e2etrace.jar
  • SupportabilityFacade.jar
  • XscriptParser.jar

The following resources should be imported under libs/armeabi folder

  • libmlcrsa16.so
  • thelibodataofflinejni.so

You can find the .jar and .so files in your OData SDK installation folder:

<Client SDK dir>\NativeSDK\ODataFramework\Android\libraries

<Client SDK dir>\NativeSDK\MAFReuse\Android\libraries

<Client SDK dir>\NativeSDK\ODataFramework\Android\libraries\armeabi


INITIALIZE OFFLINE STORE

The offline store requires among other information, the collections (also called defining requests) that will be accessible offline. When the client app requests the initialization of the offline store this is what happens under the covers:

  1. The mobile services (either SMP 3.0 SP04 on premise or HCPms) will send a GET requests to the OData producer to get the metadata (OData model) and it will use the OData model to create the Ultralite database schema.
  2. For each defining requests, the mobile services will pull the data from the OData producer and will populate the database. The mobile services checks if there’s a delta token:
    1. If there is a delta token, it will cache it and use it in the following refresh.
    2. If there is not delta token, it will cache the keys populated in the database.
  3. The mobile services will notify the client app the database is ready
  4. Using Ultralite functionality the client app will download the database. At this point the database can use used offline

Code Snippet – How to open an offline store

//This instantiate the native UDB libraries which are located in the
//libodataofflinejni.so file
ODataOfflineStore.globalInit();

//Get application endpoint URL
LogonCoreContext lgCtx = LogonCore.getInstance().getLogonContext();
String endPointURL = lgCtx.getAppEndPointUrl();
URL url = new URL(endPointURL);
                     
// Define the offline store options.
// Connection parameter and credentials and
// the application connection id we got at the registration
ODataOfflineStoreOptions options = new ODataOfflineStoreOptions();
options.host
options.port
options.enableHTTPS

// the serviceRoot is the backend connector name, which is usually the same

// as the application configuration name in the SMP Management Cockpit

options.serviceRoot= "com.sap.flight";

                     
//The logon configurator uses the information obtained in the registration
// (i.e endpoint URL, login, etc ) to configure the conversation manager

// It assumes you used MAF Logon component to on-board a user      
IManagerConfigurator configurator = LogonUIFacade.getInstance().getLogonConfigurator(context);

HttpConversationManager manager = new HttpConversationManager(context);

configurator.configure(manager);

options.conversationManager = manager;

//Preferred settings - if back-end implements repeatable request

//look at a comment below for more details

options.enableRepeatableRequests = true;

options.storeName ="flight";

             

//This defines the oData collections which will be stored in the offline store

options.definingRequests.put("defreq1", "TravelAgencies_DQ");

//Open offline store synchronously

ODataOfflineStore offlineStore = new ODataOfflineStore(context);

offlineStore.openStoreSync(options);

//A way to verify if the store opened successfully

Log.d("openOfflineStore: library version"+ ODataOfflineStore.libraryVersion());


What does it mean to support repeatable request?

If some type of connection issue prevents the client from receiving the response, then the client is unable to determine whether the request was processed by the server. However, sending the request a second time is not a solution as this could cause application errors in the backend.

If repeatable request is supported and the client makes the same request multiple times, the back-end will processed the first request, but thereafter, the only response the client will receive is a link pointing to the response created by the first request.

options.enableRepeatableRequests = true;

- By switching on the enableRepeatableRequest to true in the SMP offline store, this process is handle automatically in the client side.

- For more information on how to enable repeatable request in the back-end (gateway), please look at this documentation Settings for Idempotent Services - SAP NetWeaver Gateway - SAP Library

Once the offline store is open, you can create, update, delete and query data offline. As we mentioned before, the methods for creating, updating, deleting and querying data are the same for both stores. Note that all offline store requests are sent to the local database.


Code Snippet – How to query data with an offline store

//Define the resource path

String resourcePath = "TravelAgencies_DQ";

ODataRequestParamSingle request = new ODataRequestParamSingleDefaultImpl();

request.setMode(Mode.Read);

request.setResourcePath(resourcePath);


//Send a request to read the travel agencies from the local database

ODataResponseSingle response = (ODataResponseSingle) offlineStore.executeRequest(request);

//Check if the response is an error

if (response.getPayloadType() == ODataPayload.Type.Error) {

       ODataErrorDefaultImpl error =  (ODataErrorDefaultImpl) response.getPayload();

       //TODO show the error


//Check if the response contains EntitySet

} else if (response.getPayloadType() == ODataPayload.Type.EntitySet) {

    ODataEntitySet feed = (ODataEntitySet) response.getPayload();

    List<ODataEntity> entities = feed.getEntities();

       //Retrieve the data from the response

    ODataProperty property;

    ODataPropMap properties;

    String agencyID, agencyName;

       for (ODataEntity entity: entities){

              properties = entity.getProperties();

              property = properties.get("agencynum");

              agencyID = (String) property.getValue();

              property = properties.get("NAME");

              agencyName = (String) property.getValue();

              . . .

     }

}


SYNCHRONIZE WITH ODATA PRODUCER


Flush

When connectivity is available, the client app must send all the local changes, this process is called Flush. When the client app requests a flush, this is what happens under the covers:

  1. The offline store communicates with mobile services
  2. For each requests the mobile services attempts to execute the request against the OData Producer
  3. The mobile services send the responses (errors and successes) to the client app and the errors will be stored in the ErrorArchive collection of the offline store.


Code Snippet - Flush
offlineStore.flushQueuedRequests();



Refresh

After the flush, the client app must receive all the changes from the OData producer that have occurred since the last refresh. When the client app requests a refresh, this is what happens under the covers:

  1. If delta token is enabled, for each request the mobile services requests data with the delta token
  2. Otherwise, the mobile services retrieve all the data from the OData producer and retrieve keys from cache and compute the delta. Reducing the traffic from the mobile services to the client app
  3. The mobile services transform all the changes to the relational mobilink protocol and send it back to the client app.
  4. The client app Ultralite database performs all the instructions

Code Snippet - Refresh
offlineStore.refresh();

NOTE

The code snippets showed in this blog are using the synchronous methods for simplicity purposes. Please note there are asynchronous methods available.


This blog assumed

  • You have configured an application in the mobile services with Back-End Connections

http://<sap gateway host>:<port>/sap/opu/odata/IWFND/RMTSAMPLEFLIGHT/  

  • A user has been on-boarded with the mobile services using MAF Logon component.


ADDITIONAL LINKS

For more information on how to create an application configuration, visit Deploying Applications

If you prefer hands-on exercises, check these guides out

How To... Enable user On-boarding using MAF Logon with Template Project (Android)

How To...Consume OData Services in Offline Mode (Android)

How to... Handle Synchronization Errors (Android)

Hope you find this information useful,

Claudia

23 Comments