Skip to content
On this page

August 2022

Welcome to the notes for the August 2022 release for the CAP framework. Find the most noteworthy news and changes in the following sections.

CAP on Kyma/K8s

Important Changes ❗️

New Component Minimum Version

The latest version of the CAP Helm chart (cds add helm) introduces new minimum version requirements for the following components:

ComponentMinimum Version
cds (Java)1.27.0
@sap/hdi-deploy (SAP HANA Deployer)4.4.1
@sap/html5-app-deployer (HTML5 application deployer)4.1.2

Don't Use CDS_ENVIRONMENT_K8S_SERVICEBINDINGS_* Environment Variables

Make sure that no environment variables starting with CDS_ENVIRONMENT_K8S_SERVICEBINDINGS_ are in your chart/values.yaml file of your Helm chart, as they conflict with the new service bindings.

These variables were previously added by the cds add helm:connectivity command.

CAP Java Support for servicebinding.io Service Bindings

CAP Java now makes use of the new open source Service Binding Access library as default source to obtain service bindings. On K8s/Kyma it integrates better with the SAP BTP Service Operator, which uses a servicebinding.io based format. This allows reading service bindings with the same set of metadata as in Cloud Foundry, which makes it fully transparent to the CAP application if the service bindings are read in the K8s/Kyma or Cloud Foundry environment.

Configure Resources for Content Deployment Jobs

You can now configure the Kubernetes resources for HTML5 application and HANA deployment jobs.

The default configuration is added by running cds add helm.

Add Environment Variables for Content Deployment Jobs

HTML5 application and SAP HANA deployment jobs allow adding environment variables.

For example, the following snippet from the Helm chart adds an environment variable DEBUG with value * to the HTML5 applications deployer job:

yaml
html5_apps_deployer:
  env:
    DEBUG: '*'
html5_apps_deployer:
  env:
    DEBUG: '*'

Schema Validation

The Helm chart now contains a JSON schema that helm uses to validate the values.yaml file. Development tools, such as Visual Studio Code, can use the schema to show validation errors, descriptions and suggestions.

Improved VS Code Support for CDS Configuration

Code completion and validation for the cds configuration has been improved in VS Code. In both package.json and .cdsrc.json, you get hints on the possible values plus warnings for invalid values based on the installed @sap/cds version. Especially filling out the cds.requires section is now much easier.

json_code_completion.gif

CDS Language & Compiler

SAP HANA Regex Functions

CDS natively supports the SAP HANA Regex functions locate_regexpr, occurrences_regexpr, replace_regexpr, and substring_regexpr:

cds
entity Foo as select from Bar {
  /* ... */
  substring_regexpr(pattern in name from 5) as sub
};
entity Foo as select from Bar {
  /* ... */
  substring_regexpr(pattern in name from 5) as sub
};

Learn more about Native Database Functions.

Actions and Functions in Aspects

Aspects now can have bound actions and functions:

cds
aspect TravelActions { }
  actions {
    action rejectTravel();
    action acceptTravel();
    function isValid() returns Boolean;
  }
aspect TravelActions { }
  actions {
    action rejectTravel();
    action acceptTravel();
    function isValid() returns Boolean;
  }

Reuse these aspects for example in services:

cds
service TravelService {
  entity Travel as projection on my.Travel;
  extend Travel with TravelActions;
}
service TravelService {
  entity Travel as projection on my.Travel;
  extend Travel with TravelActions;
}

Learn more about Aspects.

Java SDK

Important Changes ❗️

Minimum Spring Boot Version 2.7.x

  • CAP Java SDK now requires Spring Boot version 2.7.x or later. Most notably the deprecated WebSecurityConfigurerAdapter has been migrated to SecurityFilterChain in CAP Java. As both can't coexist, custom security configurations in applications need to be migrated to SecurityFilterChain as well. See an example in our documentation. In addition, Spring Boot 2.7.x defaults to H2 version 2.x, which is not fully compatible with DDL artifacts generated by CDS compiler. If you use H2, make sure to pin your application to H2 version 1.x as shown in the bookshop example. In addition, read the Spring Boot upgrade instructions.

  • The deprecated path access via CdsData::get has been removed. Instead use data.getPath("deeply.nested.key") to access values in deeply nested maps.

Error Response Handler

Exceptions thrown during event handler processing, are caught by OData V2 and V4 protocol adapters and are turned into corresponding OData error responses. So far, it wasn't possible to change error responses as exceptions were thrown by the framework. Now, you can customize these responses by handling the ERROR_RESPONSE event of the Application Lifecycle Service emitted by the protocol adapter. You can control the error message text, code and the list of messages collected during request processing for specific or general error situations. The following example demonstrates how to change the error text of authorization errors:

java
@Component
@ServiceName(ApplicationLifecycleService.DEFAULT_NAME)
public class SimpleExceptionHandler implements EventHandler {

  @After
  public void overrideMissingAuthMessage(ErrorResponseEventContext context) {
    if (context.getException().getErrorStatus().equals(CdsErrorStatuses.EVENT_FORBIDDEN)) {
        context.getResult().getMessages().set(0,
            Message.create(Severity.ERROR, "You cannot execute this action"));
    }
  }
}
@Component
@ServiceName(ApplicationLifecycleService.DEFAULT_NAME)
public class SimpleExceptionHandler implements EventHandler {

