Skip to content
On this page

February 2022

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

Capire Docs & Samples

Keyboard Shortcuts in Capire

We now provide an overview of the available keyboard shortcuts in capire. Just try it out and hit ? to see this list:

Shortcuts Popup

Revised Cookbook - Deploy & Operate

This cookbook is based on the deployment guide that was previously found in the Advanced section of capire. We revised it and promoted the guide to a cookbook.

Assuming you have developed your application, it's tested and running, and ready for deployment. Before you start to automate, you want to do the necessary preparation and deploy ad-hoc, to see if everything works as before. This guide helps you.

Data Browser

Data Browser Sample

We have added a simple generic data browser to the sample suite for Node.js, useful for troubleshooting purposes during application development:

Data Browser

You can browse entities from all connected services of the application. Data is either fetched directly from the database or through the application's CDS services, which then includes projections, validations and so on.

The sample code also demonstrates the following:

  • How to write a generic CAP service (see the data-viewer package).
  • How to include such a service and its UI in another application (the bookstore app).

Note that this code is meant for demonstration purposes and should not be used in production. Copy the code into your application as needed.

Key-User Extensions with SAPUI5 Flexibility

We added a first experimental support for simple field extensibility in CAP.

Warning

This is only disclosed for testing purposes and for gathering feedback.

Current limitations:

  • Only works locally using cds watch
  • Needs to be deployed to a file-based SQLite database
  • Only available for the Node.js runtime

This is a first step to enable extensibility in CAP applications without depending on an MTX/HDI based deployment and an SAP HANA database.

Multiline String Literals

Multiline string literals enclosed in single or triple backticks provide a convenient way of writing long text snippets, for example in annotation values. In addition, they support escape sequences. The variant with triple backticks performs indentation stripping and allows tagging.

cds
annotate Customer with @Cache.UpdateHandler:
{
  XMLHttpRequest : `PUT /patients`,
  XMLRequestBody : ```xml
                    <patient id="\${entity.PatientID}">
                        <name>\${entity.Name}</name>
                        <state>\u{1f197}</state>
                        <address>\${entity.Address}</address>
                        <dateOfBirth>\${entity.DOB}</dateOfBirth>
                    <patient>
                   ```
}
annotate Customer with @Cache.UpdateHandler:
{
  XMLHttpRequest : `PUT /patients`,
  XMLRequestBody : ```xml
                    <patient id="\${entity.PatientID}">
                        <name>\${entity.Name}</name>
                        <state>\u{1f197}</state>
                        <address>\${entity.Address}</address>
                        <dateOfBirth>\${entity.DOB}</dateOfBirth>
                    <patient>
                   ```
}

Learn more about Multiline Literals.

Native Database Clauses (beta)

Activate this feature in .cdsrc.json:

JSON
"cdsc": {
  "beta": { "sqlSnippets": true }
}
"cdsc": {
  "beta": { "sqlSnippets": true }
}

Using the annotations @sql.prepend and @sql.append, you can add arbitrary SQL snippets to the DDL statements that are generated by the compiler. This allows to use database features that are not natively supported by CDS.

Model:

cds
@sql.append: ```sql
             GROUP TYPE foo
             GROUP SUBTYPE bar
             ```
entity E {
  ...,
  @sql.append: 'FUZZY SEARCH INDEX ON'
  text: String(100);
}
@sql.append: ```sql
             GROUP TYPE foo
             GROUP SUBTYPE bar
             ```
entity E {
  ...,
  @sql.append: 'FUZZY SEARCH INDEX ON'
  text: String(100);
}

Result:

sql
create table E (
  ...,
  text nvarchar(100) FUZZY SEARCH INDEX ON
) GROUP TYPE foo
GROUP SUBTYPE bar
create table E (
  ...,
  text nvarchar(100) FUZZY SEARCH INDEX ON
) GROUP TYPE foo
GROUP SUBTYPE bar

❗ Warning

The compiler doesn't check or process the provided SQL snippets in any way. You are responsible to ensure that the resulting statement is valid and doesn't negatively impact your database or your application. We don't provide support for problems caused by using this feature.

Learn more about Native Database Clauses.

Extend Array-Like Annotation Values - Insert

In addition to adding new entries at the beginning and at the end of an array-like annotation value, you can now insert them at arbitrary positions. Provide a comparator object to identify the entry after which to insert.

For displaying the day of week after the respective fields for BeginDate and EndDate:

cds
@UI.LineItem : [
    { Value : TravelID    },
    { Value : BeginDate   },
    { Value : EndDate     },
    { Value : TotalPrice  },
    { Value : Description }
  ]
entity TravelService.Travel { /* elements */ }
@UI.LineItem : [
    { Value : TravelID    },
    { Value : BeginDate   },
    { Value : EndDate     },
    { Value : TotalPrice  },
    { Value : Description }
  ]
entity TravelService.Travel { /* elements */ }

use the new ... up to syntax:

