Showing posts with label Offline. Show all posts
Showing posts with label Offline. Show all posts

Wednesday, October 10, 2018

Oracle Offline Persistence Toolkit - Applying Server Changes

This is my final post related to Oracle Offline Persistence Toolkit. I will show simple example, which explains how to apply server changes, if data conflict comes up. Read previous post about - Oracle Offline Persistence Toolkit - Submitting Client Changes.

To apply server changes is easier, than to apply client changes. You need to remove failed request from sync queue and fetch server data to client by key.

Example of data conflict during sync:


User decides to cancel his changes and bring data from the server. GET is executed to fetch latest data and push it to the client:


In JS code, first of all we remove request from sync queue, in promise we read key value for that request and then refetch data:


Download sample code from GitHub repository.

Sunday, October 7, 2018

Oracle Offline Persistence Toolkit - Submitting Client Changes

One of the key topics related to Oracle Offline Persistence toolkit - submitting client changes to backend when data conflict exists. If data was updated on the backend, while client was offline and client wants to submit his changes - we inform about the conflict and ask what client really wants to do. If client choose to submit changes, this means we should push client changes to the backend with the latest change indicator.

There is a special case, when client updates same data multiple times while offline - during online sync we need to make sure, change indicator will be retrieved in after sync and applied in before sync listeners, to make sure subsequent requests execute correctly. Check my previous post about before request sync listener - Oracle Offline Persistence Toolkit - Before Request Sync Listener.

Example - let's update a record and submit change to the backend:


Assume another user is offline and updates same record:


User updates same record again, before going online. Now we will have two requests in the sync queue:


Once going online, sync will be executed and we will get conflict for the first request (same row was updated already by another user). At this moment, after sync listener will get info about conflict and will cache latest change indicator value returned from backend. If user decides to apply his changes, requests is removed, new request is constructed with the latest change indicator value received from backend and this request is inserted into sync queue:


If same record was updated multiple times, second request will fail too - because this request wasn't updated yet with latest change indicator:


Assuming user decided to apply changes from the second request too, we will update request with latest change indicator and submit it for sync. In after sync listener, change indicator value stored in local cache will be updated.

Successful sync with change indicator = 296:


New change indicator value will be retrieved in after sync listener and applied in before sync listener for the second request, updating same data row:


Here is the code, which allows user to apply changes to backend. We remove failed request, update it and create new request in sync queue, resuming sync process:


Download sample code for the described use case from my GitHub repository.

Tuesday, October 2, 2018

Oracle Offline Persistence Toolkit - Before Request Sync Listener

One more post from me related to Oracle Offline Persistence Toolkit. I already described how after request listener could be useful to read response data after sync - Oracle Offline Persistence Toolkit - After Request Sync Listener. Today will explain when before request listener could be useful. Same as after request listener, it is defined during persistence manager registration:


Before request listener must return promise. We can control resolved action. For example if there is no need to update request, we simply return continue. We would need to update request, if same row is updated multiple times during sync. Change indicator value must be updated in request payload. We read latest change indicator value from array, initialised in after request listener. Request payload is converted to JSON, value updated and then we construct new request and resolve it with replay. API allows to provide new request, by replacing original:


Here is the use case. While offline - update value:


While remaining offline, update same value again:


We should trace executed requests during sync, when going online. First request, initiated by first change is using change indicator value 292:


Second request is using updated change indicator value 293:


Without before and after request listener logic, second request would execute with same change indicator value as the first one. This would lead to data conflict on backend.

Sample application code is available on GitHub.

Friday, September 28, 2018

Oracle Offline Persistence Toolkit - After Request Sync Listener

In my previous post, we learned how to handle replay conflict - Oracle Offline Persistence Toolkit - Reacting to Replay Conflict. Additional important thing to know - how to handle response from request which was replayed during sync (we are talking here about PATCH). It is not as obvious as handling response from direct REST call in callback (there is no callback for response which is synchronised later). You may think, why you would need to handle response, after successful sync. Well there could be multiple reasons - for instance you may read returned value and update value stored on the client.

