cancel
Showing results for 
Search instead for 
Did you mean: 

Does store.flush update the local created entity

chinna_babu2
Active Participant
0 Kudos

Hi Experts,

Can store.flush updates the local created entity with the key? I don't see that store.refresh refreshes the with new entries (if exists) in the backend, but I want my locally created entry need to be updated as my the local record will have temporary key assigned(within the program) where as when it sent to backend new number(key) will be generated.

Is there a way to update the local created record? or delete from the local record if flush was successful.

Regards,

Murthy

Accepted Solutions (1)

Accepted Solutions (1)

midhun_vp
Active Contributor
0 Kudos

Hi Narasimha,

Could you explain in detail what you are trying to do and what is your requirement.

I don't understand what you mean by temporary key.

Regards, Midhun

SAP Technology RIG

chinna_babu2
Active Participant
0 Kudos

Hi Midhun,

My requirement is to create or update the work orders from the device.

When creating the new work order from the device I assign a unique number to the work order number. For example number is 'ORD12345'.

When the store is flushed work order is getting created in the backend with the actual work order number. For example '10000234'.

In the device I have the order with number 'ORD12345' where as the same work order is with number '10000234'.

How can I update the order number 'ORD12345' with the actual number '10000234'?

Regards,

Murthy

midhun_vp
Active Contributor
0 Kudos

Hi,

Could you share the code you wrote.

Are you doing a refresh after the flush?

Regards, Midhun

SAP Technology RIG

chinna_babu2
Active Participant
0 Kudos

Hi Midhun,

Below is the code to create record, flush call and refresh.


//Save Work Order

saveWorkOrder: function(){

var data = {};

data.OrderNumber = "ORD12345";

data.description = "Testing";

data.functionaloc = "AZ09LL";

data.equipment = "1000334";

data.headerDetail = {};

data.headerDetail.OrderNumber = "ORD12345";

data.headerDetail.Priority = "3";

data.headerDetail.OrderType = "M1";

var header = {};

header['Authorization'] = authStr;

var smpUrl = "http://..../ZWORKORDER_SRV/WorkOrder";

var request = {

    headers: header,

    requestUri: smpUrl,

    method: "POST",

    data: data

    };

    OData.request(request, function(){

                   console.log("Work Order Created successfully");

                    }, function(e){

                    console.log("error in work order creation");

                    }

     );

}

//flush local changes

function flushStore() {

    if (!store) {

        alert("The store must be open before it can be flushed");

        return;

    }

    store.flush(flushStoreSuccessCallback, errorCallback);

}

function flushStoreSuccessCallback(data) {

    var endTime = new Date();

    refreshStore() ;

}



//refresh store

function refreshStore() {

    if (!store) {

        console.log("The store must be open before it can be refreshed");

        return;

    }

   

    store.refresh(refreshStoreCallback, errorCallback);

}

function refreshStoreCallback() {

    console.log("store refreshed successfully");

}


// refresh store

I can see that new work order is getting created and no errors in flush and refresh. Please suggest how to get the local work order updated with the backend work order number.

Regards,

Murthy

midhun_vp
Active Contributor
0 Kudos

Hi Murthy,

This is new to me. I am not sure this is an issue with the offline plugin; looks like the plugin is not able to detect changes in a specific property in backend while doing refresh.

What's happening when you use store.clear after flush, then followed by refresh ?

I would suggest you to raise a ticket to SAP with all the relevant details.

I would check with the developers too.

Regards, Midhun

SAP Technology RIG

chinna_babu2
Active Participant
0 Kudos

Thanks Midhun,

Before I raise the ticket I would like to make to sure whether I did any thing incorrect or not.

If I execute store.clear after flush its removing the offline store and have to create the store again.

In the gateway service after the work order is created I am returning the work order number back.

ie., in the import payload I pass the temporary number as

<OrderNumber>ORD12345</OrderNumber>

<description>Testing</description>

on return after save

<OrderNumber>10000234</OrderNumber>

<description>Testing</description>

hope there is nothing wrong the way posting the data to the service and returning the payload after the save.

Can you please clarify below queries

1. Will store.flush and refresh automatically update the local created entity and its primary key? or will it remove the entity/record after the flush from the local store?

2. For parent and child related records I am handling the save in the backend such as for example in the case of Work Order and operation creations. I save the work order first and create the operation later.

