July 2021
Welcome to the release of CAP. 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.
cds-ts serve world.cds
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:
npm add --save-dev cds-swagger-ui-express
And add a server.js
file:
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:
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.
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.
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 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:
Setting | Description |
---|---|
Cds: Workspace Validation Mode | New default: OpenEditorsOnly |
Cds > Workspace: ScanCsn | New setting. Default: off |
Cds > Quickfix: ImportArtifact | New setting. Default: off |
Cds > Contributions > Enablement: Odata | New 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:
Setting | Description |
---|---|
Editor > Goto Location: Alternative Definition Command | Don't use goToReferences to avoid unnecessary recompilations. |
Workbench > Editor > Limit: Value | Limit the number of recompilations in related editors (using statements) |
Workbench > Editor > Limit: Enabled | Enable 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:
@UI.Hidden: {$edmJson: {$If: [{$Eq: [{$Path: 'status'}, 'visible']}, false, true]}}
and the compiler will translate it to the corresponding XML:
<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:
SELECT from Authors where exists books[year=2000]
unfolds to:
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:
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:
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 goalscds:cds
andcds: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:
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:
/**
* 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:
/**
* 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
)