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: 
miltonc
Product and Topic Expert
Product and Topic Expert
0 Kudos
OverviewBackendApp ConfigurationAndroidiOS
MBO iOS AppOData iOS App

OData iOS Content:

In the MBO world (depending on SUP version and device platform), you either have a local ultralite or SQLite database residing on the device.  The data from the backend EIS system is staged (or cached) in the consolidated database (CDB).  This data is then synchronized with the local database residing on the device.  All CRUD operations are performed on the local database.  So in a sense, all native MBO based applications have offline capability. When it comes to migrating MBO based application to an OData based application using the harmonized SDK, there is an implicit mapping of the offline capability inherent in MBO world to the Offline Store concept in the OData world.  Unless absolutely required by business needs, I do not recommend using both Online Store and Offline Store within the same application.  In fact for all migration needs, I strongly recommend only using the Offline Store to achieve similar functionality.

Synchronization Groups maps to Defining Requests

There is a strong correlation between synchronization groups in MBO world to the defining requests in the OData world.  Roughly speaking, a synchronization group must contain MBOs that must be synchronized at the same time.  For example, if you have SalesOrders and SalesOrderItems MBOs, then it makes sense to synchronize both these MBOs at the same time.  In this case, you would place both SalesOrders and SalesOrderItems MBO in the same synchronization group.

In our migration example, we have the following synchronization groups.

Synchronization Group

MBOs

SG_Product

Product

ProductDetails

SG_Sales

BusinessPartner

SalesOrder

SalesOrderItems

This corresponds to creating 2 defining requests in our OData mobile application.

[options addDefiningRequestWithName:@"SG_Sales" url:@"BusinessPartners?$filter=Country eq 'US'&$expand=SalesOrders/Items" retrieveStreams:NO];

[options addDefiningRequestWithName:@"SG_Product" url:@"Product?$expand=ProductDetails" retrieveStreams:NO];

Note that the $expand option is used to retrieve all the related entities in BusinessPartner, SalesOrders and SalesOrderItems.

Load Parameters and Sync Parameters maps to Query Filter

In our MBO sample application, we filtered data sent down to the device based on the Country.  This sent down only BusinessPartners that belonged to a certain country.  Since SalesOrders and SalesOrderItems follow BusinessPartners, they were also filtered and only related entries were sent down to the device.

In the OData application, the load parameters and sync parameters can be specified as query filters in the defining request.  Here we see how the BusinessPartner is filtered based on Country eq ‘US’.

@"BusinessPartners?$filter=Country eq 'US'&$expand=SalesOrders/Items"

In some cases, the user may want data from a different country for some reason (for example, user goes on a business trip to Europe).  There is not an elegant solution to this in the OData SDK.  The current workaround is to recreate the Offline Store.

Implementing the Offline Store

Similar to the central logon handler class that was used for on-boarding a device, it is recommended to create a class that handles Offline Store functionality.  This class must implement methods to open the Offline Store and be able to flush and refresh the Offline Store.  A static variable of type SODataOfflineStore is also declared that can be used in various parts of the program using a getStore class method.

@interface ODataContext : SODataOfflineStore

+ (SODataOfflineStore *)getStore;

- (void)openOfflineStore;

- (void)flush:(void(^)(BOOL success))completion;

- (void)refresh:(void(^)(BOOL success))completion;

@end

This class must also implement the various delegate methods associated with opening an Offline Store, flushing the contents of an Offline Store and refreshing the Offline Store protocols.

static SODataOfflineStore *STORE;

@interface ODataContext() <SODataOfflineStoreDelegate, SODataOfflineStoreRefreshDelegate, SODataOfflineStoreFlushDelegate, SODataOfflineStoreRequestErrorDelegate>

@end

The getStore class method simply returns the static variable STORE to be used in various parts of the program.

+ (SODataOfflineStore *)getStore

{

    return STORE;

}

The UI can be updated based on the various callback methods that are associated with the protocols for opening the Offline Store, flushing and refreshing contents of Offline Store.

Implementing the callbacks

As mentioned earlier, the class that handles the Offline Store functionality must implement methods to open the store and perform flush and refresh.  Since all these operations are asynchronous in nature, the class must also handle the success and error callbacks.

- (void) offlineStoreStateChanged:(SODataOfflineStore *)store state:(SODataOfflineStoreState)newState

{  

    switch (newState)

    {

        case SODataOfflineStoreOpening// The store has started to open

            break;

           

        case SODataOfflineStoreInitializing: // The store is being initialized

            break;

           

        case SODataOfflineStorePopulating: // The store is being populated

            break;

           

        case SODataOfflineStoreDownloading: // The store is being downloaded

            break;

           

        case SODataOfflineStoreOpen: // The store is being opened

            break;

           

        case SODataOfflineStoreClosed: // The store is closed by user

            break;

           

    }

}

- (void) offlineStoreFlushSucceeded:(SODataOfflineStore*) store

{

  // Flush succeeded

}

- (void) offlineStoreRefreshSucceeded:(SODataOfflineStore *)store

{

  // Refresh succeeded

}

Application configuration file

In addition, use an application configuration file to configure OData endpoints and defining requests that determine the data that populates the application database when it is created.

[endpoint]

Name=com.sap.epmsales

prepopulate_offline_db=Y

[defining_request]

name=SG_Sales

is_shared_data=N

[defining_request]

name=SG_Product

is_shared_data=Y

I have attached a sample application that opens the Offline Store and performs flush and refresh using the steps outlined above.  Please let me know if you have any questions.

Our next step in the migration process is querying the data.