For the Operation and Work Order I will assign the same temporary work order number. When work order is created in the backend will store in the number in backend table and when operation is being saved will lookup work order from the table and use it to save operation.

Rather going through all these handling is there a way these scenarios can be handled?

3. How to modify locally crated records before sent out via the flush?

Every time I do the changes local records are getting updated but every modify request call going to backend when flushed.

In this scenario for example I have the work order already created, with the second modify request the call goes to the backend with temporary work order number. This gets failed as work order number doesn't exists.

Thanks in Advance,

Murthy

midhun_vp
Active Contributor
0 Kudos

Hi Murthy,

I got a question here.

You are trying to create an order, and we know that the order number will be created only when the order is successful. In that case why are you passing the order number while creating order?

Can't you make changes in the backend to make the order number field  as an optional parameter while creating order?

Regards, Midhun

SAP Technology RIG

chinna_babu2
Active Participant
0 Kudos

Hi Midhun,

Order number is the primary key without this I don't think store can be created and also existing orders will need to be downloaded as well.

Order Number is the key field for Work Order and Operation relationship.

Regards,

Murthy

midhun_vp
Active Contributor
0 Kudos

Hi Narasimha,

I haven't noticed any mistake in the way you wrote the code.

Our developers tried to replicate this scenario and found this working.

Hence I would suggest you to raise a ticket to SAP. The support team should be able to help you.

Regards, Midhun

SAP Technology RIG

Former Member
0 Kudos

Hello Narasimha,

I am having the same problem, Could you fix it?

It would be great help your feedback or solution about it.. with PUT it is working correctly...

Thank you in advance.

Óscar.

chinna_babu2
Active Participant
0 Kudos

Hi Oscar,

I didn't get it resolved. Please update this thread if you find a solution.

Regards,

Murthy

Former Member
0 Kudos

Hello Murthy,

I found the solution.. in my case, backend´s guys had not implemented "DELETE"  http method and the plugin tries to look (unsuccessfully) to get this method (as a standard way in REST apps) and it did not find it..  From backend implemented a empty method and it was enough.

Of course, it is necessary to follow oData protocol line by line and it will works...

Here you can see another example of this problem, more or less similar...

In this post I had written comments with the user Dan Antonio.

I expect you find the solution..

Former Member
0 Kudos

#update to answer all 3 questions:

Question 1:

For a new record, the flush() sends it to the backend, then removes it once the flush completes, and then the refresh() brings it back down if is part of the defining request.

Question 2/3:

When working with parent/child objects in the offline data store, make sure that any updates you perform are done against the "__metadata/uri" field of the object.

Basically what happens with the SAP Kapsel Offline OData store is:

- When you post new data to the offline store, it creates in internal ID/URI which represents the location of this data in the offline store (you see if it if you look at the "__metadata/uri" of the object/response).

- Any updates must be made to this object or else the context may get lost when flush happens.  PATCH/MERGE/PUT to the metadata uri.  You may have to include the etag as a parameter also (this is also in the __metadata).

Example using batch:

batchChanges.push(oModel.createBatchOperation(uri, "PATCH", oEntry, {sETag: etag}));

If you do the updates in this manner, it should work ok.  The SMP handles the mapping of the response to the offline data using the URI/ETAG metadata, so multiple changes should work properly.


I have found though that sometimes it gets confused if you try to change the key fields as part of the POST.  (See Kapsel Offline OData - Flush works, but doesn't clear sap.islocal() for more details).

Former Member
0 Kudos

Did you implement my solution or other approach??

Former Member
0 Kudos

Hi Dan,

We are facing similar issue in Android Native using SMP 3.0 SP 10.

Current State:

- Created work order and associated Operations in offline store using batch request.

- Successfully modified work order object and added new Operation in offline store using etag and resource path through a second batch request.

- Upon performing offlineStore.flush() the first batch executed successfully and Work order with associated Operations was created in backend.

- However when second batch executes work order update with uri like "/Workorders(lodata_sys_eid = X'047AD786A01011E4800095AE655F2D3900000000')" results in error as back end unable to identify the work order.

Can you please suggest the way forward to resolve it.

Thanking you in advance.

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

Hi / ,

We have similar issue where in on successful refresh we notice duplicate objects in the offline store (One created locally and other one which is created in backend and received through refresh).

We have implemented blank delete method as well in the backend however the issue is still persisting.

Note:

a) We are developing a Native Android SMP (v3.0.10.0) OData Offline SDK based application.