Listener is registered in Persistence Manager configuration, by adding event listener of type syncRequest for given endpoint:


This is listener code. We are getting response, reading change indicator value (it was updated on the backend and new value is returned in response) and storing it locally on the client. Additionally we maintain array with mapping of change indicator value to updated row ID (in my next post I will explain why this is needed). After request listener must return promise:


On runtime - when request sync is executed, you should see in the log message printed, which shows new change indicator value:


Double check in payload, to make sure request was submitted with previous value:


Check response, you will see new value for change indicator (same as in after request listener):


Sample code can be downloaded from GitHub repository.

Saturday, September 22, 2018

Oracle Offline Persistence Toolkit - Reacting to Replay Conflict

This is next post related to Oracle Offline Persistence Toolkit. Check my previous writing on same subject - Implementing Handle Patch Method in JET Offline Toolkit. Read more about toolkit on GitHub repo.

When application goes online, we call synchronisation method. If at least one of the requests fails, then synchronisation is stopped and error callback is invoked, where we can handle failure. In error callback, we check if failure is related to the conflict - then we open dialog, where user will decide what to do (to force client changes or take server changes). Reading latest change indicator value from response in error callback (to apply it, if user decides to force client changes in the next request):


Dialog is simple - it displays dynamic text for conflicted value and provides user with a choice of actions:


Let's see how it works.

User A editing value Lex and saving it to backend:


User B is offline, editing same value B and saving it in local storage:


We can check it in the log - changes value was stored in local storage:


When going online, pending requests logged offline, will be re-executed. Obviously above request will fail, because same value was changed by another user. Conflict will be reported:


PATCH operation fails with conflict code 409:


User will be asked - how to proceed. To apply changes and override changes in the backend, or on opposite take changes from the backend and bring them to the client:


I will explain how to implement these actions in my next post. In the meantime you can study complete application available on GitHub repo.

Wednesday, September 12, 2018

Implementing Handle Patch Method in JET Offline Toolkit

When executing PATCH requests offline, JET Offline Persistence Toolkit will record that request and synch it to the backend, once online. But it will not update data stored in cache, this is by design. Since cached data will not be updated, search queries against offline cache would not bring results based on latest changes. To solve this we need to implement cache update ourself by providing handle patch method.

Handle patch is configured through requestHandlerOverride property while registering persistence manager:


Sample implementation for handle patch. This method is invoked, when PATCH is executed while offline only. We must read information from request and pass it to cache store. Search for entry in cache based on key, updating record and updating info back to the store:


Let's do offline test - switch browser tab to be offline (you can do it Chrome browser developer tools). Do search and check log from JET Offline Persistence Toolkit - it executes search automatically against cache store:


Update same record, while offline - PATCH request will be recorded for later synchronisation. Our handle patch method will be invoked to write changes to cache store:


You will notice in the log, actions executed from handle patch method. It finds record by key in cache and updates it:


Search by updated value - updated value is found and returned from cache store:


Code is available in GitHub repository.

Thursday, August 9, 2018

Oracle Offline Persistence Toolkit - Controlling Online Replay

Few months ago I had a post about Oracle Offline Persistence toolkit, which integrates well with Oracle JET (JavaScript toolkit from Oracle) - Oracle JET Offline Persistence Toolkit - Offline Update Handling. I'm back to this topic with sample application upgraded to JET 5.1 and offline toolkit upgraded to 1.1.5. In this post I will describe how to control online replay by filtering out some of the requests, to be excluded from replay.

Source code is available on GitHub. Below I describe changes and functionality in the latest commit.

To test online replay, go offline and execute some actions in the sample app - change few records and try to search by first name, also try to use page navigation buttons. You will be able to save changes in offline mode, but if this is your first time loading app and data from other pages wasn't fetch yet, then page navigation would not bring any new results in offline mode (make sure to load more records while online and then go offline):


In online replay manager, I'm filtering out GET requests intentionally. Once going online, I replay only PATCH requests. This is done mainly for a test, to learn how to control replay process. PATCH requests are executed during replay:


Printing out in the log, each GET request which was removed from replay loop:


Replay implementation (I would recommend to read Offline Persistence Toolkit usage doc for more info):


This code is executed, after transition to online status. Calling getSyncLog method from Sync Manager - returns a list of requests pending replay. Promise returns function with array of requests waiting for online replay. I have marked function to be async, this allows to implement sequential loop, where each GET request will be removed one by one in order. This is needed, since removeRequest from Sync Manager is executed in promise and loop would complete too late - after we pass execute replay phase. Read more about sequential loop implementation in JS, when promise is used - JavaScript - Method to Call Backend Logic in Sequential Loop. Once all GET requests are removed, we execute sync method, this will force all remaining requests in queue to be replayed.

Tuesday, March 27, 2018

Oracle JET Offline Persistence Toolkit - Offline Update Handling

Oracle JET Offline Persistence Toolkit supports offline update, create and delete operations. In this post I will describe update use case. Read previous post related to offline toolkit, where I explain how to handle REST pagination, querying and shredding - REST Paging Support by Oracle Offline Persistence in JET.

This gif shows scenario, where we go to offline mode and then changing data in multiple rows. Data update happens offline and each PATCH request is tracked by offline persistence toolkit:


As soon as we go online (Offline checkbox value is changed in Chrome Developer Tools) - requests executed while offline are replayed automatically against backend server:


We should see, how update flow is implemented in JET in this particular case. Once data is changed, we call submitUpdate function. This function in turn calls JET Model API function save. This triggers PATCH call to back-end to update data. If we are offline, JET offline persistence toolkit, transparently records PATCH request to be able to replay it later while online. There are no specific code changes needed by developer to support offline logic during REST call:


Once we go online, listener is invoked and it calls our function synchOfflineChanges. This function triggers request replay to the backend. This means we can control, when requests are replayed. Besides this, we can control each request which failed to be replayed - this is important, when data conflict happens during update in backend:


Online handler is registered with window.addEventListener in the same module, where persistence manager is defined:


Offline Persistence Toolkit 1.1.1 supports extensive logging. You can update to 1.1.1 version by running: npm install @oracle/offline-persistence-toolkit command:


To enable persistence toolkit logger, add persist/impl/logger module to your target module and call logger.option('level', logger.LEVEL_LOG):


Logger prints useful information about offline update, this helps to debug offline functionality:


Download sample application from GitHub repository.

Tuesday, March 6, 2018

REST Paging Support by Oracle Offline Persistence in JET

Oracle Offline Persistence query handler - Oracle Rest Query Handler supports pagination for Oracle ADF BC REST service out of the box. Check my previous post to see how querying works through offline persistence toolkit for ADF BC REST service - Shredding and Querying with Oracle Offline Persistence in JET.

Pagination is a must for large REST resources, its great that Oracle offline persistence toolkit supports it. Let's see it in action.

I navigate through the data with left/right arrows, this triggers REST call with pagination parameters - limit and offset. These are standard parameters supported by ADF BC REST. Requests are executed online:


All pages of data are cached by offline toolkit, if while offline we try to access previously cached page by executing REST request with paging parameters - we will get data from offline toolkit. Now I switch offline and try to navigate to the one of cached pages - data is retrieved from cache automatically:


If I navigate to the page, which was not cached (meaning - not accessed while online) - no results returned. In such situation I can navigate back (paging parameters will be updated) and cached data will be displayed for the page which was cached:


Paging navigation control buttons are calling JS functions to update startIndex:


Sample application is using JET Collection API to execute fetch requests. Collection is extended with getURL function which sets limit and offset parameters to execute paging request:


Once again, make sure to use Oracle Rest Query Handler in offline persistence toolkit configuration:


Fetch function is called through JET Collection API. Start index value is calculated dynamically - this allows to execute paging requests. Same function works online and offline, no need to worry about connection status, all online/offline logic is handled by persistence toolkit:


Sample application for this post is available on GitHub.