cds
annotate TravelService.Travel with @UI.LineItem: [
  ... up to { Value : BeginDate },
  { Value : BeginWeekday },  // inserted after BeginDate
  ... up to { Value : EndDate },
  { Value : EndWeekday },    // inserted after EndDate
  ...                        // remaining array values
];
annotate TravelService.Travel with @UI.LineItem: [
  ... up to { Value : BeginDate },
  { Value : BeginWeekday },  // inserted after BeginDate
  ... up to { Value : EndDate },
  { Value : EndWeekday },    // inserted after EndDate
  ...                        // remaining array values
];

Learn more about ... up to.

Node.js Runtime

Important Changes ❗️

  • Draft entities can only be updated by the user that created the draft. From this release on, this rule includes bound actions and functions. See Restrictions and Draft Mode for more details.
  • In OData, binary data (whether as payload or part of query options) is consistently passed into the service as Base64 encoded strings.

New Hook req.before('commit')

The new hook req.before('commit') allows you to perform some final actions, such as validity checks, bookkeeping, and so on, before the respective transaction is committed. Throwing an error vetoes the commit.

Example:

js
srv.before('CREATE', Order, function(req) {
  req.before('commit', async function() {
    const { creditscore } = await SELECT.one.from(Customers)
      .where({ ID: req.data.customer_ID })
    if (creditscore < 42) throw new Error("We shouldn't make this sale")
  })
})
srv.before('CREATE', Order, function(req) {
  req.before('commit', async function() {
    const { creditscore } = await SELECT.one.from(Customers)
      .where({ ID: req.data.customer_ID })
    if (creditscore < 42) throw new Error("We shouldn't make this sale")
  })
})

Media Data

The new OData annotation @Core.ContentDisposition.Type is now supported, with attachment as the default value.

Further, we added beta support for returning custom stream objects in custom handlers as described in Custom Streaming.

Java SDK

Synchronous In-Memory Messaging to Ease Testing

The new in-memory MessagingService can be easily consumed in local testing scenarios or JUnit tests. To create such a messaging service, choose local-messaging as kind:

yaml
cds:
  messaging.services:
  - name: "messaging"
    kind: "local-messaging"
cds:
  messaging.services:
  - name: "messaging"
    kind: "local-messaging"

The MessagingService provides the common messaging service API, but the event publishing is synchronous to the event listeners. This frees test code from having to wait on the asynchronous execution of the listeners.

Instance-Based Authorization with IN Predicates

IN predicates with user attributes are now supported in instance-based authorization conditions, for example, country in $user.countries. Logically, it has the same effect as the =-operator in predicates (for example: country = $user.countries), but the $user-attribute value (list) needs to be a right operand.

Exclude Sensitive Data from Logging

Potentially, sensitive values are now excluded from CQN statements in application logging by default. To enable logging of sensitive values again you can set cds.security.logPotentiallySensitive to true.

Analyze a CQN Expression Tree

Use a CqnVisitor for in-depth analysis of a CQN expression tree. Use cases:

  • Transformation of CQN to some different query language
  • In-memory evaluation of CQN
  • Overcome limitations of the CqnAnalyzer

ORDER BY ... NULLS FIRST | LAST

You may now specify if null values are to appear first or last in a sorted result of a read query. The following query sorts the authors by year of death with the live authors appearing last:

java
Select.from(AUTHOR).orderyBy(a -> a.yearOfDeath().ascNullsLast());
Select.from(AUTHOR).orderyBy(a -> a.yearOfDeath().ascNullsLast());

Misc

  • The audit logging implementation now handles @PersonalData.EntitySemantics: 'Other' as defined in Audit Logging.

  • The OData V2 adapter now handles @Aggregation.default: #COUNT.

  • To support deferred foreign key constraints in SQLite during the CSV data import, all CSV files can be imported in an atomic change set. This behavior can be enabled by setting the new property cds.dataSource.csvSingleChangeset to true.

  • You may now write through a projection with calculated fields. The calculated fields will be silently ignored.

Command Line Client for CDS Code Formatter (beta)

Up to now the CDS code formatter was only accessible in an IDE that uses the CDS language server, for example, VSCode with the SAP CDS Language Support extension.

The CDS code formatter now provides a command line interface. This is especially helpful to guarantee a consistent formatting, for example, as a pre-commit hook or within your CI/CD pipeline.

Learn how to use the code formatter CLI.

CDS Editor

Workspace Symbols Query Supports Filters for Artifact Kinds

Workspace Symbols can now be filtered by kinds, for example: entity:... or service:.... The kind can be shortened, for example, s:... for services. A shortcut kind may match multiple kinds: e:... matches entities, enums, and elements.

Workspace Symbols with filtering by kind

Performance and Memory Improvements

The CDS language server is now bundled and minified to further reduce startup time. The caching of indexes was optimized to reduce memory.

Improved Code Completion

Code completion for index.cds files now renders just the folder when selected.

Archived Changelogs 2021

When you're looking for our changelog, you'll notice that we "archived" already our changelog for the past year. You can still search, navigate and find it. But we rearranged the content to keep the most recent content at the top.