---
title: December 2024
versions:
  cdsjs: 8.6.0+
  cdsdk: 8.6.0+
  cdsc: 5.6.0+
  cdsmtxs: 2.4.2+
  java: 3.6.0+
---

# December 2024

<ReleaseBadges />

<!-- ::: tip Preview Release Notes
This is a preview of the release notes of our upcoming release.
With these notes we want to share with you in advance what to expect soon.
Note though that these notes are still work in progress, not official yet,
and might still change.
::: -->

[[toc]]

<span id="eanode" />

<span id="ams" />

## CDS Language & Compiler {#cds}

### New `CQN` Spec Using `.d.ts`

We rewrote the [CQN specification](/@external/cds/cqn) using TypeScript declarations ([`.d.ts` files](https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html)).
This not only fills in many gaps that we had in our former documentation, it also allows for better IntelliSense
and easier integration with other projects.

```tsx
class SELECT { SELECT: {
  distinct?   : true
  count?      : true
  one?        : true
  from        : source
  columns?    : column[]
  where?      : xo[]
  having?     : xo[]
  search?     : xo[]
  groupBy?    : expr[]
  orderBy?    : order[]
  limit?      : { rows: val, offset: val }
}}
```

[See the new _CQN specification_](/@external/cds/cqn) {.learn-more}

### Annotating Foreign Keys <Beta />

