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: 
kenichi_unnai
Advisor
Advisor
0 Kudos


<updated>May 14th, 2015</updated>


Hello everyone,

Back to the blog 🙂


Now that we have gone all the way through the 10 blogs, general understanding of the OData API has been deployed on top of our brains.


From now on, we'll discuss some gotchas to watch out. As all those information are "as it is", please expect constant update in the blog, I'll put the timestamp explicitly whenever some important update come in in the future.


Throughout this blog I would like to cover bits and pieces around SODataOfflineStore.


Removing the offine store

In the blog #06, we learned how to create an offline store. We haven't discussed yet how to remove it... Here's the code to name the offline store, which is required for removal step later. The storeName property is optional for SODataOfflineStoreOptions instance.  If it is not set when opening the store, it chooses a default name.

01  SODataOfflineStore *offlineStore = [[SODataOfflineStore alloc] init];
02  SODataOfflineStoreOptions *options = [[SODataOfflineStoreOptions alloc] init];
03  options.storeName = @"MyStore";
04  ..

And the code below is about how to remove the physical store from the file system. If you don't set the storeName during the creation, the default value will be used without the property value. As written in the line #04, the store must to be closed before the removal.


Note: For security, you should be closing your store instances whenever you do not need them (e.g. via applicationDidEnterBackground:, when you app goes to the background). Once it is closed, it can be open by openStoreWithOptions:error: method (e.g. via applicationWillEnterForeground:).


When the app comes back to the foreground, you don’t simply call openStoreWithOptions on the same store instance.  Instead you have to create a new store instance using offlineStore = [[SODataOfflineStore alloc] init]; and then call openStoreWithOptions on that.

The "offlineStore" instance here is not a new one but the same name with the closed one. As long as they use the same storeName option then it will open up the same underlying local store database and do not have to redownload anything.


01  NSError *error = nil;
02  SODataOfflineStoreOptions *options = [[SODataOfflineStoreOptions alloc] init];
03  options.storeName = @"MyStore";
04  [offlineStore closeStoreWithError:&error];
05  [SODataOfflineStore RemoveStoreWithOptions:options error:&error];
06  if (error) {
07    // store removal failed
08  } else {
09    // store removal succeeded
10  }

Defining Request

In the blog #06 and #07, we learned what Defining Request is and how to define it in the code. A few things to keep in mind:

  • Entity relationships


In order for entity relationships to be available (e.g. "CarrierCollection('CO')/carrierFlights" - the relationship from one entity to another) on the client we need to have one of two things:


Option 1) Use $expands in your defining requests

Option 2) Inside OData services, implement a set of referential constraints between the two entity types


Option 1 - The $expand syntax is to name the navigation property that you want to expand, most OData producers do support $expand.


Option 2 - A referential constraint is extra information attached to an Association (or relationship) that says how the two entities are related. In OData Metadata, you should be able to find the <ReferentialConstraint> tags if it is implemented in OData services. If these are supplied, the relationships between entities is defined by the properties directly and MobiLink can use that to build up the links behind the scenes. The benefit of this approach is in case $expand can't be used, we can go to this option.


So if the OData service implements both $expand and referential constraint for the entity relationship between Customers and Orders, both do the same job from the client perspective.

01  options.definingRequests[@"req"] = @"/Customers?$expand=Orders";
01  options.definingRequests[@"req1"] = @"/Customers";
02  options.definingRequests[@"req2"] = @"/Orders";

[There is a bit of a description of referential constraints in section 10.4 of Common Schema Definition Language (CSDL). Essentially, referential constraints are OData metadata details that can be supplied in order to make OData properties act more like relational database foreign keys.]

  • OData collection times out with HTTP 500 error

You might encounter the runtime error during the offline store creation, simply because the OData collection you're trying to fetch is too big - you can copy & paste the OData endpoint URL in the web browser and see if it shows 500 timeout error. The issue in this case is a problem on the server-side.  Our HTTP requests for data were timing out because the backend producer was taking too long to query the data and encode it as OData.

In this case we should consider using server side paging on OData producer.


There are two types of paging in OData – server side and client side.

Client side paging is driven by having a $top value and then incrementing the $skip values for each request (e.g. $top=100&$skip=0 for first request, then $top=100&$skip=100 for second request etc.) This type of paging will not help with populating the database in the offline store because the defining requests are fixed. (Of course, you can use $top or $skip to make requests for small amounts of data to the local store after the store has been populated.)

In server side paging, even if you request the entire big OData collection, the server will only return a portion of the results, but provide a “next link” info, which can be followed to get the next portion and so on.  When the MobiLink is populating the local store it knows how to follow these next links. Server side paging via next links is OData Version 2.0 feature. The $skiptoken query is seen in OData URL if it is implemented.


Offline OData Version Support info


Is here!


OData Query Options supported by SAP NetWeaver Gateway


is here!


OData Query Options supported by Integration Gateway


is here! (You'll find detailed info via each tree node for JDBC/JPA/SOAP/ODC)


SAP Note# 1931374 - Integration Gateway for SAP Mobile Platform 3.0 - Known Constraints

"How do we build the best OData services for offline scenario?" Series

Okie that's all for the blog this time. I'll cover some other practical topic in the next blog...



See you in the next blog,

Ken


List of blogs

11 Comments