Configure Data Cache and Offline Support

Use the Oracle Offline Persistence Toolkit to enable data caching and offline support within your application.

The toolkit is a client-side JavaScript library that is delivered ready-to-use by Oracle Visual Builder. The toolkit provides caching and 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 and hybrid mobile 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.

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 and offline capabilities in your application. The following app-flow.js file also demonstrates how you enable the logging functionality of the toolkit 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.

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.

Oracle maintains the 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.

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'
],
    function (ServiceWorkerHelpers, PersistenceManager, DefaultResponseProxy, FetchStrategies, Logger) {
        'use strict';

        function AppModule() { }

        function OfflineHandler() {
            /**
             * 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 = function (event) {
            return Promise.resolve();
        };
        OfflineHandler.prototype.afterSyncRequestListener = function (event) {
            return Promise.resolve();
        };
        AppModule.prototype.createOfflineHandler = function () {
        /** Create the OfflineHandler that makes the toolkit cache data URLs */            
            return Promise.resolve(new OfflineHandler());
        };
        AppModule.prototype.isOnline = function () {
            return ServiceWorkerHelpers.isOnline();
        };
        AppModule.prototype.forceOffline = function (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;
    });