Now, you can specifically annotate a _foreign key element_ of a [managed association](/@external/cds/cdl#managed-associations):

```cds
entity Authors { key ID : Integer; }
entity Books   { author : Association to Authors; }

annotate Books:author.ID with @label: 'Author'; // [!code highlight]
```

Previously it wasn't possible to specifically annotate the foreign key elements of
a managed association. The workaround was a mechanism in the OData API generation
that copied all annotations assigned to a managed association to the respective foreign key elements.

## Node.js {#cds-js}

### `cds.on` w/ new `compile` Events <Beta/>

We introduced new [lifecycle events](/@external/node.js/cds-compile#lifecycle-events) emitted by different [`cds.compile`](/@external/node.js/cds-compile) commands. In contrast to [`cds.on('loaded')`](/@external/node.js/cds-server#loaded) that was used before, these new events allow plugins to transform models for specific usages, and even more important, also work for multitenant usages.

The individual events are:

- [`compile.for.runtime`](/@external/node.js/cds-compile#compileforruntime)
- [`compile.to.dbx`](/@external/node.js/cds-compile#compiletodbx)
- [`compile.to.edmx`](/@external/node.js/cds-compile#edmx)

> [!note]
>
> You can already try out using these new events, but there's not much documentation yet, and they're still beta, so could change in the final release. Next, we'll adapt the plugins maintained by us and with that, validate, document, and showcase the new events.

### `cds.env` Enhancements

The [`cds.env`](/@external/node.js/cds-env) module has been optimized and enhanced with these new features:

- Config can be provided also in `.cdsrc.js` and `.cdsrc.yaml` files, also in plugins.
- Profile-specific `.env` files can be used, for example, `.hybrid.env` or `.attic.env`.

::: code-group

```yaml [.cdsrc.yaml]
cds:
  requires:
    db:
      kind: sql
      "[hybrid]":
        kind": hana
```

```js [.cdsrc.js]
module.exports = {
  cds: {
    requires: {
      db: {
        kind: 'sql',
        '[hybrid]': {
          kind: 'hana'
        }
      }
    }
  }
}
```

```json [.cdsrc.json]
{
  "cds": {
    "requires": {
      "db": {
        "kind": "sql",
        "[hybrid]": {
          "kind": "hana"
        }
      }
    }
  }
}
```

```properties [.hybrid.env]
cds.requires.kind = hana
```

:::

> [!tip]
>
> As these enhancements apply also to any configuration for `cds-dk` and `cds-mtxs`, you can now use the same configuration files for all tools, even in Java projects.

::: warning Do not load `@sap/cds` in _.cdsrc.js_
You can generally use any JavaScript code within a _.cdsrc.js_ file. However, you **must not** import or load any `@sap/cds` module, as this can create circular dependencies in `cds.env`, leading to undefined behaviors.
:::

### `cds.ql` Enhancements

The `cds.ql` module has been optimized, consolidated, and improved for robustness, as well as enhanced with new functions to facilitate programmatic construction of CQN objects. In detail:

- Besides being a facade for all related features, [`cds.ql`](/@external/node.js/cds-ql) now also is a function to turn any respective input into an instance of respective subclasses of [`cds.ql.Query`](/@external/node.js/cds-ql#class-cds-ql-query); for example, the following all produce an equivalent instance of [`cds.ql.SELECT`](/@external/node.js/cds-ql#select):

  ```js
  let q = cds.ql `SELECT from Books where ID=${201}`
  let q = cds.ql (`SELECT from Books where ID=${201}`)
  let q = cds.ql ({
    SELECT: {
      from: { ref: [ 'Books' ] },
      where: [ { ref: [ 'ID' ] }, '=', { val: 201 } ]
    }
  })
  let q = SELECT.from('Books').where({ID:201})
  ```

- New [CXL-level helper functions](/@external/node.js/cds-ql#expressions) to facilitate construction of CQN objects have been added, which you can use like that:

  ```js
  const { expr, ref, val, columns, expand, where, orderBy } = cds.ql
  let q = {
    SELECT: {
      from: ref`Authors`,
      columns: [
        ref`ID`,
        ref`name`,
        expand (ref`books`, where`stock>7`, orderBy`title`,
          columns`ID,title`
        )
      ],
      where: [ref`name`, 'like', val('%Poe%')]
    }
  }
  await cds.run(q)
  ```

- All `cds.ql` functions, as well as all `cds.parse` functions, and all related `srv.run` methods now consistently support [tagged template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates). For example, all of these work now:

  ```js
  await cds.run (cds.parse.cql `SELECT ID,title from Books`)
  await cds.run `SELECT ID,title from Books`
  await cds.ql `SELECT ID,title from Books`
  await SELECT `ID,title from Books`
  await SELECT `ID,title`.from`Books`
  await SELECT.from `Books {ID,title}`
  await cds.read `ID,title from Books`
  await cds.read `Books`
  await cds.read `Books where ID=201`
  ```

> [!warning]
> In course of this, former globals `CDL`, `CQL`, and `CXL` have been deprecated
> in favor of respective [`cds.parse.cdl`](/@external/node.js/cds-compile#parse-cdl), [`.cql`](/@external/node.js/cds-compile#parse-cql), and [`.expr`](/@external/node.js/cds-compile#parse-cxl) counterparts.

[Learn more in the reference docs for _`cds.ql`_](/@external/node.js/cds-ql) {.learn-more}

[Note in there the recommendation for _`cds repl`_](/@external/node.js/cds-ql#using-cds-repl) {.learn-more}

### OData Containment

The new config option <Config>cds.odata.containment: true</Config> allows to switch on containment mode which maps CDS Compositions to effective OData Containment Navigation Properties as [introduced in OData v4](http://docs.oasis-open.org/odata/odata/v4.0/cos01/part3-csdl/odata-v4.0-cos01-part3-csdl.html#_Toc372793924) and supported meanwhile by Fiori clients.

For example, given the following CDS model:

```cds
service Sue {
  entity Orders { //...
    Items : Composition of many { /*...*/ }
  }
}
```

That will be exposed like that with containment mode enabled (the removed line indicates what is not exposed anymore):

```xml
 <EntityContainer Name="EntityContainer">
   <EntitySet Name="Orders" ... />
-  <EntitySet Name="Orders_Items" ... /> <!-- [!code error] -->
 </EntityContainer>
```

Contained entities can only be reached via navigation from their roots reducing the entry points of the OData service.

> [!tip]
> While we think that containment mode is best for most applications, and fully supported by Fiori clients, we provide it as an opt-in for the time being, for you to test it in your apps. It's planned to become the default in the next major release.

<!-- [Learn more about containment in OData APIs](/@external/guides/protocols/odata#cds-odata-containment-true-false) {.learn-more} -->

### Function Parameters via Query Options

The [OData V4.01 specification](https://docs.oasis-open.org/odata/new-in-odata/v4.01/cn04/new-in-odata-v4.01-cn04.html#sec_NewInvokingFunctionswithImplicitPara) allows providing parameters of functions as query options which is now supported by the Node.js runtime. The example below illustrates the usage:

```http
GET sue/stock(id=2) // traditional syntax
GET sue/stock?id=2  // new syntax
```

[Learn more about functions in CDS](/@external/guides/services/custom-actions#calling-actions--functions) {.learn-more}

### Consolidated Authorization Checks

The processing of `@restrict.where` was aligned with the CAP Java stack.
As a result, there are the following behavioral changes in edge cases, each with their own compat feature flag to deactivate the change until the next major:

- Read restrictions on the entity are no longer taken into consideration when evaluating restrictions on bound actions/ functions. Instead, only the restrictions that apply to the bound action/ function are evaluated. <br>
Deactivate via <Config>cds.features.compat_restrict_bound: true</Config>.

- For `UPDATE` and `DELETE` requests, additional filters (these are, those not originating from key predicates) are no longer considered during the authorization check. For example, assumed we got the equivalent of this query:

  ```sql
  UPDATE Books SET title = 'foo' WHERE title = 'bar'
  ```

  The filter `title = 'bar'` is ignored for access control checks, and, effectively, the user needs to be allowed to update all books.

Please note that `UPDATE` and `DELETE` requests from a client always contain key predicates, making this change only affect service calls executed in custom handlers. In case you encounter issues with the new behavior, you can deactivate it via <Config>cds.features.compat_restrict_where: true</Config>.

## Java {#cds-java}

### Important Changes ❗️ { .important #important-changes-in-java}

#### NPM Build-Plugin Support { #npm-build-plugins }

To support a growing number of NPM build-plugins for CDS build,
we recommend a slightly different CAP Java project setup which uses `devDependencies` section in the _package.json_ file.
Consequently, also the required dependency to `@sap/cds-dk` now should be added there.

To ensure stable versions of the packages, `npm ci` should be configured for the CDS build:

```xml [srv/pom.xml]
<execution>
  <id>cds.npm-ci</id>
  <goals>
    <goal>npm</goal>
  </goals>
  <configuration>
    <arguments>ci</arguments>
  </configuration>
</execution>
```

The goal `install-cdsdk` of the cds-maven-plugin has been deprecated and should be removed from the project.

[Learn how to Migrate From Goal `install-cdsdk` to `npm ci`.](/@external/java/developing-applications/building#migration-install-cdsdk){.learn-more}

::: info New projects in recommended setup
The built-in [Maven Archetype](/@external/java/getting-started#run-the-cap-java-maven-archetype) creates a Java project with the recommended setup.
:::

<span id="java-mTLS-kafka" />

### SAP Document Management Service Plugin

The new Calesi plugin [com.sap.cds/sdm](https://central.sonatype.com/search?q=com.sap.cds.sdm) is now available as [open source on GitHub](https://github.com/cap-java/sdm). You can easily add the dependency to your application's dependencies and use the `Attachments` type in your model.

::: code-group

```xml [srv/pom.xml]
<dependency>
  <groupId>com.sap.cds</groupId>
  <artifactId>sdm</artifactId>
  <version>1.0.0</version>
</dependency>
```

:::

![Screenshot showing the attachments table in an SAP Fiori UI.](assets/jun24/sdm-table.png)

[Find more details about the SAP Document Management Service Plugin.](https://github.com/cap-java/sdm#readme)

<span id="java-ord" />

<span id="java-kafka-dwc" />

### IAS Support for Kyma

CAP Java now offers out-of-the-box [integration](/@external/java/security#xsuaa-ias) for [SAP Cloud Identity Authentication](https://help.sap.com/docs/cloud-identity-services) (IAS) in the [SAP BTP, Kyma runtime](https://discovery-center.cloud.sap/serviceCatalog/kyma-runtime). It performs proof-of-possession checks on the client certificates passed by calling IAS applications in the context of Kyma runtime.

### SAP HANA Connection Pooling Optimized

Multitenant applications configured with a [shared database pool](/@external/java/multitenancy#combine-data-pools) for all tenants help reduce resource consumption from database connections. However, this mode requires logging in with the technical database user of the current business tenant for each request. To optimize performance, CAP Java now skips the login if the pooled connection is already connected to the corresponding user, saving an extra roundtrip and reducing CPU consumption in the database.

### Outbox Message Versioning

Messages written to [Transactional Outbox](/@external/java/event-queues#default-outbox-services) can originate from application instances of different versions.
Instances of an outdated version might introduce failures or inconsistencies when trying to collect messages of younger versions.

To avoid such a situation, you can now configure CAP Java to write an application version outbox message being published.
Outbox collectors of an application instance will not collect messages of younger versions.

Using [<Config java keyOnly filesOnly>cds.environment.deployment.version: ${project.version}</Config>](/@external/java/developing-applications/properties#cds-environment-deployment-version), we recommend configuring the application with the version identifier from the Maven build automatically.

This requires the build version available in the resources folder:

::: code-group

```xml [srv/pom.xml]
<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
    </resource>
  </resources>
</build>
```

:::

CAP Java can only support version identifiers which have an ordering.

[Learn more about Outbox Event Versions.](/@external/java/event-queues#event-versions){.learn-more}

### CDS Config in `.cdsrc.yaml` Files

Alternative to `.cdsrc.json` files, Java projects can now also use `.cdsrc.yaml` files
to configure the CDS compiler and `cds-dk`.

[See respective entry in the Node.js section.](#cdsenv-enhancements) {.learn-more}

## Tools { #tools}

### `cds repl` Enhancements

As you know, [`cds repl`](/@external/tools/cds-cli#cds-repl) is your friend when you want to find out, how things work. While this is especially relevant for Node.js projects, it also applies to Java projects. For example, to find out how a CSN or CQN object notation for a given CDL or CQL could look like that:

```sh
cds repl  # from your command line
```

```js
cds.parse`
  entity Foo { bar : Association to Bar }
  entity Bar { key ID : UUID }
`
```

```js
cds.ql`SELECT from Authors {
  ID, name, books [order by title] {
    ID, title, genre.name as genre
  }
} where exists books.genre[name = 'Mystery']`
```

This release brings a few new enhancements to `cds repl` as follows:

- New [REPL dot command](https://nodejs.org/en/learn/command-line/how-to-use-the-nodejs-repl#dot-commands) `.run` allows to start Node.js `cds.server`s:

  ```sh
  .run cap/samples/bookshop
  ```

- New CLI option `--run` to do the same from command line, for example:

  ```sh
  cds repl --run cap/samples/bookshop
  ```

- New CLI option `--use` to easily use the features of a `cds` module, for example:

  ```sh
  cds repl --use ql # as a shortcut of that within the repl:
  ```

  ```js
  var { expr, ref, columns, /* ...and all other */ } = cds.ql
  ```

- New [REPL dot command](https://nodejs.org/en/learn/command-line/how-to-use-the-nodejs-repl#dot-commands) `.inspect` to display objects with configurable depth:

  ```sh
  .inspect cds .depth=1
  .inspect CatalogService.handlers .depth=1
  ```

### `cds watch` for TypeScript

In a TypeScript project, you can now just run `cds watch` as if it was a JavaScript project.
It will automatically detect TypeScript mode based on a `tsconfig.json` and run [`cds-tsx`](/@external/node.js/typescript#cds-tsx) under the hood.
In other words, it's not necessary anymore to use `cds-tsx watch`.

```sh
cap/sflight $ cds watch

Detected tsconfig.json. Running with tsx.
...
[cds] serving TravelService { impl: 'srv/travel-service.ts', path: '/processor' }
...
```
