Skip to content

Change Tracking for CAP Services

The tools provided by the SAP Cloud Application Programming Model make it easy to model, generate and deploy an OData service.

If the generated OData service is to be consumed by occasionally-connected mobile clients, together with CloudSyncProvider or OfflineODataProvider in one of the SAP Business Technology Platform client SDKs, then it is highly beneficial for data synchronization performance to augment the CAP service with OData change tracking capabilities.

In particular, the performance of delta downloads, where the client wishes to download only the back-end data changes since the previous download, can be expected to be achieved in seconds if change tracking is enabled, compared with minutes to hours if change tracking is not enabled (assuming there was a high volume of data in the initial download).

Requirements

  • The CAP service is already deployed to the SAP Business Technology Platform Cloud Foundry environment, using either the Node.js runtime or the Java runtime.

  • The CAP service is already configured to store CAP entities in a SAP HANA Cloud schema (HDI container). CAP entities that proxy/wrap non-CAP back-end APIs and aren't presently stored in the HANA schema can also be supported for change tracking.

  • A destination service instance has been configured in the same Cloud Foundry space as the CAP service, including a destination whose name matches the CAP Service's app name except with hyphen ('-') replaced by underscore ('_'). For example, if the app name is myapp-srv, the destination service instance might be named myapp-dest, and the destination must be named myapp_srv. The destination configuration should use the OData (HTTP) service root URL for your CAP service, and the Authentication option of NoAuthentication. This destination is used by the delta service when it needs to check HTTP Authorization headers by delegating to the CAP service. Use the SAP Business Technology Platform Cockpit for setting up destination service instances and destinations.

Architecture

The mobile back-end tools is used to generate and deploy a delta service, which is a proxy service that is positioned between mobile clients and the CAP service. Change tracking is enabled by either delta views or cache tables.

  • For CAP entities (including projections) that are mapped by the CAP tools to simple database views, the mobile back-end tools will generate tracking tables, tracking triggers and delta views (in the same SAP HANA Cloud schema used by the existing CAP service) for change tracking and the delta service will use the delta views to enable efficient OData change tracking.

  • For CAP entities that are mapped by the CAP tools to complex database views (or to external entities, not present in the HANA schema), the mobile back-end tools generates cache tables (in the same SAP HANA Cloud schema used by the existing CAP service) and the delta service uses the cache tables to enable efficient OData change tracking.

Effectively, the mobile back-end tools will use a hybrid of Working with Existing Database Tables and Caching Data in the Cloud (OData Back-End Systems) to enable change tracking for each CAP entity as efficiently as possible.

The generated delta service uses a Java runtime to ensure optimum performance, and should be deployed to run in Apache Tomcat in the SAP Business Technology Platform Cloud Foundry environment.

Development

See Installing the Tools for initial setup instructions including the Java Development Kit, Apache Maven and Cloud Foundry CLI. Ensure that the JDK version that you select is at least the minimum version required for CAP Java services.

Create CAP Project

An existing CAP project is required, with a service model in the srv subfolder. If you don't have one, you can create a simple CAP project for testing as follows.

It you haven't yet installed the CAP CDS Development Kit, see CAP Getting Started. You can skip the SQLite requirements for CAP. Ensure that node and npm are installed, java and mvn (unless you plan only to use Node.js), and install the CDS Development Kit.

npm i -g @sap/cds-dk

Additionally, to support MTA deployment to Cloud Foundry, install the Cloud MTA Build Tool and Cloud Foundry CLI w/ MTA Plugins.

In a Terminal window (or Windows Command Prompt), use the following commands to create, build and deploy your CAP project. The name myapp is a placeholder for your desired CAP project name.

  • Node.js

    cds init myapp
    
  • Java

    cds init myapp --java
    

Change the working directory to the newly created project.

cd myapp

Add a CDS data model in the db folder and a CDS service model in the srv folder, for example by adding tiny-sample to your project, and enable the HANA database.

cds add tiny-sample
cds add hana --for production

For a Node.js project, install the xssec package.

npm i @sap/xssec

For simplification of initial testing, you may wish to disable authentication by adding the following to the "cds" section of your project's package.json (for Node.js) or to your project's .cdsrc.json (for Java):

"requires": {
    "auth": { "kind": "dummy" }
}

Please remember to enable and test authentication before putting your CAP service into production.

