#07 SMP3 OData SDK for iOS – Offline APIs
Hi everyone, let’s continue.
In order to use SODataOfflineStore, we need to understand how the offline store works.
During initialization, the offline store communicates with the server to collect the data from that OData Endpoint and stores it locally on the device. In the last blog, we learned how to do it with the defining request in the code snippet.
A formal description about the defining request is:
A defining request is an OData read request that targets the OData Endpoint associated with the offline store and retrieves a subset of the OData Endpoint data. Before a store is opened, it is initialized with a set of defining requests. The set of data that is made available while disconnected on the device corresponds to the union of data received by executing all of the defining requests. During initialization, the offline store communicates with the server to collect the data from that OData Endpoint and stores it locally on the device.
Once you obtained an offline store successfully, you can do the Read operation just like you do with an online store. One thing we have to keep in mind is the fact that the offline store is the locally stored data. This means if you try to read the OData collection, which is not defined during the initialization (via the defining request), you will get an empty result.
Okie, so what we have learned is once the creation of an offline store is done, we can read the store. But we can expect that over time, the locally stored data may grow out of date compared to the OData Endpoint.
It’s time to learn another new cool thing – MobiLink, introduced with SMP3 SP4.
SODataOfflineStore is running with MobiLink behind the scenes. MobiLink is responsible to synchronize the local database in the mobile device and the database in the SMP server.
When the developer works with the SODataOfflineStore, it refers the local data in an offline store. And MobiLink handles the data communication in the most efficient way. If the OData service supports Delta Query mechanism, the transferred data can be optimized too.
It has two key tasks:
- Refresh
- Flush
Refresh is to asynchronously communicate with the server to download any new changes to the OData content. During a refresh, the offline store communicates with the server to re-collect the data from the OData Endpoint and reconciles it with the locally stored data.
An offline store enables the application to modify data (that is, CUD operation) while disconnected. As a result, modification requests made to the offline store are stored locally in a request queue until connectivity can be re-established. When connectivity is available, the application must flush the request queue in order to propagate the stored requests to the OData Producer. During a flush, the offline store communicates with the server and attempts to execute all of the stored requests against the OData Producer.
…that’s all about MobiLink 101 with SMP3 SP4. Hope you have gained a quick idea how SODataOfflineStore works – so what we haven’t done yet is how we implement it with the API. We’ll talk about it in the next blog!
See you in the next blog,
Ken
Hi Kenichi,
It's a great blog. I read through it and stumbled upon the word 'Mobilink'.
Is it, by any chance, a component from SUP 2.x.? We've faced lots of issues about the component back then. If it does, hopefully this time around it's going to perform well.
Next thing I'm curious about the transport protocol behind 'Mobilink'. Does 'Standard OData over HTTP' still apply to the Mobilink component? Or it eventually uses a proprietary protocol for transport, which we have no idea of?
Thank you
Surachai
Hi Surachai,
Thanks for your interest.
Both SUP 2.x and SMP3 SP4 use MobiLink as an underlying transport. The features and performance of SUP 2.x were governed largely by the MBO layer above MobiLink, and that layer has been completely redesigned around OData.
Although the underlying plumbing is based on SQL Anywhere MobiLink, the development experience, APIs, performance and scalability characteristics, functionality, data flow, and integration into other systems with OData are all different.
And yes, it uses proprietary MobiLink protocol to implement the efficient & optimized data transfer as described.
Best regards,
Ken
Hi Kennichi,
I'm appreciate your reply. I get the idea and overall picture of it now. Next step for me is get my hands dirty and try it all out.
Thank you
Surachai
Hi Kenichi Unnai
While opening offline store i am getting below error. can you please share some info how to solve this error
Error Domain=NetworkDomain Code=2 "[-10060] An error occurred while performing a synchronization.
Reason: -857 (ERROR) %1:[-10225]
Message: Failure occurred while executing user supplied code"
UserInfo=0x2820e330
{NSLocalizedDescription=[-10060] An error occurred while performing a synchronization.
Reason: -857 (ERROR) %1:[-10225] Message: Failure occurred while executing user supplied code}
Hi Mahesh,
Nice try. Your post made me decide what would be in the blog #11 🙂
-857 error means that something went wrong in the server (This is changing to a more descriptive error message in the upcoming patch). Usually if the client reports this error, there should already be a stack trace of the error in the server log.
I bet your problem is related with how you wrote the defining request. Can you hold on about the details in the blog #11?
Best regards,
Ken
Namaskar Mahesh,
In case if you're not yet aware of...so the blog #11 is explaining about the details & remarks for Defining Request.
Hope this helps,
Ken
Hi Kenichi Unnai,
Offline store is working after iOS SMP SDK upgrade. 🙂
Hi Kenichi Unnai,
When I try kapsel OData offline, I am getting below error.
[-10060] An error occurred while performing a synchronization.Reason:-1305(MOBILINK_COMMUNICATIONS_ERROR)%1:88 %2:X-CORDOVA-PLUGINS=com.sap.mp.cordova.plugins.encryptedstorage 3.5.
code: sap.OData.createOfflineStore(properties);
properties params is:
SMP Application Offline config:
@Kenichi Unnai
There is a separate SCN article that covers the Kapsel Offline OData plugin. Perhaps it might be helpful. There is a troubleshooting section that lists some common problems and how they are reported in the logs.
Getting Started with Kapsel - Part 15 -- Offline OData (New in SP05)
Regards,
Dan van Leeuwen
Thank you very much for reply.
This article describes how to conduct troubleshooting, but there is no corresponding error solution.
I passed several amendments to the current use of pad test OData Offline when app often flash back. I estimate the amount of data is too large OData insufficient memory. What you encountered this situation?
Hi Kenichi,
Thanks a lot for sharing this wonderful blogs.
I have a question regarding offline OData.
I'm using OData offline Store "native iOS" with SMP 3.0 SP06 and it is working fine with me till now, but I wonder why I don't see any configuration in SMP server in offline section ?
as below:
Am I missing something ?
another question is not related to offline topic, how can I use client resources bundle using OData SDK ? and how can I get notified in code that bundles has been updated as I want to use it as application settings.
Thanks in advance.
Regards,
Hossam
Hi Hossam, good to know they are helping you 🙂
>Am I missing something ?
You need to upload the application configuration file manually, it is introduced here.
> client resources bundle
You can find "Client Resource" tab in the application configuration section (next to the Offline tab). Here you can find how to use the APIs..and Automatic notification was a feature of the IMO channel (in SUP), so the up-to-date approach is to query it on app start or with an appropriate frequency.
Thanks Kenichi,
So, uploading configuration is optional and I don't have to, also if it is configured automatically it will not be shown in my SMP Server. Right ?
Thanks,
Hossam
Correct, it should be empty if you don't upload .ini file.
Hi Kenichi,
have a question regarding offline store concept.
Dose SMP create a middle-tear database on SMP server too, or it just create a database on client device ?
Another question, what happens if I changed the schema of OData for example adding a new property or adding new entity, when client refresh its offline store what will happen ?
Thanks
Hossam
>Does SMP create a middle-tear database
By default it doesn't. If you upload your .ini file, the middle tier cache db will be created.
>if I changed the schema of OData
If you ever tried to run the actual offline store, you'll see the offline store will be initialized and download the OData payload. When you initialize it you'll declare the defining request which is explained in my blogs - so If you change the entity structure itself, you need to drop the existing offline store and create a new one.
Hi Kenichi Unnai
Can you please clarify if there are any limitations with the offline store?
I am specifically interested in how many offline stores can be opened at any one point and is there a limitation in the number of defining requests allowed in one offline store?
Thanks in advance!
Jeff
Thanks for the inquiry.
Actually there is no hard limit to the number of defining requests, but please keep in mind that an Ultralite database has a limit of 4GB.
I believe there is a limit of 4 offline stores that can be open at one time. See also the question and answer section of this blog.
Getting Started with Kapsel - Part 10 -- Offline OData (SP09+)
Question
How many Offline Stores can be open at the same time? The following error is occurring when opening five offline databases. [-10067] Could not create the store. Reason: -685
Answer
There is a limit to the total number of Ultralite databases that can be running concurrently as of SDK SP10, and each offline store has 2 databases (the offline store and the request queue). Currently on a device, the limit is 8 databases which means that a maximum of 4 offline stores can be open at the same time.
Regards,
Dan van Leeuwen
Thanks Dan for the follow-up. Just I'm back from the clarification.
The limit is actually related to database connections and not databases themselves.
This limitation applies to any Offline Stores, including Hybrid and native - and our developers are currently working on improving these remarks in the upcoming release.
Hi Kenichi Unnai,
Small question : is it possible to use a delete method on offlineStore without send this deletion in the next push ?
Or differently : how to delete an entity in the offlineStore only in the local database ?
Regards.
Hi Julien,
Can you share your use case why you want to delete entities only on the local side?
As you learned, the SDK is designed to sync with the backend data by means of flush & refresh.
I wonder if there's any use case to make it sense with the local deletion? If the client wants to keep it locally even after flush, the backend data is going to be obsolete and we should have the data inconsistency with other clients.
Hi Kenichi,
In fact, we discovered a problem in the SMP library with function import when we use Chinese characters. The URL is invalid when a Chinese character is in.
I tried to use an URL encoded method, but people of back end told me that he could not decode the URL (because a gateway problem I believe, I did not quite understand, I am only on the front).
It was therefore decided to transform this Web service by passing an import function has a web-service entity so that Chinese characters no longer happening in the URL but in the payload. In this way it works but there is no method to "delete" or "update" on the server, only create (and maybe "read"). So if I do a delete, this correctly deletes the entity in my local database but when I make a flush, I receive an error and the entities back into my local database.
So I would do a delete to remove only local entities created for the web service once the flush was successful.
I see.
Just to clarify, are you trying to use the function imports with offline store? As it is formally stated (I believe you already confirmed it in the link in this H2G), it is not supported.
This is simply because of the fundamental design reason - that offline store loads the OData by means of the standard & consistent CRUD operations (the function imports are intended for online store only)
Are you trying to use the function imports with offline store?
Before the web service was indeed a function import. But if I understand what I hear from people back, they changed this Web Service to use an entity. So now, this Web Service has been changed and works as an entity. Except that some method like "Delete" does not seem to have implemented.
Alright - so if I understand correctly, the web services originally used are now re-implemented as a standard OData services but it doesn't have the Delete method implemented yet.
So do you still have any issue as of now...? Please note that the (SOAP or REST) web services are NOT the OData services (it has the standard interface via the OData service document).
If I understand correctly, the offline store must always be synchronized with the backend data in order to avoid data inconsistency. There is therefore no method of local deletion.
If you confirm me that no, I have no further questions.
Exactly, your understanding is correct.
Hi Kenichi Unnai
I have an iOS app with offline store up and running, however I have noticed that when I perform a refresh my data is not being updated even with a refresh success.
We have an offline store that pulls the initial data, within the data there is a property that contains the server timestamp. At the server end every time we access this property it will return the server's current timestamp.
However when I perform a refresh on the offline store I was expecting this timestamp property to be updated, but it hasn't. The only time when it gives me a new timestamp is if I delete the offline store and open it again.
1. Do you know why this maybe happening?
2. Is there anyway to see what has been brought down in a refresh?
Thanks
Jeff
That sounds your offline store fetched cached data - have you configured .ini file for the offline store?
And - do you confirm the same behavior from your REST client (Or online store)?
Thanks for the prompt response.
No I haven't configured a .ini file, is this on the server side?
I will test with an online store and I will report back.
Just tested with a rest client, I get a new timestamp every time.
ok - i'll check that possibility. I'll get back here.
So just to give you a better understanding of the use case.
I have an iOS app that is accessing data in the backend through SMP. This data is stored in the offline store of the app and is manipulated locally then a flush/ refresh will occur at some point in time.
During the offline period of the app, the server data maybe updated through other channels e.g. a separate desktop application.
Putting conflicts aside, my expectation is that when I perform a refresh on the offline store, I will also receive the data changes that occurred as a result of using the desktop application.
The timestamp property is a simulation of this scenario.
Hi Jeff/Ken,
Please create a new Discussion marked as a Question to continue this conversation. The Comments section of a Blog (or Document) is not the right vehicle for asking questions as the results are not easily searchable. Once your issue is solved, a Discussion with the solution (and marked with Correct Answer) makes the results visible to others experiencing a similar problem. If a blog or document is related, put in a link.
NOTE: Getting the link is easy enough for both the author and Blog. Simply MouseOver the item, Right Click, and select Copy Shortcut. Paste it into your Discussion. You can also click on the url after pasting. Click on the A to expand the options and select T (on the right) to Auto-Title the url.
Thanks, Mike (Moderator)
SAP Technology RIG