---
title: April 2024
versions:
  cdsjs: 7.9.0
  cdsdk: 7.9.1
  cdsc: 4.9.0
  cdsmtxs: 1.18.0
  java: 2.9.0

---

<script setup>
  import PlaygroundBadge from '../../@external/tools/cds-lint/components/PlaygroundBadge.vue'
</script>

# April 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]]

## Fewer Views in Database <Beta />

New option `cds.sql.transitive_localized_views: false` allows to skip generating _transitive_ localized views. For example, use it like that in your _package.json_ or in your _.cdsrc.json_:

::: code-group

```json [package.json]
{ "cds": {
  "sql": {                              // [!code focus]
    "transitive_localized_views": false // [!code focus]
  }                                     // [!code focus]
}}
```

:::

::: tip Java: `false` as default
In CAP Java, transitive localized views are never used. Hence the default value is `false` and you automatically benefit from fewer views.
:::

::: warning Node.js: Only with new database services
In CAP Node.js, transitive localized views can only be disabled when using _new_ database services. For compatibility with old database services the default value is still `true`, but will be changed to `false` in the future.
:::

::: details What are transitive localized views?

As explained in the [_Localized Data_ guide](/@external/guides/uis/localized-data#localized-helper-views), localized views are created for entities with localized data, recursively. This also includes entities which don't have localized elements on its own, but only associations to such. For example:

```cds
entity Books { ...
  title : localized String; // has own localized data
}
entity Authors { ...
  books : Association to many Books;
}
```

Without `cds.sql.transitive_localized_views: false`, a localized view is created for `Authors` as well, because it has an association to `Books` which has localized data. This is what we call a _transitive_ localized view.

:::

::: details Dry-run in your project...

For example when running this in _cap/sflight_:

::: code-group

```sh [macOS/Linux]
cds_sql_transitive__localized__views=true  cds \* -2 sql | grep -c VIEW
cds_sql_transitive__localized__views=false cds \* -2 sql | grep -c VIEW
```

```cmd [Windows]
set cds_sql_transitive__localized__views=true
cds * -2 sql | find /C "VIEW"
set cds_sql_transitive__localized__views=false
cds * -2 sql | find /C "VIEW"
```

This should print out some numbers, showing that the number of views created in the database is reduced from 80 to 55, like this:

```txt
80
55
```

:::

::: tip Speeds up database upgrades
This option can significantly reduce the number of views in your database, which can speed up database upgrades significantly, especially using SAP HANA.
:::

## Expressions as Annotation Values <Beta /> { #expression-annotations }

The handling of [expressions as annotation values](/@external/cds/cdl#expressions-as-annotation-values)
has been significantly enhanced.

### Propagation

When annotations are propagated in views/projections or along type references,
the compiler now automatically adapts references in expression-like annotation values, if necessary.

Example:

```cds
entity E {
  @Common.Text: (text) // [!code highlight]
  code : Integer;
  text : String;
}
entity P as projection on E {
  code,
  text as descr // [!code highlight]
}
```

When propagated to element `code` of projection `P`, the annotation is automatically
rewritten to `@Common.Text: (descr)` due to the renaming of `text` to `descr`.

::: tip Note the syntax

Expression-like annotation values need to be enclosed in parentheses.
It's still possible to provide a reference as an annotation value without parentheses,
but such references are not adapted.

:::

### References in OData Annotations

When the CDS model is flattened for OData generation, references in expression-like annotation
values are automatically adapted.

Example:

```cds
type Price {
  @Measures.ISOCurrency: (currency) // [!code highlight]
  amount : Decimal; // [!code highlight]
  currency : String(3);
}
service S {
  entity Product {
    key id : Integer;
    name : String;
    price : Price; // [!code highlight]
  }
}
```

The resulting annotation in EDMX correctly references the flattened element:

```xml
<Annotations Target="S.Product/price_amount">
  <Annotation Term="Measures.ISOCurrency" Path="price_currency"/>
</Annotations>
```

::: warning Restrictions concerning the foreign key elements of managed associations

1. Usually an annotation assigned to a managed association is copied to the foreign key elements of the association.
This is _not_ done for annotations with expression values. That means, it's currently not possible
to use expression-valued annotations for annotating foreign keys of a managed association.

2. In an expression-valued annotation, it's not possible to reference the foreign key element
of a managed association.

:::

### Expressions in OData Annotations

Expressions in OData annotations are automatically translated to the corresponding EDMX syntax. You can now simply write the following:

```cds
service S {
  @UI.LineItem : [{
    Value: (status),
    Criticality: ( status = 'O' ? 2 : ( status = 'A' ? 3 : 0 ) )  // [!code highlight]
  }]
  entity Order {
    key id : Integer;
    status : String;
  }
}
```

Previously, you'd have needed to write the following expression:
<!-- cds-mode: ignore, because it is only a snippet without context -->
```cds
Criticality : { $edmJson: { $If: [{$Eq: [{ $Path: 'status'}, 'O']}, 2,
                          { $If: [{$Eq: [{ $Path: 'status'}, 'A']}, 3, 0] }] } }
```

<div id="relnote-embedded-analytics" />

## Node.js {#cds-js}

### INSERT w/ Streams and Subselects

With new database services (SAP HANA, PostgreSQL and SQLite) you can now specify streams and subselect queries as arguments to `INSERT.entries()`, for example:

Using a **stream** instead of reading and parsing full JSONs or alike into memory:

```js
let streamed = fs.createReadStream('books.json')
await INSERT.into(Books) .entries (streamed)
```

Using a **subselect** query to copy _within_ the database:

```js
await INSERT.into(Books) .entries (SELECT.from(Products))
```

[Learn more about `INSERT.entries()`](/@external/node.js/cds-ql#insert-entries) {.learn-more}

::: tip Recommendation

Prefer using streams and subselects whenever possible. Streams significantly reduce memory consumption and increase scalability. Subselects delegate all read/writes to the database.

:::

## Java {#cds-java}

<span id="java-attachments-plugin" />

### Enhanced Index Page

The [Index Page](/@external/get-started/bookshop#generic-indexhtml) has been enhanced in this release. It now lists links to all web applications contained in the `app` folder, which are now served automatically as well.
In addition it comes with SAP Fiori preview links for entities with UI annotations and has a renewed stylesheet:

![The screenshot is explained in the accompanying text.](./assets/apr24/java-indexpage-light.png){width="400px" .mute-dark}

### Secure by Default

A bunch of CAP Java features are available for development scenarios only:

- Index Page
- Mock user authentication
- ...

To make sure these features are deactivated automatically in production mode, you can now tell the CAP runtime which Spring profile should be interpreted as productive:

```yaml
cds.environment.production.profile: cloud
```

Note that the Java buildpack chooses the `cloud` profile by default.

<span id="java-ias-mtxs" />

### SAP Java Buildpack 2

You can now choose to deploy CAP Java by means of SAP Java Buildpack version 2 (`sap_java_buildpack_jakarta`) which brings sapmachine 17 and 21 in offline mode:

```yaml
parameters:
  buildpack: sap_java_buildpack_jakarta
properties:
  JBP_CONFIG_COMPONENTS: "jres: ['com.sap.xs.java.buildpack.jre.SAPMachineJRE']"
  JBP_CONFIG_SAP_MACHINE_JRE: '{ version: 21.+ }'
```

[Learn more about SAP Java buildpack usage](/@external/java/developing-applications/configuring#buildpack){.learn-more}

### Full-Fledged Sample Project

`cds add sample` now generates a full-fledged  CAP Java application with bookshop entities that can be modified by mock users in a UI.
In contrast, the result of `cds add tiny-sample` exposes the bookshop only as OData API.

## Tools { #tools}

### Shell Completion for CDS Commands <Beta />

You can now easily enable shell completion in your shell for all `cds` commands like `build`, `compile`, and for `cds` itself.

Simply run the following command to install it once:

```sh
cds add completion
```

After that, you have to source or restart your shell and you're good to go to use `tab` key for completion.

Currently, _bash_, _zsh_, _Git Bash_ and _PowerShell_ are supported.

### Test Data Generation  <Beta />

In VS Code, test data for your application model is now available at your fingertips:

<video src="./assets/apr24/generate-data-json_compressed.mp4" autoplay loop muted webkit-playsinline playsinline />

With the new commands _Generate Model Data as JSON / CSV_, select a CDS entity in the pick list, and then test data is inserted at the cursor position in the active text editor.  This may include:

- plain `.csv` and `.json` files used for initial data deployment
- test `.js`/`.ts` files
- `.http` files used for manual tests with the [REST Client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client)

You can then modify the data as you wish potentially using AI tools.

Under the hood, this feature uses the `cds add data` CLI like this:

```sh
cds add data --records 2 --content-type csv --filter Books
```

Which will create 2 CSV records with test data for all entities matching _Books_ and store it in `db/data` by default.
Run `cds add data --help` to see all options.

[Learn more about test data generation](/@external/tools/cds-cli#data){.learn-more}

### HTTP Requests Generation  <Beta />

The new _Generate HTTP Requests_ command in VS Code allows you to quickly generate sample HTTP requests for your services and entities, including sample data, authentication and endpoint information. You can execute the created request data with the [REST Client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) in `.http` files.

<video src="./assets/apr24/generate-http-requests_compressed.mp4" autoplay loop muted webkit-playsinline playsinline />

Under the hood, the extension uses the `cds add http` CLI command as follows:

```sh
cds add http --filter Authors
```

This creates `.http` files with sample read and write requests for all services that include the `Authors` entity.

To add authentication and a CloudFoundry endpoint, use the `--for-app <app name>` option.

[Learn more about request generation](/@external/tools/cds-cli#http){.learn-more}

### CDS Syntax Highlighting in VS Code Markdown Editor

The CDS language is now highlighted in `cds` code fences in the markdown editor of VS Code:

![syntax highlighting in markdown editor](assets/apr24/cds-in-md-editor.png){ style="width:400px; box-shadow: 1px 1px 5px #888888"}

This is useful for all you authors that write about CAP and the CDS language.

<!-- ::: info Not in markdown _preview_ -->
The [markdown _preview_](https://code.visualstudio.com/docs/languages/markdown#_markdown-preview) in VS Code does not highlight CDS though.
This remains to be tackled in a future release.
<!-- ::: -->

[Learn more about highlighting code in markdown](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks) {.learn-more}

### Playground for CDS ESLint Rules

You can now try each of the available [ESLint rules for CDS](/@external/tools/cds-lint/rules/) in a playground environment.
This can help you better understand what the rule is supposed to do.

See this example from the [auth-valid-restrict-where](/@external/tools/cds-lint/rules/auth-valid-restrict-where/) rule with the _Open in Playground_ link:

::: code-group

```cds [srv/cat-service.cds]
service CatalogService {
  // invalid `where` expression, the equality operator is `=`
  @(restrict: [{ grant: 'READ', to: 'Viewer', where: 'CreatedBy === $user' }])
  entity ListOfBooks as projection on Books; // [!code warning]
  ...
}
```

:::
<PlaygroundBadge
  name="auth-valid-restrict-where"
  kind="incorrect"
  :rules="{'@sap/cds/auth-valid-restrict-where': ['warn', 'show']}"
  :files="['db/schema.cds', 'srv/cat-service.cds']"
/>

### ESLint 9 Support

CAP's ESLint plugin `@sap/eslint-plugin-cds` has reached a new major version 3 which is now compatible with the new ESLint major version 9.

This means that you can do the following:

- Adjust your `@sap/eslint-plugin-cds` dependencies from `^2` to `^3`.
- Consult the [ESLint 9 migration guide](https://eslint.org/docs/latest/use/migrate-to-9.0.0) for more information. Especially the notes about the new ['flat' configuration format](https://eslint.org/docs/latest/use/migrate-to-9.0.0#flat-config) are helpful to migrate your ESLint config files.
- Use both, `cds lint` and `eslint`, clients for your project as before.

The [`cds add lint`](/@external/tools/cds-lint/#cds-add-lint) facet now creates ESLint 9 configuration for new projects.

In the upcoming major release of CAP Node.js, the [`cds lint`](/@external/tools/cds-lint/#usage-lint-cli) client will use ESLint 9 by default.

### Binding Shared Service Instances on Cloud Foundry

You can now bind to a shared service instance on Cloud Foundry just like any other service instance.
For example, if you have access to a shared `redis-cache` service instance:

```sh
cds bind messaging --to redis-cache
```

[Learn more about binding shared service instances](/@external/tools/cds-bind#binding-shared-service-instances){.learn-more}

### Overwrite Cloud Service Credentials

You can easily overwrite service credential values with local binding information.
For example, you might need extra information to connect to a Cloud Foundry service via an SSH tunnel:

```sh
cds bind service --to my-service --credentials '{ "proxy_host": "localhost" }'
```

Before, you had to use a `default-env.json` file with the _entire_ credential details locally.

[Learn more about overwriting cloud service credentials](/@external/tools/cds-bind#overwriting-service-credentials){.learn-more}

## CAP Operator Plugin

The [CAP Operator](https://sap.github.io/cap-operator/) manages and automates the lifecycle operations involved in running multitenant CAP applications on Kubernetes (K8s) clusters. If you deploy an application using the CAP Operator, you must manually define the custom resources for the application in a helm chart, which needs time and deep knowledge of helm concepts.

This is where the CAP Operator **plugin** is very useful, as it provides an easy way to generate such a helm chart, which can be easily modified.

[Learn more about how to add and consume the CAP Operator plugin in our documentation](https://github.com/cap-js/cap-operator-plugin#readme). {.learn-more}