Build and deploy your CAP project:

cds up

See the above Requirements for details of setting up a destination service instance and a destination.

The mta.yaml file for the CAP service should include a reference to the destination service instance in the requires section.

modules:
  - name: myapp-srv
    ...
    requires:
      ...
      - name: myapp-dest

The mta.yaml file for the CAP service should include a definition of the destination service instance in the resources section.

resources:
  ...
  - name: myapp-dest
    type: org.cloudfoundry.managed-service
    parameters:
      service: destination
      service-plan: lite

Create MBT Project

Find the cds-delta script in the same folder as the csdl-to-war script.

In a Mac/Linux Terminal or Windows Command Prompt window, change the current directory to your CAP project's root directory, and execute the cds-delta script as follows, where server-odata-sdk-bin is a placeholder for the bin folder in which the cds-delta script is located.

Mac/Linux Terminal:

server-odata-sdk-bin/cds-delta.sh init [ my-service.cds ]

Windows Command Prompt:

server-odata-sdk-bin\cds-delta.bat init [ my-service.cds ]

The square brackets above indicate an optional CAP service CDS file (the brackets should not be included in the command). If the CDS file is not specified, there should be a single CDS file in the CAP project's srv folder.

You will be prompted for the following information:

  • The SAP Business Technology Platform Cloud Foundry app name for of your existing deployed CAP service (e.g. myapp-srv).

  • The SAP Business Technology Platform Cloud Foundry HANA Cloud schema (HDI container) instance name for your existing schema (e.g. myapp-db).

  • The SAP Business Technology Platform Cloud Foundry destination service instance name (e.g. myapp-dest). As mentioned in the above Requirements, a destination must have already been defined for the destination service instance with the URL of the deployed CAP service.

The provided information will be checked to ensure that the Cloud Foundry app/instances already exist.

The cds-delta init command creates a sidecar MBT project within your CAP project's delta subfolder — the generated delta service and the CAP service will run side-by-side in the same Cloud Foundry space.

Embedded Mode

For the CAP Java runtime (but not the Node.js runtime), the cds-delta init command can be optionally be invoked with the -embed option.

The cds-delta init -embed command creates an embedded MBT project within your CAP project's srv/delta subfolder — the generated delta service and the CAP service will run in the same Java process.

Generation Options

The generated delta folder will include a generated options file, e.g. my-service.options.

If you need to add or change any options, please refer to the Service Generator's Command-Line Tool Options.

Convenience Scripts

For your convenience after creating the MBT project, two convenience scripts will be generated into your CAP project's root folder, namely cds-delta.bat and cds-delta.sh.

This allows the subsequent build and deploy steps to be conveniently executed without having to remember the path to the server-odata-sdk-bin folder containing the cds-delta script.

Note

If the init step was performed on a Windows system, the cds-delta.sh script might not have the necessary execute permissions for use by Mac/Linux users. The shell command chmod ugo+x cds-delta.sh (on a Mac/Linux system) will apply the necessary permissions, which should be subsequently retained if the project is checked in to a Git repository.

Build MBT Project

After creating the MBT project, and then subsequently each time you change your CAP service model (or any underlying CDS data model), execute the cds-delta script as follows:

Mac/Linux Terminal:

./cds-delta.sh build

Windows Command Prompt:

.\cds-delta.bat build

The cds-delta build command will execute the following commands:

Deploy MBT Project

After building the MBT project, and then subsequently each time you change your CAP service model (or any underlying CDS data model), execute the cds-delta script as follows:

Mac/Linux Terminal:

./cds-delta.sh deploy

Windows Command Prompt:

.\cds-delta.bat deploy

The cds-delta deploy command will execute the following commands:

  • cds deploy --to hana

  • cf push delta/manifest.yml (only for sidecar mode, not for embedded mode)

  • btp-cf-setup logs myapp-delta (only for sidecar mode, not for embedded mode)

Deployment Artifacts

