Skip to content
On this page

July 2021

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

On-the-fly TypeScript with cds-ts

Use the cds-ts CLI command instead of cds to avoid having to precompile TypeScript files to JavaScript each time and speed up development.

sh
cds-ts serve world.cds
cds-ts serve world.cds
sh
cds-ts watch
cds-ts watch

Learn more about using TypeScript.

Swagger UI Made Easier

For Node.js apps, less code is now needed to serve exported OpenAPI definitions in Swagger UI. Just install the new cds-swagger-ui-express package:

sh
npm add --save-dev cds-swagger-ui-express
npm add --save-dev cds-swagger-ui-express

And add a server.js file:

js
const cds = require ('@sap/cds')
module.exports = cds.server

if (process.env.NODE_ENV !== 'production') {
  const cds_swagger = require ('cds-swagger-ui-express')
  cds.on ('bootstrap', app => app.use (cds_swagger()) )
}
const cds = require ('@sap/cds')
module.exports = cds.server

if (process.env.NODE_ENV !== 'production') {
  const cds_swagger = require ('cds-swagger-ui-express')
  cds.on ('bootstrap', app => app.use (cds_swagger()) )
}

Follow the Open API preview links on the index page and see your API definitions in action: Swagger UI

Learn more about OpenAPI publishing.

New CAP/SAP Fiori Sample

SFLIGHT is a new sample app for the travel reference scenario, built with CAP and SAP Fiori elements.

The purpose of this sample app is to demonstrate SAP Fiori annotations, compare SAP Fiori features on various stacks (CAP Node.js, CAP Java SDK, ABAP) and run UI test suites on various stacks.

Currently the app is only available for the CAP Node.js runtime. A version for CAP Java SDK will follow soon.

SFLIGHT App

Try out the SFLIGHT app.

New End-to-End Tutorials

Try out step by step our new tutorials to Build an Application End-to-End using CAP, Node.js, and VS Code. You will develop a business application using CAP, enhance it with an SAP Fiori UI, and add business logic to it. Furthermore, you will add a Launch Page to start the UIs, add roles and authorization checks, and deploy your application to SAP Business Technology Platform using SAP HANA Cloud Service and Launchpad Service.

CAP Mission

As a next step you can Configure and Run a Predefined SAP Continuous Integration and Delivery (CI/CD) Pipeline for your developed CAP application.

Command Line / Toolkit

Best Guess for Unknown Commands

The command line interface (CLI) of @sap/cds-dk offers you a best guess in case a command can't be found or if your input is ambiguous, for example, due to a typing mistake.

The following screenshot shows cds output for the unknown command logu.

CDS message for unknown command

Importer Improvements

OData V4 Support

In much the same way as with OData v2, cds import now supports input documents for OData V4.

Preserved Documentation

If your imported EDMX documents contain tags like <Documentation><Summary>, <LongDescription> (OData V2), or Core.Description/LongDescription annotations (OData V4), these are now preserved in the resulting .csn file.

To carry this documentation over to your provided services, generate EDMX files with the respective Core.Description annotations:

cds compile --to edmx --docs
cds compile --to edmx --docs

CDS Editors Speedup

The following applies to CDS editors in SAP Business Application Studio and Visual Studio Code.

More and more users create models with hundreds of files. With this release, we introduce some settings to improve the editor performance and also changed some defaults. Notable settings:

SettingDescription
Cds: Workspace Validation ModeNew default: OpenEditorsOnly
Cds > Workspace: ScanCsnNew setting. Default: off
Cds > Quickfix: ImportArtifactNew setting. Default: off
Cds > Contributions > Enablement: OdataNew setting. Default: on

Best performance is achieved with default CDS settings, except for the last one in the list above → Switch it off to speed up compilation, if you can do without Editor support for Fiori annotations.

Additionally, you may want to adjust some non-CDS settings to further increase performance:

SettingDescription
Editor > Goto Location: Alternative Definition CommandDon't use goToReferences to avoid unnecessary recompilations.
Workbench > Editor > Limit: ValueLimit the number of recompilations in related editors (using statements)
Workbench > Editor > Limit: EnabledEnable the Limit: Value setting.

CDS Language & Compiler

Dynamic Expressions in SAP Fiori Annotations

In particular, when writing annotations for SAP Fiori UIs, you may want to make use of dynamic expressions in annotation values. They are evaluated in the front end and can, for example, be used to avoid status mapping in the backend.

Provide an expression in the EDM JSON representation, like:

cds
@UI.Hidden: {$edmJson: {$If: [{$Eq: [{$Path: 'status'}, 'visible']}, false, true]}}
@UI.Hidden: {$edmJson: {$If: [{$Eq: [{$Path: 'status'}, 'visible']}, false, true]}}

and the compiler will translate it to the corresponding XML:

xml
<Annotation Term="UI.Hidden">
  <If>
    <Eq>
      <Path>status</Path>
      <String>visible</String>
    </Eq>
    <Bool>false</Bool>
    <Bool>true</Bool>
  </If>
</Annotation>
<Annotation Term="UI.Hidden">
  <If>
    <Eq>
      <Path>status</Path>
      <String>visible</String>
    </Eq>
    <Bool>false</Bool>
    <Bool>true</Bool>
  </If>
</Annotation>

Learn more about Dynamic Expressions.

Define Views with the Exists Predicate

Use the Exists Predicate with path expressions and infix filters as a simplified way to define views with correlated exists subqueries:

sql
SELECT from Authors where exists books[year=2000]
SELECT from Authors where exists books[year=2000]

unfolds to:

