SlideShare a Scribd company logo
1 of 31
Download to read offline
Reliable, Fast, Engaging Offline-First
Architecture for JavaScript Applications
Andrejus Baranovskis, CEO andTechnical Expert, Red Samurai Consulting
Oracle ACE Director and Oracle Groundbreaker Ambassador
Florin Marcus,Technical Expert, Red Samurai Consulting
Oracle ExpertsTeam
ADF, JET, ORACLE FUSION, ORACLE CLOUD, MACHINE LEARNING
Oracle PaaS Partner Community Award for Outstanding Java Cloud
Service Contribution 2017
AGENDA
• Offline-First Architecture Why and How
• Technical Implementation
• Solution WalkThrough
• Offline PersistenceToolkit Config for JavaScript (Oracle JET)
OFFLINE-FIRST ARCHITECTURE
WHY AND HOW
No Wi-Fi?
No Problem
Build web/mobile applications that can work great,
whatever the connection
TECHNICAL IMPLEMENTATION
Oracle JET
Offline PersistenceToolkit
Online
Log Request for Replay
Local Storage for
Temporary Data
request/response yes
no
KEY POINTS
• Business logic code stays the same, simple for developers, no code
intrusion with offline toolkit API
• API is very rich, many options to override and control
• Configurable and flexible, e.g. store factory can be changed
• API is heavily based on JS Promise - represents the eventual completion
(or failure) of an asynchronous operation, and its resulting value
KEY POINTS
• Offline:
• Request is logged and inserted into replay queue automatically
• If user is changing data, developer must implement request update logic - in custom
handlePatch or handlePost methods
• Online:
• Possible to define before and after synch listeners.This helps to control request data
• Can control request synchronisation queue execution
SOLUTION WALKTHROUGH
ENDPOINT REGISTRATION
Register
Endpoint
Define Shredder and
Query Handler
Provide handlePatch
method
Define
before/after
listeners
ENDPOINT REGISTRATION
persistenceManager.init().then(function() {
persistenceManager.register({scope: '/Employees'})
.then(function(registration) {
var responseProxy = defaultResponseProxy.getResponseProxy({
jsonProcessor: {
shredder: oracleRestJsonShredding.getShredder('emp', 'EmployeeId'),
unshredder: oracleRestJsonShredding.getUnshredder()
},
queryHandler: queryHandlers.getOracleRestQueryHandler('emp'),
requestHandlerOverride: {handlePatch: customHandlePatch}
});
var fetchListener = responseProxy.getFetchEventListener();
registration.addEventListener('fetch', fetchListener);
// initial data load
self.fetchData();
});
// handles request data before synch
persistenceManager.getSyncManager().addEventListener('beforeSyncRequest', self.beforeRequestListener, '/Employees' );
// handles response data after synch
persistenceManager.getSyncManager().addEventListener('syncRequest', self.afterRequestListener, '/Employees' );
});
OFFLINE UPDATE OR CREATION
Offline
yes
Get request
data
Open offline
store
Find data by
key in offline
store
Update data
in offline store
OFFLINE UPDATE OR CREATION
var customHandlePatch = function(request) {
if (!persistenceManager.isOnline()) {
persistenceUtils.requestToJSON(request).then(function (data) {
var requestData = JSON.parse(data.body.text);
persistenceStoreManager.openStore('emp').then(function (store) {
store.findByKey(requestData.EmployeeId).then(function (data) {
data.FirstName = requestData.FirstName;
data.ChangeIndicatorAttr = requestData.ChangeIndicatorAttr;
store.upsert(requestData.EmployeeId, JSON.parse('{}'), data);
})
});
})
var init = {'status': 503, 'statusText': 'Edit will be processed when online'};
return Promise.resolve(new Response(null, init));
} else {
return persistenceManager.browserFetch(request);
}
};
ONLINE REPLAY
Check if request
should be
replayed
Execute replay If replay error occurs,
ask user feedback and
read info from response
Clear up
helper variables
when replay
completes
ONLINE REPLAY
persistenceManager.getSyncManager().sync({preflightOptionsRequest: 'disabled'}).then(function () {
employeeSynchMap = {};
console.log('SYNCH DONE');
}, function (error) {
var statusCode = error.response.status;
if (statusCode == 409) {
// conflict during offline data synch
$("#md3").ojDialog("open");
synchErrorRequestId = error.requestId;
var response = error.response;
response.json().then(function (value) {
self.onlineConflictResolutionTitle('Conflict resolution: ' + value.FirstName);
synchErrorChangeIndicatorAttr = value.ChangeIndicatorAttr;
});
}
}
);
AFTER REQUEST LISTENER
Get response
data
Update local change
indicator value with the
one from response
Save data ID and change
indicator value
AFTER REQUEST LISTENER
self.afterRequestListener = function (event) {
// invoked if offline synch for request was success, to bring back values updated in backend
var statusCode = event.response.status;
if (statusCode == 200) {
event.response.json().then(function(response) {
var id = response.EmployeeId;
var changeIndicatorAttr = response.ChangeIndicatorAttr;
for (var i = 0; i < self.allItems().length; i++) {
if (self.allItems()[i].id === id) {
self.allItems.splice(i, 1, {"id": self.allItems()[i].id, "firstName": self.allItems()[i].firstName,
"lastName": self.allItems()[i].lastName, "email": self.allItems()[i].email,
"phoneNumber": self.allItems()[i].phoneNumber,
"changeIndicatorAttr": changeIndicatorAttr});
employeeSynchMap[id] = changeIndicatorAttr;
console.log('UPDATE SUCCESS IN SYNCH FOR: ' + id + ',WITH NEW CHANGE INDICATOR: ' + changeIndicatorAttr);
break;
}
}
});
}
return Promise.resolve({action: 'continue'});
}
BEFORE REQUEST LISTENER
Construct request
promise
Get request
data
Check if change
indicator value
must be updated
Update request
and continue
BEFORE REQUEST LISTENER
self.beforeRequestListener = function (event) {
var request = event.request;
return new Promise(function (resolve, reject) {
persistenceUtils.requestToJSON(request).then(function (data) {
var empl = JSON.parse(data.body.text);
var employeeId = empl.EmployeeId;
var updateRequest = false;
for (var i in employeeSynchMap) {
if (parseInt(i) === parseInt(employeeId)) {
updateRequest = true;
var changeIndicatorVal = employeeSynchMap[i];
empl.ChangeIndicatorAttr = changeIndicatorVal;
data.body.text = JSON.stringify(empl);
persistenceUtils.requestFromJSON(data).then(function (updatedRequest) {
resolve({action: 'replay', request: updatedRequest});
});
break;
}}
if (!updateRequest) {
resolve({action: 'continue'});
}
CONFLICT - APPLY CLIENT CHANGES
Remove request Read request
data
Update change
indicator value and
construct new request
Insert new request
into queue and call
replay
CONFLICT - APPLY CLIENT CHANGES
self.applyOfflineClientChangesToServer = function(event) {
persistenceManager.getSyncManager().removeRequest(synchErrorRequestId).then(function (request) {
$("#md3").ojDialog("close");
persistenceUtils.requestToJSON(request).then(function (requestData) {
var requestPayload = JSON.parse(requestData.body.text);
requestPayload.ChangeIndicatorAttr = synchErrorChangeIndicatorAttr;
requestData.body.text = JSON.stringify(requestPayload);
persistenceUtils.requestFromJSON(requestData).then(function (request) {
persistenceManager.getSyncManager().insertRequest(request).then(function () {
self.synchOfflineChanges();
});
});
});
});
}
CONFLICT - APPLY SERVER CHANGES
Refresh client side entry
by calling backend
service
Call replay to
continue
Remove request Read request
data
CONFLICT - APPLY SERVER CHANGES
self.cancelOfflineClientChangesToServer = function(event) {
persistenceManager.getSyncManager().removeRequest(synchErrorRequestId).then(function (request) {
$("#md3").ojDialog("close");
persistenceUtils.requestToJSON(request).then(function (requestData) {
var requestPayload = JSON.parse(requestData.body.text);
var employeeId = requestPayload.EmployeeId;
var searchUrl = empls.getEmployeesEndpointURL() + "/" + employeeId;
self.refreshEntry(searchUrl);
});
self.synchOfflineChanges();
});
}
OFFLINE PERSISTENCETOOLKIT CONFIG
FOR JAVASCRIPT (ORACLE JET)
PATH MAPPING: OFFLINETOOLKIT
"offline": {
"cdn": "",
"cwd": "node_modules/@oracle/offline-persistence-toolkit/dist/debug",
"debug": {
"src": ["*.js", "impl/*.js"],
"path": "libs/offline-persistence-toolkit/v1.1.5/dist",
"cdnPath": ""
}
}
PATH MAPPING: POUCH DB
"pouchdb": {
"cdn": "",
"cwd": "node_modules/pouchdb/dist",
"debug": {
"src": ["*.js"],
"path": "libs/pouchdb/v6.3.4/dist/pouchdb.js",
"cdnPath": ""
}
}
require(['pouchdb'], function (pouchdb) {
window.PouchDB = pouchdb;
});
DEFINE BLOCK FOR OFFLINETOOLKIT
define(['ojs/ojcore', 'knockout', 'jquery',
'offline/persistenceStoreManager',
'offline/pouchDBPersistenceStoreFactory',
'offline/persistenceManager',
'offline/defaultResponseProxy',
'offline/oracleRestJsonShredding',
'offline/queryHandlers',
'offline/persistenceUtils',
'offline/impl/logger',
'viewModels/helpers/employeesHelper',
QUESTIONS
CONTACTS
• Andrejus Baranovskis (https://andrejusb.blogspot.com)
• Email: abaranovskis@redsamuraiconsulting.com
• Twitter: @andrejusb
• LinkedIn: https://www.linkedin.com/in/andrejus-baranovskis-251b392
• Web: http://redsamuraiconsulting.com
REFERENCES
• Source Code on GitHub - https://bit.ly/2PU4iaw
• Oracle OfflineToolkit on GitHub - https://bit.ly/2I7Nr11
• Oracle JET - https://bit.ly/2O21GtS

More Related Content

Similar to Reliable, Fast, Engaging Offline-First Architecture for JavaScript Applications

Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Joe Keeley
 
Introduction to Angular js
Introduction to Angular jsIntroduction to Angular js
Introduction to Angular jsMustafa Gamal
 
Testdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTestdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTruls Jørgensen
 
CiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForceCiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForceCiklum Ukraine
 
API Days Australia - Automatic Testing of (RESTful) API Documentation
API Days Australia  - Automatic Testing of (RESTful) API DocumentationAPI Days Australia  - Automatic Testing of (RESTful) API Documentation
API Days Australia - Automatic Testing of (RESTful) API DocumentationRouven Weßling
 
Service workers and the role they play in modern day web apps
Service workers and the role they play in modern day web appsService workers and the role they play in modern day web apps
Service workers and the role they play in modern day web appsMukul Jain
 
Introduction to Struts
Introduction to StrutsIntroduction to Struts
Introduction to Strutselliando dias
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
Asynchronous Interfaces
Asynchronous InterfacesAsynchronous Interfaces
Asynchronous Interfacesmaccman
 
How to separate the f2 e and sde in web development for_taobao
How to separate the f2 e and sde in web development for_taobaoHow to separate the f2 e and sde in web development for_taobao
How to separate the f2 e and sde in web development for_taobaotaobao.com
 
Angular resolver tutorial
Angular resolver tutorialAngular resolver tutorial
Angular resolver tutorialKaty Slemon
 
Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Paco de la Cruz
 
Vertx - Reactive & Distributed
Vertx - Reactive & DistributedVertx - Reactive & Distributed
Vertx - Reactive & DistributedOrkhan Gasimov
 
Velocity EU 2014 — Offline-first web apps
Velocity EU 2014 — Offline-first web appsVelocity EU 2014 — Offline-first web apps
Velocity EU 2014 — Offline-first web appsandrewsmatt
 

Similar to Reliable, Fast, Engaging Offline-First Architecture for JavaScript Applications (20)

Introduction to BreezeJs
Introduction to BreezeJsIntroduction to BreezeJs
Introduction to BreezeJs
 
Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019Rethinking Syncing at AltConf 2019
Rethinking Syncing at AltConf 2019
 
Introduction to Angular js
Introduction to Angular jsIntroduction to Angular js
Introduction to Angular js
 
Testdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinnerTestdrevet javautvikling på objektorienterte skinner
Testdrevet javautvikling på objektorienterte skinner
 
CiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForceCiklumJavaSat_15112011:Alex Kruk VMForce
CiklumJavaSat_15112011:Alex Kruk VMForce
 
API Days Australia - Automatic Testing of (RESTful) API Documentation
API Days Australia  - Automatic Testing of (RESTful) API DocumentationAPI Days Australia  - Automatic Testing of (RESTful) API Documentation
API Days Australia - Automatic Testing of (RESTful) API Documentation
 
Ajax Tuturial
Ajax TuturialAjax Tuturial
Ajax Tuturial
 
Service workers and the role they play in modern day web apps
Service workers and the role they play in modern day web appsService workers and the role they play in modern day web apps
Service workers and the role they play in modern day web apps
 
Introduction to Struts
Introduction to StrutsIntroduction to Struts
Introduction to Struts
 
Struts Intro
Struts IntroStruts Intro
Struts Intro
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Asynchronous Interfaces
Asynchronous InterfacesAsynchronous Interfaces
Asynchronous Interfaces
 
RIA
RIARIA
RIA
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
How to separate the f2 e and sde in web development for_taobao
How to separate the f2 e and sde in web development for_taobaoHow to separate the f2 e and sde in web development for_taobao
How to separate the f2 e and sde in web development for_taobao
 
Thinking Beyond ORM in JPA
Thinking Beyond ORM in JPAThinking Beyond ORM in JPA
Thinking Beyond ORM in JPA
 
Angular resolver tutorial
Angular resolver tutorialAngular resolver tutorial
Angular resolver tutorial
 
Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30)
 
Vertx - Reactive & Distributed
Vertx - Reactive & DistributedVertx - Reactive & Distributed
Vertx - Reactive & Distributed
 
Velocity EU 2014 — Offline-first web apps
Velocity EU 2014 — Offline-first web appsVelocity EU 2014 — Offline-first web apps
Velocity EU 2014 — Offline-first web apps
 

More from andrejusb

Machine Learning Applied - Tabular Dataset Models and Sentiment Analysis
Machine Learning Applied - Tabular Dataset Models and Sentiment AnalysisMachine Learning Applied - Tabular Dataset Models and Sentiment Analysis
Machine Learning Applied - Tabular Dataset Models and Sentiment Analysisandrejusb
 
JavaScript Development on Steroids with Oracle Visual Builder
JavaScript Development on Steroids with Oracle Visual BuilderJavaScript Development on Steroids with Oracle Visual Builder
JavaScript Development on Steroids with Oracle Visual Builderandrejusb
 
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlowMachine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlowandrejusb
 
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor...
 Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor... Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor...
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor...andrejusb
 
Microservice Approach for Web Development with Micro Frontends
Microservice Approach for Web Development with Micro FrontendsMicroservice Approach for Web Development with Micro Frontends
Microservice Approach for Web Development with Micro Frontendsandrejusb
 
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensorflow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorflowMachine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensorflow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensorflowandrejusb
 
Oracle Development Cloud Service
Oracle Development Cloud ServiceOracle Development Cloud Service
Oracle Development Cloud Serviceandrejusb
 
Oracle Java Cloud Service: How to Estimate Production System Performance
Oracle Java Cloud Service: How to Estimate Production System PerformanceOracle Java Cloud Service: How to Estimate Production System Performance
Oracle Java Cloud Service: How to Estimate Production System Performanceandrejusb
 
Essential Kit for Oracle JET Programming
Essential Kit for Oracle JET ProgrammingEssential Kit for Oracle JET Programming
Essential Kit for Oracle JET Programmingandrejusb
 
Oracle JET and ADF BC REST Production Experience with Oracle Java Cloud
Oracle JET and ADF BC REST Production Experience with Oracle Java CloudOracle JET and ADF BC REST Production Experience with Oracle Java Cloud
Oracle JET and ADF BC REST Production Experience with Oracle Java Cloudandrejusb
 
Offline Web with Oracle JET
Offline Web with Oracle JETOffline Web with Oracle JET
Offline Web with Oracle JETandrejusb
 
End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...
End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...
End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...andrejusb
 
Forms, ADF and JET a Non-Aggression Pact
Forms, ADF and JET a Non-Aggression PactForms, ADF and JET a Non-Aggression Pact
Forms, ADF and JET a Non-Aggression Pactandrejusb
 
Oracle JET CRUD and ADF BC REST
Oracle JET CRUD and ADF BC RESTOracle JET CRUD and ADF BC REST
Oracle JET CRUD and ADF BC RESTandrejusb
 
Oracle JET and WebSocket
Oracle JET and WebSocketOracle JET and WebSocket
Oracle JET and WebSocketandrejusb
 
Oracle Alta UI Patterns for Enterprise Applications and Responsive UI Support
Oracle Alta UI Patterns for Enterprise Applications and Responsive UI SupportOracle Alta UI Patterns for Enterprise Applications and Responsive UI Support
Oracle Alta UI Patterns for Enterprise Applications and Responsive UI Supportandrejusb
 
ADF Mythbusters UKOUG'14
ADF Mythbusters UKOUG'14ADF Mythbusters UKOUG'14
ADF Mythbusters UKOUG'14andrejusb
 
Data Caching Strategies for Oracle Mobile Application Framework
Data Caching Strategies for Oracle Mobile Application FrameworkData Caching Strategies for Oracle Mobile Application Framework
Data Caching Strategies for Oracle Mobile Application Frameworkandrejusb
 
ADF Development Survival Kit
ADF Development Survival KitADF Development Survival Kit
ADF Development Survival Kitandrejusb
 
ADF Anti-Patterns: Dangerous Tutorials
ADF Anti-Patterns: Dangerous TutorialsADF Anti-Patterns: Dangerous Tutorials
ADF Anti-Patterns: Dangerous Tutorialsandrejusb
 

More from andrejusb (20)

Machine Learning Applied - Tabular Dataset Models and Sentiment Analysis
Machine Learning Applied - Tabular Dataset Models and Sentiment AnalysisMachine Learning Applied - Tabular Dataset Models and Sentiment Analysis
Machine Learning Applied - Tabular Dataset Models and Sentiment Analysis
 
JavaScript Development on Steroids with Oracle Visual Builder
JavaScript Development on Steroids with Oracle Visual BuilderJavaScript Development on Steroids with Oracle Visual Builder
JavaScript Development on Steroids with Oracle Visual Builder
 
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlowMachine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorFlow
 
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor...
 Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor... Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor...
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensor...
 
Microservice Approach for Web Development with Micro Frontends
Microservice Approach for Web Development with Micro FrontendsMicroservice Approach for Web Development with Micro Frontends
Microservice Approach for Web Development with Micro Frontends
 
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensorflow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and TensorflowMachine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensorflow
Machine Learning Applied - Contextual Chatbots Coding, Oracle JET and Tensorflow
 
Oracle Development Cloud Service
Oracle Development Cloud ServiceOracle Development Cloud Service
Oracle Development Cloud Service
 
Oracle Java Cloud Service: How to Estimate Production System Performance
Oracle Java Cloud Service: How to Estimate Production System PerformanceOracle Java Cloud Service: How to Estimate Production System Performance
Oracle Java Cloud Service: How to Estimate Production System Performance
 
Essential Kit for Oracle JET Programming
Essential Kit for Oracle JET ProgrammingEssential Kit for Oracle JET Programming
Essential Kit for Oracle JET Programming
 
Oracle JET and ADF BC REST Production Experience with Oracle Java Cloud
Oracle JET and ADF BC REST Production Experience with Oracle Java CloudOracle JET and ADF BC REST Production Experience with Oracle Java Cloud
Oracle JET and ADF BC REST Production Experience with Oracle Java Cloud
 
Offline Web with Oracle JET
Offline Web with Oracle JETOffline Web with Oracle JET
Offline Web with Oracle JET
 
End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...
End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...
End-to-End Cloud: Oracle Java Cloud, Oracle Mobile Cloud Service, Oracle MAF,...
 
Forms, ADF and JET a Non-Aggression Pact
Forms, ADF and JET a Non-Aggression PactForms, ADF and JET a Non-Aggression Pact
Forms, ADF and JET a Non-Aggression Pact
 
Oracle JET CRUD and ADF BC REST
Oracle JET CRUD and ADF BC RESTOracle JET CRUD and ADF BC REST
Oracle JET CRUD and ADF BC REST
 
Oracle JET and WebSocket
Oracle JET and WebSocketOracle JET and WebSocket
Oracle JET and WebSocket
 
Oracle Alta UI Patterns for Enterprise Applications and Responsive UI Support
Oracle Alta UI Patterns for Enterprise Applications and Responsive UI SupportOracle Alta UI Patterns for Enterprise Applications and Responsive UI Support
Oracle Alta UI Patterns for Enterprise Applications and Responsive UI Support
 
ADF Mythbusters UKOUG'14
ADF Mythbusters UKOUG'14ADF Mythbusters UKOUG'14
ADF Mythbusters UKOUG'14
 
Data Caching Strategies for Oracle Mobile Application Framework
Data Caching Strategies for Oracle Mobile Application FrameworkData Caching Strategies for Oracle Mobile Application Framework
Data Caching Strategies for Oracle Mobile Application Framework
 
ADF Development Survival Kit
ADF Development Survival KitADF Development Survival Kit
ADF Development Survival Kit
 
ADF Anti-Patterns: Dangerous Tutorials
ADF Anti-Patterns: Dangerous TutorialsADF Anti-Patterns: Dangerous Tutorials
ADF Anti-Patterns: Dangerous Tutorials
 

Recently uploaded

"Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency""Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency"growthgrids
 
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...APNIC
 
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制pxcywzqs
 
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime BalliaBallia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Balliameghakumariji156
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsMonica Sydney
 
Call girls Service in Ajman 0505086370 Ajman call girls
Call girls Service in Ajman 0505086370 Ajman call girlsCall girls Service in Ajman 0505086370 Ajman call girls
Call girls Service in Ajman 0505086370 Ajman call girlsMonica Sydney
 
Vip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac Room
Vip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac RoomVip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac Room
Vip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac Roommeghakumariji156
 
Down bad crying at the gym t shirtsDown bad crying at the gym t shirts
Down bad crying at the gym t shirtsDown bad crying at the gym t shirtsDown bad crying at the gym t shirtsDown bad crying at the gym t shirts
Down bad crying at the gym t shirtsDown bad crying at the gym t shirtsrahman018755
 
💚 Call Girls Bahraich 9332606886 High Profile Call Girls You Can Get The S...
💚 Call Girls Bahraich   9332606886  High Profile Call Girls You Can Get The S...💚 Call Girls Bahraich   9332606886  High Profile Call Girls You Can Get The S...
💚 Call Girls Bahraich 9332606886 High Profile Call Girls You Can Get The S...Sareena Khatun
 
Meaning of On page SEO & its process in detail.
Meaning of On page SEO & its process in detail.Meaning of On page SEO & its process in detail.
Meaning of On page SEO & its process in detail.krishnachandrapal52
 
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime NagercoilNagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoilmeghakumariji156
 
一比一原版犹他大学毕业证如何办理
一比一原版犹他大学毕业证如何办理一比一原版犹他大学毕业证如何办理
一比一原版犹他大学毕业证如何办理F
 
Delivery in 20 Mins Call Girls Cuttack 9332606886 HOT & SEXY Models beautifu...
Delivery in 20 Mins Call Girls Cuttack  9332606886 HOT & SEXY Models beautifu...Delivery in 20 Mins Call Girls Cuttack  9332606886 HOT & SEXY Models beautifu...
Delivery in 20 Mins Call Girls Cuttack 9332606886 HOT & SEXY Models beautifu...Sareena Khatun
 
一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理
一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理
一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理AS
 
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrStory Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrHenryBriggs2
 
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查ydyuyu
 
Washington Football Commanders Redskins Feathers Shirt
Washington Football Commanders Redskins Feathers ShirtWashington Football Commanders Redskins Feathers Shirt
Washington Football Commanders Redskins Feathers Shirtrahman018755
 
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查ydyuyu
 
Mira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
Mira Road Housewife Call Girls 07506202331, Nalasopara Call GirlsMira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
Mira Road Housewife Call Girls 07506202331, Nalasopara Call GirlsPriya Reddy
 
Local Call Girls in Jharsuguda 9332606886 HOT & SEXY Models beautiful and ch...
Local Call Girls in Jharsuguda  9332606886 HOT & SEXY Models beautiful and ch...Local Call Girls in Jharsuguda  9332606886 HOT & SEXY Models beautiful and ch...
Local Call Girls in Jharsuguda 9332606886 HOT & SEXY Models beautiful and ch...Sareena Khatun
 

Recently uploaded (20)

"Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency""Boost Your Digital Presence: Partner with a Leading SEO Agency"
"Boost Your Digital Presence: Partner with a Leading SEO Agency"
 
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
APNIC Policy Roundup, presented by Sunny Chendi at the 5th ICANN APAC-TWNIC E...
 
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
一比一原版(Offer)康考迪亚大学毕业证学位证靠谱定制
 
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime BalliaBallia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
Ballia Escorts Service Girl ^ 9332606886, WhatsApp Anytime Ballia
 
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi EscortsIndian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
Indian Escort in Abu DHabi 0508644382 Abu Dhabi Escorts
 
Call girls Service in Ajman 0505086370 Ajman call girls
Call girls Service in Ajman 0505086370 Ajman call girlsCall girls Service in Ajman 0505086370 Ajman call girls
Call girls Service in Ajman 0505086370 Ajman call girls
 
Vip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac Room
Vip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac RoomVip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac Room
Vip Firozabad Phone 8250092165 Escorts Service At 6k To 30k Along With Ac Room
 
Down bad crying at the gym t shirtsDown bad crying at the gym t shirts
Down bad crying at the gym t shirtsDown bad crying at the gym t shirtsDown bad crying at the gym t shirtsDown bad crying at the gym t shirts
Down bad crying at the gym t shirtsDown bad crying at the gym t shirts
 
💚 Call Girls Bahraich 9332606886 High Profile Call Girls You Can Get The S...
💚 Call Girls Bahraich   9332606886  High Profile Call Girls You Can Get The S...💚 Call Girls Bahraich   9332606886  High Profile Call Girls You Can Get The S...
💚 Call Girls Bahraich 9332606886 High Profile Call Girls You Can Get The S...
 
Meaning of On page SEO & its process in detail.
Meaning of On page SEO & its process in detail.Meaning of On page SEO & its process in detail.
Meaning of On page SEO & its process in detail.
 
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime NagercoilNagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
Nagercoil Escorts Service Girl ^ 9332606886, WhatsApp Anytime Nagercoil
 
一比一原版犹他大学毕业证如何办理
一比一原版犹他大学毕业证如何办理一比一原版犹他大学毕业证如何办理
一比一原版犹他大学毕业证如何办理
 
Delivery in 20 Mins Call Girls Cuttack 9332606886 HOT & SEXY Models beautifu...
Delivery in 20 Mins Call Girls Cuttack  9332606886 HOT & SEXY Models beautifu...Delivery in 20 Mins Call Girls Cuttack  9332606886 HOT & SEXY Models beautifu...
Delivery in 20 Mins Call Girls Cuttack 9332606886 HOT & SEXY Models beautifu...
 
一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理
一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理
一比一原版(Dundee毕业证书)英国爱丁堡龙比亚大学毕业证如何办理
 
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrStory Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
Story Board.pptxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
 
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
原版制作美国爱荷华大学毕业证(iowa毕业证书)学位证网上存档可查
 
Washington Football Commanders Redskins Feathers Shirt
Washington Football Commanders Redskins Feathers ShirtWashington Football Commanders Redskins Feathers Shirt
Washington Football Commanders Redskins Feathers Shirt
 
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
哪里办理美国迈阿密大学毕业证(本硕)umiami在读证明存档可查
 
Mira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
Mira Road Housewife Call Girls 07506202331, Nalasopara Call GirlsMira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
Mira Road Housewife Call Girls 07506202331, Nalasopara Call Girls
 
Local Call Girls in Jharsuguda 9332606886 HOT & SEXY Models beautiful and ch...
Local Call Girls in Jharsuguda  9332606886 HOT & SEXY Models beautiful and ch...Local Call Girls in Jharsuguda  9332606886 HOT & SEXY Models beautiful and ch...
Local Call Girls in Jharsuguda 9332606886 HOT & SEXY Models beautiful and ch...
 

Reliable, Fast, Engaging Offline-First Architecture for JavaScript Applications

  • 1. Reliable, Fast, Engaging Offline-First Architecture for JavaScript Applications Andrejus Baranovskis, CEO andTechnical Expert, Red Samurai Consulting Oracle ACE Director and Oracle Groundbreaker Ambassador Florin Marcus,Technical Expert, Red Samurai Consulting
  • 2. Oracle ExpertsTeam ADF, JET, ORACLE FUSION, ORACLE CLOUD, MACHINE LEARNING Oracle PaaS Partner Community Award for Outstanding Java Cloud Service Contribution 2017
  • 3. AGENDA • Offline-First Architecture Why and How • Technical Implementation • Solution WalkThrough • Offline PersistenceToolkit Config for JavaScript (Oracle JET)
  • 5. No Wi-Fi? No Problem Build web/mobile applications that can work great, whatever the connection
  • 7. Oracle JET Offline PersistenceToolkit Online Log Request for Replay Local Storage for Temporary Data request/response yes no
  • 8. KEY POINTS • Business logic code stays the same, simple for developers, no code intrusion with offline toolkit API • API is very rich, many options to override and control • Configurable and flexible, e.g. store factory can be changed • API is heavily based on JS Promise - represents the eventual completion (or failure) of an asynchronous operation, and its resulting value
  • 9. KEY POINTS • Offline: • Request is logged and inserted into replay queue automatically • If user is changing data, developer must implement request update logic - in custom handlePatch or handlePost methods • Online: • Possible to define before and after synch listeners.This helps to control request data • Can control request synchronisation queue execution
  • 11. ENDPOINT REGISTRATION Register Endpoint Define Shredder and Query Handler Provide handlePatch method Define before/after listeners
  • 12. ENDPOINT REGISTRATION persistenceManager.init().then(function() { persistenceManager.register({scope: '/Employees'}) .then(function(registration) { var responseProxy = defaultResponseProxy.getResponseProxy({ jsonProcessor: { shredder: oracleRestJsonShredding.getShredder('emp', 'EmployeeId'), unshredder: oracleRestJsonShredding.getUnshredder() }, queryHandler: queryHandlers.getOracleRestQueryHandler('emp'), requestHandlerOverride: {handlePatch: customHandlePatch} }); var fetchListener = responseProxy.getFetchEventListener(); registration.addEventListener('fetch', fetchListener); // initial data load self.fetchData(); }); // handles request data before synch persistenceManager.getSyncManager().addEventListener('beforeSyncRequest', self.beforeRequestListener, '/Employees' ); // handles response data after synch persistenceManager.getSyncManager().addEventListener('syncRequest', self.afterRequestListener, '/Employees' ); });
  • 13. OFFLINE UPDATE OR CREATION Offline yes Get request data Open offline store Find data by key in offline store Update data in offline store
  • 14. OFFLINE UPDATE OR CREATION var customHandlePatch = function(request) { if (!persistenceManager.isOnline()) { persistenceUtils.requestToJSON(request).then(function (data) { var requestData = JSON.parse(data.body.text); persistenceStoreManager.openStore('emp').then(function (store) { store.findByKey(requestData.EmployeeId).then(function (data) { data.FirstName = requestData.FirstName; data.ChangeIndicatorAttr = requestData.ChangeIndicatorAttr; store.upsert(requestData.EmployeeId, JSON.parse('{}'), data); }) }); }) var init = {'status': 503, 'statusText': 'Edit will be processed when online'}; return Promise.resolve(new Response(null, init)); } else { return persistenceManager.browserFetch(request); } };
  • 15. ONLINE REPLAY Check if request should be replayed Execute replay If replay error occurs, ask user feedback and read info from response Clear up helper variables when replay completes
  • 16. ONLINE REPLAY persistenceManager.getSyncManager().sync({preflightOptionsRequest: 'disabled'}).then(function () { employeeSynchMap = {}; console.log('SYNCH DONE'); }, function (error) { var statusCode = error.response.status; if (statusCode == 409) { // conflict during offline data synch $("#md3").ojDialog("open"); synchErrorRequestId = error.requestId; var response = error.response; response.json().then(function (value) { self.onlineConflictResolutionTitle('Conflict resolution: ' + value.FirstName); synchErrorChangeIndicatorAttr = value.ChangeIndicatorAttr; }); } } );
  • 17. AFTER REQUEST LISTENER Get response data Update local change indicator value with the one from response Save data ID and change indicator value
  • 18. AFTER REQUEST LISTENER self.afterRequestListener = function (event) { // invoked if offline synch for request was success, to bring back values updated in backend var statusCode = event.response.status; if (statusCode == 200) { event.response.json().then(function(response) { var id = response.EmployeeId; var changeIndicatorAttr = response.ChangeIndicatorAttr; for (var i = 0; i < self.allItems().length; i++) { if (self.allItems()[i].id === id) { self.allItems.splice(i, 1, {"id": self.allItems()[i].id, "firstName": self.allItems()[i].firstName, "lastName": self.allItems()[i].lastName, "email": self.allItems()[i].email, "phoneNumber": self.allItems()[i].phoneNumber, "changeIndicatorAttr": changeIndicatorAttr}); employeeSynchMap[id] = changeIndicatorAttr; console.log('UPDATE SUCCESS IN SYNCH FOR: ' + id + ',WITH NEW CHANGE INDICATOR: ' + changeIndicatorAttr); break; } } }); } return Promise.resolve({action: 'continue'}); }
  • 19. BEFORE REQUEST LISTENER Construct request promise Get request data Check if change indicator value must be updated Update request and continue
  • 20. BEFORE REQUEST LISTENER self.beforeRequestListener = function (event) { var request = event.request; return new Promise(function (resolve, reject) { persistenceUtils.requestToJSON(request).then(function (data) { var empl = JSON.parse(data.body.text); var employeeId = empl.EmployeeId; var updateRequest = false; for (var i in employeeSynchMap) { if (parseInt(i) === parseInt(employeeId)) { updateRequest = true; var changeIndicatorVal = employeeSynchMap[i]; empl.ChangeIndicatorAttr = changeIndicatorVal; data.body.text = JSON.stringify(empl); persistenceUtils.requestFromJSON(data).then(function (updatedRequest) { resolve({action: 'replay', request: updatedRequest}); }); break; }} if (!updateRequest) { resolve({action: 'continue'}); }
  • 21. CONFLICT - APPLY CLIENT CHANGES Remove request Read request data Update change indicator value and construct new request Insert new request into queue and call replay
  • 22. CONFLICT - APPLY CLIENT CHANGES self.applyOfflineClientChangesToServer = function(event) { persistenceManager.getSyncManager().removeRequest(synchErrorRequestId).then(function (request) { $("#md3").ojDialog("close"); persistenceUtils.requestToJSON(request).then(function (requestData) { var requestPayload = JSON.parse(requestData.body.text); requestPayload.ChangeIndicatorAttr = synchErrorChangeIndicatorAttr; requestData.body.text = JSON.stringify(requestPayload); persistenceUtils.requestFromJSON(requestData).then(function (request) { persistenceManager.getSyncManager().insertRequest(request).then(function () { self.synchOfflineChanges(); }); }); }); }); }
  • 23. CONFLICT - APPLY SERVER CHANGES Refresh client side entry by calling backend service Call replay to continue Remove request Read request data
  • 24. CONFLICT - APPLY SERVER CHANGES self.cancelOfflineClientChangesToServer = function(event) { persistenceManager.getSyncManager().removeRequest(synchErrorRequestId).then(function (request) { $("#md3").ojDialog("close"); persistenceUtils.requestToJSON(request).then(function (requestData) { var requestPayload = JSON.parse(requestData.body.text); var employeeId = requestPayload.EmployeeId; var searchUrl = empls.getEmployeesEndpointURL() + "/" + employeeId; self.refreshEntry(searchUrl); }); self.synchOfflineChanges(); }); }
  • 25. OFFLINE PERSISTENCETOOLKIT CONFIG FOR JAVASCRIPT (ORACLE JET)
  • 26. PATH MAPPING: OFFLINETOOLKIT "offline": { "cdn": "", "cwd": "node_modules/@oracle/offline-persistence-toolkit/dist/debug", "debug": { "src": ["*.js", "impl/*.js"], "path": "libs/offline-persistence-toolkit/v1.1.5/dist", "cdnPath": "" } }
  • 27. PATH MAPPING: POUCH DB "pouchdb": { "cdn": "", "cwd": "node_modules/pouchdb/dist", "debug": { "src": ["*.js"], "path": "libs/pouchdb/v6.3.4/dist/pouchdb.js", "cdnPath": "" } } require(['pouchdb'], function (pouchdb) { window.PouchDB = pouchdb; });
  • 28. DEFINE BLOCK FOR OFFLINETOOLKIT define(['ojs/ojcore', 'knockout', 'jquery', 'offline/persistenceStoreManager', 'offline/pouchDBPersistenceStoreFactory', 'offline/persistenceManager', 'offline/defaultResponseProxy', 'offline/oracleRestJsonShredding', 'offline/queryHandlers', 'offline/persistenceUtils', 'offline/impl/logger', 'viewModels/helpers/employeesHelper',
  • 30. CONTACTS • Andrejus Baranovskis (https://andrejusb.blogspot.com) • Email: abaranovskis@redsamuraiconsulting.com • Twitter: @andrejusb • LinkedIn: https://www.linkedin.com/in/andrejus-baranovskis-251b392 • Web: http://redsamuraiconsulting.com
  • 31. REFERENCES • Source Code on GitHub - https://bit.ly/2PU4iaw • Oracle OfflineToolkit on GitHub - https://bit.ly/2I7Nr11 • Oracle JET - https://bit.ly/2O21GtS