16 Add Offline Capabilities to Your Application

Applications that you create in Visual Builder can function even when your device is disconnected from the network. To do this, you can use the Oracle Offline Persistence Toolkit which enables your application to cache data on the client for offline support.

If you use business objects to shape your application's data, you can leverage the object's caching settings to cache data read from a business object on the client. For more information, see Control Data Caching for Business Objects.

Add Offline Support Using the Oracle Offline Persistence Kit

The Oracle Offline Persistence Toolkit is a client-side JavaScript library that helps to provide offline support for your application.

It enables caching for offline support at the HTTP request layer. This support is transparent to the user and is done through the Fetch API and an XHR adapter. HTTP requests made while the client or client device is offline are captured for replay when connection to the server is restored. Additional capabilities include a persistent storage layer, synchronization manager, binary data support, and various configuration APIs for customizing the default behavior. This toolkit can be used in both ServiceWorker and non-ServiceWorker contexts within web apps.

Using the toolkit, you can configure your application to:

  • Download content for offline reading where connectivity isn’t available.

    For example, an application could include product inventory data that a salesperson could download and read at customer sites where connectivity isn’t available.

  • Cache content for improved performance.
  • Perform transactions on the downloaded content where connectivity isn’t available and upload the transactions when connectivity returns.

    For example, the salesperson could visit a site with no Internet access and enter an order for some number of product items. When connectivity returns, the application can automatically send the transaction to the server.

  • Provide conflict resolution when the offline data can’t merge with the server.

    If the salesperson’s request exceeds the amount of available inventory, the application can configure a message asking the salesperson to cancel the order or place the item on back order.

The architecture diagram illustrates the major components of the toolkit and how an application interacts with it:
Responses from REST services to your application must not include either the no-cache or no-store value in the Cache-Control HTTP header as these values prevent the toolkit from working in your application. Work with the administrators of the REST services that your application connects to so that values in the Cache-Control HTTP header are configured appropriately.

Note:

Data caching for business objects is disabled by default, with each object's Resource Cache Control setting defined as Sensitive. This default option combines the no-cache and no-store values to disable data caching. Before you use the Oracle Offline Persistence Toolkit to enable data caching for offline support, check the data caching strategy used by your application's business objects. See Define a Data Caching Strategy.
To use the toolkit in a web (or mobile) application, you update the application’s app-flow.js file to include an OfflineHandler() function that determines the scope of data in your application to cache, what type of caching strategy from the toolkit to use, and so on. The following commented app-flow.js file demonstrates one scenario of how you might go about implementing caching for offline capabilities in your application. The file also demonstrates how you enable toolkit's logging functionality while you develop the application that uses the toolkit. Enabling this type of logging during the development phase will help you understand what data the toolkit caches offline in your application. Disable the logging functionality when you are ready to publish your application in a production environment.
define([
    'vbsw/helpers/serviceWorkerHelpers',
    /**
     * Add the following entries to include the toolkit classes that you'll use. More information about these
     * classes can be found in the toolkit's API doc. See the link to the API doc in the paragraph before
     * this sample file.
     *
     */
    'persist/persistenceManager',
    'persist/defaultResponseProxy',
    'persist/fetchStrategies',
    /**
     * Add the following entry to enable console logging while you develop your app with the toolkit.
     */
    'persist/impl/logger'
],
    (ServiceWorkerHelpers, PersistenceManager, DefaultResponseProxy, FetchStrategies, Logger) => {
        'use strict';

        class AppModule {

        }

        var OfflineHandler = function () {

            /**
             * Enable console logging of the toolkit for development testing
             */
            Logger.option('level', Logger.LEVEL_LOG);
            Logger.option('writer', console);

            var options = {
                /**
                 * The following code snippets implements the toolkit's CacheFirstStrategy. This strategy
                 * checks the application's cache for the requested data before it makes a request to cache
                 * data. The code snippet also disables the background fetch of data.
                 */

                fetchStrategy: FetchStrategies.getCacheFirstStrategy({
                    backgroundFetch: 'disabled'
                }),
            };
            this._responseProxy = DefaultResponseProxy.getResponseProxy(options);
        };

        OfflineHandler.prototype.handleRequest = function(request, scope) {
            /**
             * (Optional). Write output from the OfflineHandler to your browser's console. Useful to help
             * you understand  the code that follows.
             */
            console.log('OfflineHandler.handleRequest() url = ' + request.url + ' cache = ' + request.cache +
                ' mode = ' + request.mode);

            /**
             * Cache requests where the URL matches the scope for which you want data cached.
             */
            if (request.url.match(
                'http://localhost:1988/webApps/ifixitfaster/api')) {

                return this._responseProxy.processRequest(request);
            }
            return PersistenceManager.browserFetch(request);
        };

        OfflineHandler.prototype.beforeSyncRequestListener = (event) => {
            return Promise.resolve();
        };
        OfflineHandler.prototype.afterSyncRequestListener = (event) => {
            return Promise.resolve();
        };
        AppModule.prototype.createOfflineHandler = () => {
            /** Create the OfflineHandler that makes the toolkit cache data URLs */
            return Promise.resolve(new OfflineHandler());
        };
        AppModule.prototype.isOnline = () => {
            return ServiceWorkerHelpers.isOnline();
        };
        AppModule.prototype.forceOffline = (flag) => {
            return ServiceWorkerHelpers.forceOffline(flag).then(function () {
                /** if online, perform a data sync */
                if (!flag) {
                    return ServiceWorkerHelpers.syncOfflineData();
                }
                return Promise.resolve();

            }).catch(function (error) {
                console.error(error);
            });
        };
        return AppModule;
    });

Oracle maintains the persistence toolkit as an open-source project. For additional information about using the toolkit, see the README.md and Wiki for the persistence toolkit on Github at https://github.com/oracle/offline-persistence-toolkit. API documentation for the toolkit is linked to from the aforementioned Github page, but can also be accessed directly at https://oracle.github.io/offline-persistence-toolkit/index.html.