To aid understanding of the delta service implementation, please take note of the following generated artifacts.

  • The db/src/delta folder, containing the generated HANA deployment (HDI) artifacts for delta views and cache tables. These files supplement the HDI artifacts that were generated by the CAP tools, ensuring that anything needed in the HANA schema to support change tracking will be automatically added during execution of the cds-delta build command.

  • The delta folder, a sub-project folder containing the main files for the delta service.

  • The delta/src folder, containing generated Java source files for the delta service implementation. Customization of the generated Java files is permitted, although it is generally recommended to customize the CAP service implementation files rather than the delta service implementation files (unless the customization is related to the OData change tracking).

  • Some OData metadata files. Do not edit any of these files, as your changes will be lost upon any subsequent execution of the cds-delta build command.

    • A copy of the CAP service's metadata file, generated by the cds-delta build command.

    • The file delta/my-service-client.xml, a client-side copy of the OData metadata document for the delta service. This file may be useful when building client applications as an input to proxy generation tools in the SAP Business Technology Platform Mobile SDKs.

    • The file delta/my-service-server.xml, a server-side copy of the OData metadata document for the delta service. This file contains OData annotations indicating the use of delta views and/or cache tables.

  • The file delta/pom.xml, an Apache Maven POM, generated and then used by the csdl-to-war task to build the delta service WAR file. You can edit this file if you need to customize the Maven build to include additional class libraries, e.g. if you have customized the generated Java code.

  • The file delta/manifest.yml, a Cloud Foundry App Manifest, generated and then used by the cf push command to deploy the delta service WAR file. You can edit this file to alter Cloud Foundry runtime options for disk, instances, memory, and so forth. A minimum of 2GB disk and 2GB memory per instance is recommended. Multiple instances can be used if needed to support the client workload.

See also: Partitioning for Memory Efficiency.

Delta Service URLs

The OData service root URL for your delta service is different for sidecar services and embedded services.

  • If you generated a sidecar service, your delta service will have its own host name (Cloud Foundry route). Use the cf app myapp-delta command to see your app's route(s). Then use the URL https://myapp-delta-route to access your delta service.

  • If you generated an embedded service, your delta service will share the host name (Cloud Foundry route) of the CAP service, but with a special URL suffix to identify the delta service. Use the cf app myapp-srv command to see your app's route(s). Then use the URL https://myapp-srv-route/delta/MyService to access your delta service.

Note

Accessing your delta service requires a Client Registration. See Registration Header.

Delta Service Logs

For a sidecar service, the cds-delta init command generates a convenience cf-logs script (delta/logs/cf-logs.sh for Mac/Linux, delta\logs\cf-logs.bat for Windows). Invoking this script from a Visual Studio Code Terminal can be a convenient way to download the logs to a local file, and view them in the editor.

Alternatively for a sidecar service, use standard Cloud Foundry cf logs myapp-delta or cf logs --recent myapp-delta to access your Cloud Foundry logs.

Alternatively for an embedded service, use standard Cloud Foundry cf logs myapp-srv or cf logs --recent myapp-srv to access your Cloud Foundry logs.

See also: Monitoring Generated Services.

Customization

CDS Annotations

Normally mobile back-end tools allows special annotations to be placed in the server-side OData metadata document, to describe options for change tracking, download queries and back-end interactions.