b) We are using batch request as we need to support deep insert.

c) We can't keep the key field blank (suggested by Dan as helpful answer) because we can have multiple objects created and updated (later) in offline mode even before a flush is triggered. So to identify each local object uniquely, we have to maintain unique key values in offline mode.

Our situation is as follows:

1. Created an object in offline store with key '%00000000010' using batch.

2. Updated the description field (which is a non-key field) in offline store successfully using batch.

3. Triggered flush and refresh successfully.

4. We got the newly created object with proper key (i.e. '000004000000') from backend.

5. We noticed there are two different objects in offline store, one with key '%00000000010' and other one with key '000004000000'.

We want that, Object with key '%00000000010' should get deleted from offline store once the corresponding object received from backend with actual key value.

Kindly suggest a way through it.

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

Some thoughts:

- Batch is fine, but deep insert might not be.  See Offline OData Version Support and Limitations - Application Development in SAP Mobile Platform - SAP... for more details.

- Keeping the keys blank is the essential part of this (if the key is going to be generated on the backend at sync time).  To perform any updates to the record you should use the record locator url and etag to reference the item to update instead. (like your other example "/Workorders(lodata_sys_eid = X'047AD786A01011E4800095AE655F2D3900000000')"If you need to display a temporary key field in the offline app until sync happens, I would recommend creating a secondary field to store the temporary display name so you can the leave the key field blank.

Former Member
0 Kudos

Where/when are you seeing this error?  Any updates to newly created offline data should be using the record locator/url and etag. 

When the sync happens, as the first batch is executed and creates the new object, the SMP server uses the locator url to identify which other pending requests are for the same object and it makes sure that it uses the correct new keys for those transactions. 

But this may only work if the keys are empty in the original request...

Former Member
0 Kudos

Ok, we had the same problem.. it is important to understand mirroring process.

In our case, we have two different scenarios:

1º items sent from BE with id registered in BE and when is synchronized with the FE mirroring is finished because in both sides is the same,

2º item created in the device in offline mode, in that moment item is only in FE and after the flush is synchronized with BE but it is necessary to send again to the FE the same item (same object, in the refresh) with the ID generated in BE (in our case we have a outbox view and we hide the items sychronized with a boolean parameter), so it is necessary to follow this way.

If you have logs in the console you can see this item synchronized only will be send once to the FE.

Blank DELETE method is necessary if you delete items from the FE, because in the FLUSH method will propagate each HTTP method used in the offline mode, and if you have a CRUD app will be needed. At the beginning we thought with a blank method would be enough, but now and from other perspective we have implemented a complete implementation of this method.

Let me know if you need more clarification, please see the image, we wrote a PPT file with the different situations and HTTP methods, this slide (I think) it is your scenario.

.

Former Member
0 Kudos

Thanks ,

We followed you and are able to delete the locally created object from Offline Store after successful flush and refresh. But Update is not happening in the BE.

Note: We are using OData Services published on NetWeaver Gateway (v7.0).

We followed below steps.

1. We kept the Key field blank and created object in local offline store.

2. We successfully updated the locally created object (in step 1) using Etag and locally generated locator/ URL.(WoHeaderSet(lodata_sys_edt=X'B2662FF44EBE11E6800080F6C8597C8200000000').

3. We flushed the store. Two batch requests should go to BE, first one is for create and other for update.

4. First batch executed successfully i.e. object got created in the BE with original key.

5. While execution of second batch request, it is failing and giving us 'Invalid key name in key predicate' error in BE. Because the resource path in request body is coming as below.

     PUT WoHeaderSet(lodata_sys_edt=X'B2662FF44EBE11E6800080F6C8597C8200000000')      HTTP/1.1

     Content-Type: application/json

     Accept: application/json;q=1, application/atom+xml;q=0.5

6. We refreshed the store and we got the newly created object back to FE and we notice that locally generated object got deleted automatically.

We had also posted the similar 'Invalid key name in key predicate' issue separately. Below is the link. Please refer it for more explanation.

Invalid Key Name in Key predicate when updating... | SCN

Kindly help us.

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

Thanks ,

Yes, our scenario is exactly what you have highlighted. Appreciating your effort for quick reply.

We also have same thought of implementing our own logic to delete local objects after refresh by detecting some flag.

Let's wait for Dan's reply. If there would be nothing more that we could do then we have to implement our own logic. In that case if we want any clarification we will reach out to you.

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

It is very important to understand REST concepts and follow these steps in both sides (BE and FE) and of course to understand mirroring concept and the difference in between to create items in FE and receive items from BE, in the first case it is necessary to return items sent to complete correctly the mirror..

Former Member
0 Kudos

We saw this in our environment also at one time.  The SAP Mobile Platform Server should be handling the mapping of the locator url/key to the real keys during that same flush, so you shouldn't see the locator URL ever get to the SAP Odata Service.

Can you share the following to troubleshoot?

- The request payloads for the POST and PUT, and the reponses if possible

- The relevant metadata for the entites

One thing we had to do was make sure the real new keys/object data is being returned properly in the response to the CREATE request.

Former Member
0 Kudos

Hi ,

First of all thanks for your quick response.

We verified that our service is returning the newly created entity in response to the create request.

Captured the response from create request in a Rest Client for your reference. Please take a look and suggest whether we are getting the expected response or not?

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

Hi ,

We are returning the newly created entities back. But we are not able find refresh success call back method in SDK, where we could write our own code for deleting the local objects after successful refresh?

Is there any such callback method available? If not then please suggest us, where we should write the code to delete locally created objects?

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

Definitely it is not needed to write a code to delete locally objects/items.. if you make DELETE locally, this method will be sent to the BE when the user synchonizes.. if you have not correctly implemented this method in BE, behavior could be random in the future.

I think I have the solution for you  😉   please read the next post it was created by me.

In this post you can see a screenshot of my request/response and it is the same example attached by you, but not the concept.. 

Former Member
0 Kudos

Hi / ,

Thanks a ton for helping us out!!

It would have been very difficult if you both wouldn't guide us.

We are able to do auto deletion of locally created entities and also successfully achieved Update of those entities in BE.

Only one issue, when the create request fails in BE, the local entity gets deleted in that case also. Not sure whether this is an issue or expected behavior but at the end there is lose of Data. Which has to be taken care.

Please guide us if you have any thoughts/ suggestions.

Thanks & Regards:

Shubham Kansal

Former Member
0 Kudos

Hi / ,

I would like to thank you both again. Your suggestions and help means a lot to us, our fundamentals are clear now about this concept.

Just want to take your suggestions on the below as well.

In case of one - one entity the auto deletion of locally created entity is working properly and we were able to do the updates as well. But when we tried creating deep entities using batch, then the auto deletion is not happening.

We got a few questions:

1) Is it the limitation of SMP?

2) If No for 1st, then do you have any idea or thoughts regarding the same?