  @After
  public void overrideMissingAuthMessage(ErrorResponseEventContext context) {
    if (context.getException().getErrorStatus().equals(CdsErrorStatuses.EVENT_FORBIDDEN)) {
        context.getResult().getMessages().set(0,
            Message.create(Severity.ERROR, "You cannot execute this action"));
    }
  }
}

Find the details in our documentation.

WARNING

Messaging via Redis PubSub (beta) This is a beta feature. Beta features aren't part of the officially delivered scope that SAP guarantees for future releases. :::

There's a new MessagingService based on Redis PubSub, which is suitable for asynchronous communication between tightly-coupled microservices. To configure this messaging service, bind your CAP application to an appropriate platform service, for example of type redis-cache, and add the following feature in your pom.xml:

xml
<dependency>
    <groupId>com.sap.cds</groupId>
    <artifactId>cds-feature-redis</artifactId>
</dependency>
<dependency>
    <groupId>com.sap.cds</groupId>
    <artifactId>cds-feature-redis</artifactId>
</dependency>

In the application.yaml you can configure a Redis messaging service explicitly:

yaml
cds:
  messaging.services:
    my-redis-service:
      kind: redis-pubsub
cds:
  messaging.services:
    my-redis-service:
      kind: redis-pubsub

Enhanced TenantProviderService

The TenantProviderService now offers a new readProviderTenant() method, which provides the tenant ID of the provider. This method tries to retrieve the information from an existing XSUAA, Identity (IAS) or SaaS Registry service binding.

Character-based Media Streams

Besides media types based on binary data (LargeBinary), CAP Java now also supports character-based media streams (LargeString):

java
entity Books : cuid {
  title         : String;
  content       : LargeString @Core.MediaType: 'text/plain';
}
entity Books : cuid {
  title         : String;
  content       : LargeString @Core.MediaType: 'text/plain';
}

Programmatically you consume content in custom handlers using java.io.Reader. Refer to the media type documentation for details.

Simplified Authentication Configuration

We introduced a new property cds.security.authentication.mode, which controls the authentication strategy for CAP endpoints:

  • model-strict authenticates endpoints based on @requires/@restrict. Paths to model elements without annotation are authenticated.
  • model-relaxed authenticates endpoints based on @requires/@restrict. Paths to model elements without annotation are public.
  • never disables authentication of all CAP endpoints (use in local development scenario only!).
  • always authenticates all CAP endpoints.

Mode model-strict is set by default. Note that the authentication mode has no impact on the authorization behaviour.

Miscellaneous

  • The generated data accessor interfaces for entities with a single key element now come with a create method that takes the key value.
java
Books book = Books.create(201);
Integer bookId = book.getId(); // 201
Books book = Books.create(201);
Integer bookId = book.getId(); // 201
  • The CqnAnalyzer now can extract (key) values from more complex predicates.

  • The cds-services-archetype now provides the new parameter inMemoryDatabase to choose the in-memory database configuration for local testing in the newly created CAP Java project. Supported values are h2 (default) and sqlite.

  • Annotations @Capabilities.Readable and @Capabilities.ReadRestrictions.Readable are now handled.

  • Authentication-related settings in section cds.security have been moved to new subsection cds.security.authentication:

    • authenticateUnknownEndpoints is replaced by authentication.authenticateUnknownEndpoints.
    • openMetadataEndpoints is replaced by authentication.authenticateMetadataEndpoints (mind the negation!).
    • openUnrestrictedEndpoints and defaultRestrictionLevel are subsumed under the new property authentication.mode.

    All previous properties are deprecated and can still be used for compatibility.

Node.js Runtime

Important Changes ❗️

You can now use cds.ql fluent API to query tables not in the model, but in the database. For example, within cap/samples/bookshop this works now:

js
await SELECT.from('sqlite_master')
await cds.read('sqlite_master')
await SELECT.from('sqlite_master')
await cds.read('sqlite_master')

Caveat: the following undocumented usage of unqualified names happened to work in the past. But this was very fragile and caused lots of issues, and therefore was removed:

js
await SELECT.from('Books')
await cds.read('Books')
await SELECT.from('Books')
await cds.read('Books')

Always use qualified names, or reflected definitions instead:

js
const Books = 'sap.capire.bookshop.Books'
await SELECT.from(Books)
await cds.read(Books)
const Books = 'sap.capire.bookshop.Books'
await SELECT.from(Books)
await cds.read(Books)
js
const {Books} = cds.entities ('sap.capire.bookshop')
await SELECT.from(Books)
await cds.read(Books)
const {Books} = cds.entities ('sap.capire.bookshop')
await SELECT.from(Books)
await cds.read(Books)

Improved REST Adapter

  • Aliased parameters in requests like /submitOrder(ID=@p)?@p=1 are now supported.
  • in operator in requests like /Books?$filter=ID in (1,2,3) are now converted to the correct CQN syntax.

Improved Consumption of Remote OData V2 Services

  • cds.Time is now converted to the correct format PT<hh>H<mm>M<ss>S.
  • The CQN property search is now converted into a SAP-specific custom query option:
js
{
  SELECT: {
    from: [{ ref: ['Books'] }],
    search: [{ val: 'wut' }]
  }
}
{
  SELECT: {
    from: [{ ref: ['Books'] }],
    search: [{ val: 'wut' }]
  }
}

This query is translated into the URL /Books?search=wut.