But when using mobile back-end tools to enable change tracking for a CAP service, the OData metadata is not directly maintained. Rather the developer provides a CDS service model. Special CDS annotations can be placed in the CDS model to specify options for change tracking and download queries.

  • Annotations affecting selection criteria for client downloads.

    • sync.download (string) - equivalent to the OData SQL.DownloadQuery term.

      @sync.download : 'select entity.* from Customer entity, CustomerFilter filter where entity.id = filter.customer_id'
      entity Customer
      {
          key id : Integer;
          name : String(100) not null;
          address : String(100) not null;
          phone : String(30);
      }
      

      Note the filter.customer_id in the above example is referring to the foreign key property in the CAP service's OData metadata that is generated by the CAP tools to implement the customer association in the CustomerFilter entity.

    • sync.filter (boolean) - equivalent to the OData SQL.ClientFilter term.

      @sync.filter
      @cds.persistence.skip
      entity CustomerFilter
      {
          key id : Integer;
          customer : Association to one Customer;
      }
      

      Note the additional @cds.persistence.skip annotation to force the CAP tools to not attempt to create the DB artifacts for filter entities; that will be taken care of by the mobile back-end tools.

    • sync.inherit (path) - equivalent to the OData SQL.InheritDownloadQuery term.

      @sync.inherit : order
      entity OrderItem
      {
          key id : Integer64;
          order : Association to one Order not null;
          product : Association to one Product not null;
          quantity : Integer not null;
          deliveryDate : DateTime;
      }
      
  • Annotations affecting whether a cache table is used.

    • cache.required (boolean) - specifies that an entity should be cached even if delta views would otherwise be selected by default.

      Note that cache tables will be used for CAP entities using localized elements, as well as entities using @restrict with a where condition, since the database views for such entities are too complex for the generation of change tracking triggers. Cache tables will also be used for CAP external entities with @cds.persistence.skip.

  • Annotations affecting when a cache table is refreshed.

    • cache.background (boolean) - equivalent to the opposite of the OData Cache.OnDemand term, i.e. cached CAP entities will use on-demand refresh by default (with a one hour timeout), and will only use scheduled refresh when explicitly requested. If scheduled refresh is selected, the SAP Business Technology Platform HTTP destination used by the delta service to access the CAP service must specify technical user credentials; this can be configured in the SAP Business Technology Platform Cockpit.

      @cache.background
      entity EntityWithCacheBackground
      {
          ...
      }
      
    • cache.schedule (time) - equivalent to the OData Cache.Schedule term.

      @cache.schedule : '02:30'
      entity EntityWithCacheSchedule
      {
          ...
      }
      
    • cache.timeout (duration) - equivalent to the OData Cache.Timeout term.

      @cache.timeout : 'PT2H'
      entity EntityWithCacheTimeout
      {
          ...
      }
      
    • cache.loadAfter (string) - equivalent to the OData Cache.LoadAfter term.

    • cache.loadBefore (string) - equivalent to the OData Cache.LoadBefore term.

  • Annotations affecting how a cache table is partitioned.

    • cache.partition - equivalent to the OData Cache.PartitionBy term.

    • cache.byClient (boolean) - equivalent to the OData Cache.ByClient term.

    • cache.byLocale (boolean) - equivalent to the OData Cache.ByLocale term.

Example CDS Model

service TestService
{
    @sync.download : 'select entity.* from Customer entity, CustomerFilter filter where entity.id = filter.customer_id'
    entity Customer
    {
        key id : Integer;
        name : String(100) not null;
        address : String(100) not null;
        phone : String(30);
    }

    @sync.filter
    @cds.persistence.skip
    entity CustomerFilter
    {
        key id : Integer;
        customer : Association to one Customer;
    }

    entity Product
    {
        key id : Integer;
        name : String(100) not null;
        description : String(100) not null;
        standardPrice : Decimal not null;
    }

    entity Factory
    {
        key id : Integer;
        name : String(100) not null;
        address : String(100) not null;
        phone : String(30);
    }

    @sync.filter
    @cds.persistence.skip
    entity FactoryFilter
    {
        key id : Integer;
        factory : Association to one Factory;
    }

    @sync.download : 'select entity.* from FactoryProduct entity, FactoryFilter filter where entity.factory_id = filter.factory_id'
    entity FactoryProduct
    {
        key factory : Association to one Factory;
        key product : Association to one Product;
        factoryPrice : Decimal;
    }

    @sync.download : 'select entity.* from Order entity, CustomerFilter filter where entity.customer_id = filter.customer_id'
    entity Order
    {
        key id : Integer64;
        customer : Association to one Customer not null;
        factory : Association to one Factory not null;
        items : Composition of many OrderItem on items.order = $self;
        created : DateTime not null;
        shipped : DateTime;
    }

    @sync.inherit : order
    entity OrderItem
    {
        key id : Integer64;
        order : Association to one Order not null;
        product : Association to one Product not null;
        quantity : Integer not null;
        deliveryDate : DateTime;
    }
}

Security

The generated delta service automatically checks the HTTP Authorization header of incoming requests by delegating to the CAP service. Thus there is no specific security configuration required for the delta service.

Delegation to the CAP service is also used for permission checks when the client requests are OData queries. To check if the user has read access to an entity set, the delegated permission check will use a query such as SomeEntitySet?$top=1.

If the CAP service performs user-specific filtering of data even when the client does not specify an OData $filter in the query URL, then you should use CDS annotations @cache.required and @cache.byClient (noting that this will result in the cache containing user-specific copies of data), or for entities with shared data using delta views, the CDS annotation @sync.download could be used to replicate the user-specific filtering of that shared data.


Last update: May 19, 2025