sql
SELECT name FROM Authors AS a WHERE EXISTS (
  SELECT 1 FROM Books AS b WHERE b.author_id = a.id AND b.year = 2000
)
SELECT name FROM Authors AS a WHERE EXISTS (
  SELECT 1 FROM Books AS b WHERE b.author_id = a.id AND b.year = 2000
)

Learn more about the Exists Predicate in CQL.

Node.js Runtime

This release focuses on quality and incremental steps towards larger feature packages. See the changelog for more details.

Merged Runtime Packages ❗️

We merged the former package @sap/cds-runtime into @sap/cds.

As @sap/cds-runtime was always an internal package, this should not affect you. Yet, if, for any reason, you had @sap/cds-runtime in your list of dependencies, you should remove it.

Important Changes ❗️

The following changes affect undocumented internal implementations, and hence shouldn’t affect CAP-based projects. Nevertheless, they’re listed here for your reference.

  • Cascade delete order reverted from leaves to root → Fixes an issue in cascading delete where a child entity has more than one parent, for example, Books and Restaurants both have a composition of many Reviews

  • Always use flag u during input validation via @assert.format

Kibana-Ready Logging Out of the Box (beta)

We now provide a Kibana-friendly log formatter to use with cds.log(). Currently, the formatter must be activated via cds.env.features.kibana_formatter = true (additional to NODE_ENV === 'production'), but it will become the default in the future.

TIP

Note that the formatter is in beta state and feedback is welcome!

OData Return Formats

The Node.js runtime now supports the prefer header return with values minimal and representation. The default value for the server is configurable at cds.env.odata.prefer.return. If not configured, the default is representation.

Further, annotation @Core.ContentDisposition.Filename is now supported. See Serving Media Data for more details.

Java SDK

Important Changes ❗️

Spring Boot 2.5 Support

  • Update the CAP Java SDK to version 1.17.0 if you want to use Spring Boot 2.5. This Spring Boot version came with incompatible changes that were adopted by the CAP Java SDK.
  • Note that CAP Java 1.17.0 now requires Spring Boot 2.5. Therefore, please update your Spring Boot dependency if you adopt this CAP Java version!

Enhanced Media Streaming Support

You can now use the @Core.ContentDisposition.Filename annotation to enable web browsers to handle the media data as an attachment download.

Enhanced Remote Service Consumption

You can now use aliases in projections you define on entities used in remote OData queries, for example:

cds
entity Addresses as projection on external.A_BusinessPartnerAddress {
  key AddressID as ID,
  key BusinessPartner as businessPartner,
  CityName as city,
  StreetName as street,
  HouseNumber as houseNumber
}
entity Addresses as projection on external.A_BusinessPartnerAddress {
  key AddressID as ID,
  key BusinessPartner as businessPartner,
  CityName as city,
  StreetName as street,
  HouseNumber as houseNumber
}

These projections can then be used to retrieve data from a Remote Service:

java
bupa.run(Select.from("Addresses")).stream().map(a -> a.get("city"));
bupa.run(Select.from("Addresses")).stream().map(a -> a.get("city"));

In addition, the IN operator is now supported in remote OData queries. In OData V2, which doesn't natively support IN the query is transformed into multiple comparisons concatenated by OR.

Alter Single Entity Properties

You can read and modify a property of an entity directly by sending GET, POST, PUT, and DELETE requests to the properties URL, for example POST .../odata/v4/Person/name. Primitive and complex collections are also supported.

Reliable Implicit Sorting

Implicit Sorting now works reliably when aggregation functions are used in queries. Also, queries that don't use a limit (top/skip, for example when Implicit Pagination is disabled) are not implicitly sorted anymore to improve performance.

Improved Development Turnaround Times

The CDS Maven Plugin helps improving development roundtrips:

  • It automatically creates JavaDoc for the generated Data Accessor interfaces based on doc comments in the CDS model.
  • A new goal cds:build combines the existing goals cds:cds and cds:generate.

Path Expressions on Outer References in EXISTS

You can now use path expressions based on outer referenced in an exists subquery. This query selects all books where the publisher's city is the same as the author's city of birth:

java
Select.from(BOOKS).where(b -> b.exists(outer ->
   Select.from(AUTHOR).where(a -> outer.publisher().city().eq(a.cityOfBirth())));
Select.from(BOOKS).where(b -> b.exists(outer ->
   Select.from(AUTHOR).where(a -> outer.publisher().city().eq(a.cityOfBirth())));

Support Doc Comments in Code Generation

Doc comments in CDS are now converted to Javadoc comments in generated Java artifacts:

cds
/**
 * A medium for recording information in the form of writing
 */
entity Books {
  key id : GUID;

  /**
   * A name for the book which is usually chosen by the author
   */
  title : String;
}
/**
 * A medium for recording information in the form of writing
 */
entity Books {
  key id : GUID;

  /**
   * A name for the book which is usually chosen by the author
   */
  title : String;
}

→ produces this Java output:

js
/**
 * A medium for recording information in the form of writing
 */
interface Books {
  String getID();

  /**
   * A name for the book which is usually chosen by the author
   */
  String getTitle();
}
/**
 * A medium for recording information in the form of writing
 */
interface Books {
  String getID();

  /**
   * A name for the book which is usually chosen by the author
   */
  String getTitle();
}

Miscellaneous

  • Virtual elements can now be set by client requests. See section Virtual Elements for more details.
  • The interface EventContext now exposes the keySet() method to iterate over all event parameter keys.
  • Support SAP proprietary local 3Q (en-US-x-saprigi)