3) If Yes for 1st, then Is there any possibility that SMP will start supporting it?

Kindly share your thoughts.

Regards:

Shubham Kansal

Former Member
0 Kudos

1/2.  Yes, at least in part.  The SMP doc states partial support for deep entity -

  • The navigation property used for the deep insert must refer to at most one entity.

For us this made it unusable, as we have a one to many relationship instead of a one to one.

Offline OData Version Support and Limitations - Developer - SAP Library

3.  I have no idea.  I have not heard or seen any plans to change this, but SAP would have to respond to that one.  I would suggest opening a support ticket to ask.

Former Member
0 Kudos

Error handling is a manual process/coding at this time.  (also see the note about Deep Inserts here)

Offline OData Conflicts and Errors - Developer - SAP Library

Basically the flow as I understand it is, at the completion of the flush() API the ErrorArchive entity set is populated in the offline store with any errors.  So any data that generated BE errors is MOVED to the ErrorArchive. (it will be missing from the normal data in the offline store).  You have to write code which re-applies the changes which are now stored in the ErrorArchive, or else the data will be lost the next time you clear the ErrorArchive.

I have heard that they would be making this a little smarter/more automated in the future, but for now it is still a manual process.

Former Member
0 Kudos

Hi ,

Thanks a lot for your time and guidance. That was really a great help. Now our fundamentals are more clear.

Kind Regards:

Shubham R Kansal

Answers (0)