diff --git a/.vitepress/theme/styles.scss b/.vitepress/theme/styles.scss index 75ac9b266..e49c35f61 100644 --- a/.vitepress/theme/styles.scss +++ b/.vitepress/theme/styles.scss @@ -45,6 +45,7 @@ --vp-c-text-1: #000; h1, h2, h3, h4, h5 { color: rgba(60, 60, 67) } + h6 { color: transparent; position: absolute; margin-top: -7.7em; right: 0px; } // we use h6 for alternative anchor targets /* inverts image colors in dark mode */ @@ -346,7 +347,7 @@ main { .prefer::before { content: 'Prefer: '; color: #0a0 } .avoid::before { content: 'Avoid: '; color: #e00 } - .good .green { color:#0a0 }; + .good, .green { color:#0a0 }; .bad, .red, .important { color:darkred; .dark & { color:#e00 } } .grey { color:#777 }; diff --git a/about/bad-practices.md b/about/bad-practices.md index 7b3cd4727..9ffe7acc3 100644 --- a/about/bad-practices.md +++ b/about/bad-practices.md @@ -66,31 +66,31 @@ Alternative frameworks or toolsets follow code generation approaches. Swagger do -| Feature | Swagger | CAP | -|--------------------------------------|:----------------------------------------------------:|:-----------------------------------------:| -| Lines of code for service definition | **~555**{.h3}
written in YAML {.red} | **~11**{.h3}
written in CDS {.green} | -| Lines of code for implementation | **~500**{.h3}
generated
boilerplate {.red} | **0**{.h3} {.green} | -| Size of framework library | 16 MB {.red} | 10 MB {.green} | -| CRUDQ served on DB, including... | ❌ | ✅ | -| Deep Reads & Writes | ❌ | ✅ | -| Deep Hierarchies | ❌ | ✅ | -| Aggregations | ❌ | ✅ | -| Pagination | ❌ | ✅ | -| Sorting | ❌ | ✅ | -| Search | ❌ | ✅ | -| Filtering | ❌ | ✅ | -| Primary Keys | ❌ | ✅ | -| Access Control | ❌ | ✅ | -| Localized Data | ❌ | ✅ | -| Managed Data | ❌ | ✅ | -| Media Data | ❌ | ✅ | -| Temporal Data | ❌ | ✅ | -| Fiori Draft Handling | ❌ | ✅ | -| Exclusive Locking | ❌ | ✅ | -| Conflict Detection (via ETags) | ❌ | ✅ | -| Data Replication (upcomming) | ❌ | ✅ | -| Data Privacy | ❌ | ✅ | -| ... | ❌ | ✅ | +| Feature | Swagger | CAP | +|--------------------------------------|:--------------------:|:---------------------:| +| Lines of code for service definition | **~555**{.h3}{.red} | **~11**{.h3} {.green} | +| Lines of code for implementation | **~500**{.h3} {.red} | **0**{.h3} {.green} | +| Size of framework library | 16 MB {.red} | 10 MB {.green} | +| CRUDQ served on DB, including... | | ✓ | +| Deep Reads & Writes | | ✓ | +| Deep Hierarchies | | ✓ | +| Aggregations | | ✓ | +| Pagination | | ✓ | +| Sorting | | ✓ | +| Search | | ✓ | +| Filtering | | ✓ | +| Primary Keys | | ✓ | +| Access Control | | ✓ | +| Localized Data | | ✓ | +| Managed Data | | ✓ | +| Media Data | | ✓ | +| Temporal Data | | ✓ | +| Fiori Draft Handling | | ✓ | +| Exclusive Locking | | ✓ | +| Conflict Detection (via ETags) | | ✓ | +| Data Replication (upcomming) | | ✓ | +| Data Privacy | | ✓ | +| ... | | ✓ |
diff --git a/about/best-practices.md b/about/best-practices.md index 9a53e6c4f..8031cb0f1 100644 --- a/about/best-practices.md +++ b/about/best-practices.md @@ -7,7 +7,7 @@ status: released Key Concepts & Qualities {.subtitle} -[[toc]] +[[toc]] @@ -22,15 +22,15 @@ The CAP framework features a mix of proven and broadly adopted open-source and S The major building blocks are as follows: -- [**Core Data Services** (CDS)](/cds/) — CAP's universal modeling language, and the very backbone of everything; used to capture domain knowledge, generating database schemas, translating to and from various API languages, and most important: fueling generic runtimes to automatically serve request out of the box. +- [**Core Data Services** (CDS)](../cds/) — CAP's universal modeling language, and the very backbone of everything; used to capture domain knowledge, generating database schemas, translating to and from various API languages, and most important: fueling generic runtimes to automatically serve request out of the box. -- [**Service Runtimes**](/guides/providing-services.md) for [Node.js](/node.js/) and [Java](/java/) — providing the core frameworks for services, generic providers to serve requests automatically, database support for SAP HANA, SQLite, and PostgreSQL, and protocol adaptors for REST, OData, GraphQL, ... +- [**Service Runtimes**](../guides/providing-services.md) for [Node.js](../node.js/) and [Java](../java/) — providing the core frameworks for services, generic providers to serve requests automatically, database support for SAP HANA, SQLite, and PostgreSQL, and protocol adaptors for REST, OData, GraphQL, ... -- [**Platform Integrations**](/plugins/) — providing CAP-level service interfaces (*'[Calesi](#the-calesi-effect)'*) to cloud platform services in platform-agnostic ways, as much as possible. Some of these are provided out of the box, others as plugins. +- [**Platform Integrations**](../plugins/) — providing CAP-level service interfaces (*'[Calesi]()'*) to cloud platform services in platform-agnostic ways, as much as possible. Some of these are provided out of the box, others as plugins. -- [**Command Line Interface** (CLI)](/tools/) — the swiss army knife on the tools and development kit front, complemented by integrations and support in *SAP Build Code*, *Visual Studio Code*, *IntelliJ*, and *Eclipse*. +- [**Command Line Interface** (CLI)](../tools/) — the swiss army knife on the tools and development kit front, complemented by integrations and support in [*SAP Build Code*](), *Visual Studio Code*, *IntelliJ*, and *Eclipse*. -In addition, there is a fast-growing number of [plugins] contributed by open-source and inner-source [communities](/resources/#public-resources) that enhance CAP in various ways, and integrate with additional tools and environments; the [*Calesi* plugins](#the-calesi-effect) are among them. +In addition, there is a fast-growing number of [plugins](../plugins/) contributed by open-source and inner-source [communities](/resources/#public-resources) that enhance CAP in various ways, and integrate with additional tools and environments; the [*Calesi* plugins](#the-calesi-effect) are among them. @@ -62,7 +62,7 @@ We'll dive into each of these concepts in the following sections below, starting ## Domain Models -[CDS](/cds/) is CAP's universal modeling language to declaratively capture knowledge about an application's domain. Data models capture the *static* aspects of a domain, using the widely used technique of *entity-relationship modelling*. For example, a simple domain model as illustrated in this ER diagram: +[CDS](../cds/) is CAP's universal modeling language to declaratively capture knowledge about an application's domain. Data models capture the *static* aspects of a domain, using the widely used technique of [*entity-relationship modelling*](). For example, a simple domain model as illustrated in this ER diagram: ![bookshop-erm.drawio](assets/bookshop-erm.drawio.svg) @@ -87,18 +87,18 @@ entity Authors : cuid, managed { ::: -[Type `Country` is declared to be an association to `sap.common.Countries`.](/cds/common#type-country) {.learn-more} +[Type `Country` is declared to be an association to `sap.common.Countries`.](../cds/common#type-country) {.learn-more} ### Definition Language (CDL) -We use CDS's [*Conceptual Definition Language (CDL)*](/cds/cdl) as a *human-readable* way to express CDS models. Think of it as a *concise*, and more *expressive* derivate of [SQL DDL](https://wikipedia.org/wiki/Data_definition_language). +We use CDS's [*Conceptual Definition Language (CDL)*](../cds/cdl) as a *human-readable* way to express CDS models. Think of it as a *concise*, and more *expressive* derivate of [SQL DDL](https://wikipedia.org/wiki/Data_definition_language). -For processing at runtime CDS models are compiled into a *machine-readable* plain object notation, called *CSN*, which stands for [*Core Schema Notation (CSN)*](/cds/csn). For deployment to databases, CSN models are translated into native SQL DDL. Supported databases are *[SQLite]* and *[H2]* for development, and *[SAP HANA]* and *[PostgreSQL]* for production. +For processing at runtime CDS models are compiled into a *machine-readable* plain object notation, called *CSN*, which stands for [*Core Schema Notation (CSN)*](../cds/csn). For deployment to databases, CSN models are translated into native SQL DDL. Supported databases are [*SQLite*](../guides/databases-sqlite.md) and *[H2](../guides/databases-h2.md)* for development, and [_SAP HANA_](../guides/databases-hana.md) and [_PostgreSQL_](../guides/databases-postgres.md) for production. ![cdl-csn.drawio](assets/cdl-csn.drawio.svg) -See also *[On the Nature of Models](/cds/models)* in the CDS reference docs. {.learn-more} +See also *[On the Nature of Models](../cds/models)* in the CDS reference docs. {.learn-more} @@ -232,7 +232,7 @@ service BookshopService { Most frequently, services expose denormalized views of underlying domain models. They act as facades to an application's core domain data. The service interface results from the _inferred_ element structures of the given projections. -For example, if we take the [*bookshop* domain model](/get-started/in-a-nutshell#capture-domain-models) as a basis, we could define a service that exposes a flattened view on books with authors names as follows (note and click on the *⇒ Inferred Interface* tab): +For example, if we take the [*bookshop* domain model](../get-started/in-a-nutshell#capture-domain-models) as a basis, we could define a service that exposes a flattened view on books with authors names as follows (note and click on the *⇒ Inferred Interface* tab): ::: code-group @@ -260,7 +260,7 @@ service CatalogService { ::: ::: tip **Single-purposed Services** -The previous example follows the recommended best practice of a *[single-purposed service](/guides/providing-services#single-purposed-services)* which is specialized on *one* specific use case and group of users. Learn more about that in the [Providing Services](/guides/providing-services) guide. +The previous example follows the recommended best practice of a *[single-purposed service](../guides/providing-services#single-purposed-services)* which is specialized on *one* specific use case and group of users. Learn more about that in the [Providing Services](../guides/providing-services) guide. ::: ### Service Providers @@ -480,9 +480,9 @@ entity ListOfBooks as projection on underlying.Books { } ``` -We use [CDS's *Conceptual Query Language (CQL)*](/cds/cql) to write queries in a human-readable way. For reasons of familiarity, CQL is designed as a derivate of SQL, but used in CAP independent of SQL and databases. For example to derive new types as projections on others, or sending OData or GraphQL queries to remote services. +We use [CDS's *Conceptual Query Language (CQL)*](../cds/cql) to write queries in a human-readable way. For reasons of familiarity, CQL is designed as a derivate of SQL, but used in CAP independent of SQL and databases. For example to derive new types as projections on others, or sending OData or GraphQL queries to remote services. -Here's a rough comparison of [CQL] with [GraphQL], [OData], and [SQL]: +Here's a rough comparison of [CQL](../cds/cql.md) with [GraphQL](http://graphql.org), [OData](https://www.odata.org), and [SQL](https://en.wikipedia.org/wiki/SQL): @@ -505,7 +505,7 @@ As apparent from this comparison, we can regard CQL as a superset of the other q ### Queries at Runtime -CAP also uses queries at runtime: an OData or GraphQL request is essentially a query which arrives at a service interface. Respective protocol adapter translate these into *machine-readable* runtime representations of CAP queries (→ see [*Core Query Notation, CQN*](/cds/cqn)), which are then forwarded to and processed by target services. Here's an example, including CQL over http: +CAP also uses queries at runtime: an OData or GraphQL request is essentially a query which arrives at a service interface. Respective protocol adapter translate these into *machine-readable* runtime representations of CAP queries (→ see [*Core Query Notation, CQN*](../cds/cqn)), which are then forwarded to and processed by target services. Here's an example, including CQL over http: ::: code-group @@ -579,7 +579,11 @@ This thoroughly agnostic design is the key enabling quality for several of the m -### ⇒ Hexagonal Architecture {#hexagonal} + + +## Hexagonal Architecture + + The *[Hexagonal Architecture](https://alistair.cockburn.us/hexagonal-architecture/)* (aka *Ports and Adapters Architecture/Pattern*) as first proposed by Alistair Cockburn in 2005, is quite famous and fancied these days (rightly so). As Cockburn introduces it, its intent is to: @@ -628,7 +632,7 @@ Let's do a quick time travel by a rough summary of the respective entries in the #### Hexagonal Architecture by CAP -CAP's [agnostic design principles](#agnostic-by-design) are very much in line with the goals of Hexagonal Architecture, and actually give you exactly what these are aiming for: as your applications greatly stay *agnostic* to protocols, and other low-level details, which could lock them in to one specific execution environment, they can be "*developed and tested in isolation*", which in fact is one of CAP's [key guiding principles](#inner-loop) and [value propositions](../about/). Moreover, they become [*resilient* to disrupting changes](../about/best-practices#evolution) in "the outside". +CAP's [agnostic design principles](#agnostic-by-design) are very much in line with the goals of Hexagonal Architecture, and actually give you exactly what these are aiming for: as your applications greatly stay *agnostic* to protocols, and other low-level details, which could lock them in to one specific execution environment, they can be "*developed and tested in isolation*", which in fact is one of CAP's [key value propositions](./index#accelerated-inner-loops). Moreover, they become [*resilient* to disrupting changes](./index#evolution-wo-disruption) in "the outside". Not only do we address the very same goals, we can also identify several symmetries in the way we address and achieve these goals as follows: @@ -646,31 +650,7 @@ Not only do we address the very same goals, we can also identify several symmetr [Also take notice of the *Squared Hexagons* section in the Anti Patterns guide](bad-practices#squared-hexagons) {.learn-more} -### ⇒ Inner Loop Development {#inner-loop} - -The database-agnostic design allows us to use in-memory SQLite or H2 databases at development time, as well as for level 1 functional tests, while using SAP HANA for production. This not only speeds up development turnaround times by magnitudes, it also minimises development costs in a similar scale. - - - -### ⇒ Late-cut Microservices {#late-cut-mss} - -This agnostic design allows [mocking remote services](/guides/using-services#local-mocking), as well as doing late changes to service topologies. For example, you can — and always should — start with co-located services in a single process, while being able to deploy them to separate micro services later on, when you know more about your app and how to scale which parts of it. -::: - - ## Intrinsic Extensibility @@ -745,7 +725,7 @@ In contrast to DDD however, CAP prefers a strong distinction of active services #### CAP promotes CQRS -Similar to CQRS, CAP strongly recommends separating write APIs from read APIs by [defining separate, single-purposed services](/guides/providing-services#single-purposed-services). CDS's reflexive view building eases the task of declaring derived APIs exposing use case-specific de-normalized views on underlying domain models. Service actions in CAP can be used to represent pure commands. There's no restriction to 'verb-only' dogmas in CAP though, as CAP focuses on business applications, which are mostly data-oriented by nature, hence frequently 'entity/noun-centric'. {.indent} +Similar to CQRS, CAP strongly recommends separating write APIs from read APIs by [defining separate, single-purposed services](../guides/providing-services#single-purposed-services). CDS's reflexive view building eases the task of declaring derived APIs exposing use case-specific de-normalized views on underlying domain models. Service actions in CAP can be used to represent pure commands. There's no restriction to 'verb-only' dogmas in CAP though, as CAP focuses on business applications, which are mostly data-oriented by nature, hence frequently 'entity/noun-centric'. {.indent} #### CAP and Event Sourcing @@ -754,12 +734,12 @@ CAP can be combined with event sourcing patterns, that is, by tracking events in #### CAP supports SQL -CDS borrows reflexive view building from SQL to declare derived models and APIs as projections/transformation of underlying models, such as domain models. [CQL](/cds/cql) is based on SQL DML to allow direct mapping to SQL databases. However, it extends SQL with [Associations](/cds/cdl#associations), [Path Expressions](/cds/cql#path-expressions), and [Nested Projections](/cds/cql#nested-expands) to overcome the need to deal with JOINs. Instead, these extensions allow working with data in a structured document-oriented way. {.indent} +CDS borrows reflexive view building from SQL to declare derived models and APIs as projections/transformation of underlying models, such as domain models. [CQL](../cds/cql) is based on SQL DML to allow direct mapping to SQL databases. However, it extends SQL with [Associations](../cds/cdl#associations), [Path Expressions](../cds/cql#path-expressions), and [Nested Projections](../cds/cql#nested-expands) to overcome the need to deal with JOINs. Instead, these extensions allow working with data in a structured document-oriented way. {.indent} #### CAP supports NoSQL -The previously mentioned extensions in [CQL](/cds/cql) feature the modeling of nested document structures as well as view building and querying using navigation instead of cross products, joins, and unions. This actually brings CDS close to the concepts of NoSQL databases, with the data models playing the role of schemas for validation. Although CAP currently doesn't provide out-of-the-box support for concrete NoSQL databases, it's easy to do so in project-specific solutions. {.indent} +The previously mentioned extensions in [CQL](../cds/cql) feature the modeling of nested document structures as well as view building and querying using navigation instead of cross products, joins, and unions. This actually brings CDS close to the concepts of NoSQL databases, with the data models playing the role of schemas for validation. Although CAP currently doesn't provide out-of-the-box support for concrete NoSQL databases, it's easy to do so in project-specific solutions. {.indent} #### CAP and the Relational Model @@ -769,12 +749,12 @@ While CDS extends SQL and the relational model by means to [describe, read, and #### CAP == Entity-Relationship Modeling -CAP employs proven basics of Entity-Relationship Modeling for capturing the conceptual data structures of a given domain. Relationships are modeled as [Associations](/cds/cdl#associations) and [Compositions](/cds/cdl#compositions). {.indent} +CAP employs proven basics of Entity-Relationship Modeling for capturing the conceptual data structures of a given domain. Relationships are modeled as [Associations](../cds/cdl#associations) and [Compositions](../cds/cdl#compositions). {.indent} #### CAP == Aspect-Oriented Programming -[Aspects](/cds/cdl#aspects) in [CDS](/cds/ are borrowed from AOP, especially _Mixins_. With that, CAP greatly facilitates separation of concerns by "...factoring out technical concerns (such as security, transaction management, logging) from a domain model, and as such makes it easier to design and implement domain models that focus purely on the business logic." (source: [Wikipedia](https://en.wikipedia.org/wiki/Domain-driven_design#Relationship_to_other_ideas)) {.indent} +[Aspects](../cds/cdl#aspects) in [CDS](../cds/ are borrowed from AOP, especially _Mixins_. With that, CAP greatly facilitates separation of concerns by "...factoring out technical concerns (such as security, transaction management, logging) from a domain model, and as such makes it easier to design and implement domain models that focus purely on the business logic." (source: [Wikipedia](https://en.wikipedia.org/wiki/Domain-driven_design#Relationship_to_other_ideas)) {.indent} #### CAP == Functional Programming @@ -786,8 +766,8 @@ In addition, CAP features _queries as first-class and higher-order objects_, all #### CAP != Object-Relational Mapping -CAP and CDS aren't _Object-Relational Mapping_ (ORM). Instead, **we prefer querying** using [CQL](/cds/cql) to read and write data, which allows declaratively expressing which data you're interested in by means of projection and selection instead of loading object graphs automatically. Result sets are pure REST data, that are snapshot data representations. One reason for this is the assumption that the lifetime of object cache entries (which are essential for ORMs to perform) is frequently in the range of milliseconds for _REST_ services. {.indent} +CAP and CDS aren't _Object-Relational Mapping_ (ORM). Instead, **we prefer querying** using [CQL](../cds/cql) to read and write data, which allows declaratively expressing which data you're interested in by means of projection and selection instead of loading object graphs automatically. Result sets are pure REST data, that are snapshot data representations. One reason for this is the assumption that the lifetime of object cache entries (which are essential for ORMs to perform) is frequently in the range of milliseconds for _REST_ services. {.indent} #### CAP != Business Objects -Business Object Patterns promote the notion of active objects, which provide instance methods to modify their internal state. In contrast to that, CAP promotes a strict separation of passive data, read and exchanged in RESTful ways, and pure, stateless services, see also the [relationship to Functional Programming](#cap-functional-programming). {.indent} +Business Object Patterns promote the notion of active objects, which provide instance methods to modify their internal state. In contrast to that, CAP promotes a strict separation of passive data, read and exchanged in RESTful ways, and pure, stateless services. {.indent} diff --git a/about/features.md b/about/features.md index 3d2eb2e0b..7b68fe6aa 100644 --- a/about/features.md +++ b/about/features.md @@ -99,20 +99,20 @@ Following is an index of the features currently covered by CAP, with status and ### Providing Services -| Core Framework Features | CDS | Node.js | Java | -|----------------------------------------------------------------------------------------|:-----:|:-------:|:----:| -| [Automatically Serving CRUD Requests](../guides/providing-services#generic-providers) | | | | -| [Deep-Read/Write Structured Documents](../guides/providing-services#deep-reads-writes) | | | | -| [Automatic Input Validation](../guides/providing-services#input-validation) | | | | -| [Auto-filled Primary Keys](../guides/domain-modeling#prefer-uuids-for-keys) | | | | -| [Implicit Paging](../guides/providing-services#implicit-pagination) | | | | -| [Implicit Sorting](../guides/providing-services#implicit-sorting) | | | | -| [Access Control](../guides/security/authorization) | | | | -| [Arrayed Elements](../cds/cdl#arrayed-types) | | | | -| [Streaming & Media Types](../guides/providing-services#serving-media-data) | | | | -| [Conflict Detection through _ETags_](../guides/providing-services#etag) | | | | -| [Authentication via JWT](../guides/security/authorization#prerequisite-authentication) | | | | -| [Basic Authentication](../guides/security/authorization#prerequisite-authentication) | | | | +| Core Framework Features | CDS | Node.js | Java | +|-------------------------------------------------------------------------------------------|:-----:|:-------:|:----:| +| [Automatically Serving CRUD Requests](../guides/providing-services#generic-providers) | | | | +| [Deep-Read/Write Structured Documents](../guides/providing-services#deep-reads-nd-writes) | | | | +| [Automatic Input Validation](../guides/providing-services#input-validation) | | | | +| [Auto-filled Primary Keys](../guides/domain-modeling#prefer-uuids-for-keys) | | | | +| [Implicit Paging](../guides/providing-services#implicit-pagination) | | | | +| [Implicit Sorting](../guides/providing-services#implicit-sorting) | | | | +| [Access Control](../guides/security/authorization) | | | | +| [Arrayed Elements](../cds/cdl#arrayed-types) | | | | +| [Streaming & Media Types](../guides/providing-services#serving-media-data) | | | | +| [Conflict Detection through _ETags_](../guides/providing-services#etag) | | | | +| [Authentication via JWT](../guides/security/authorization#prerequisite-authentication) | | | | +| [Basic Authentication](../guides/security/authorization#prerequisite-authentication) | | | |
diff --git a/about/index.md b/about/index.md index fea245b91..e3a17a7fd 100644 --- a/about/index.md +++ b/about/index.md @@ -12,131 +12,212 @@ Value Propositions {.subtitle} ## What is CAP? -The _Cloud Application Programming Model_ (CAP) is a framework of languages, libraries, and tools for building *enterprise-grade* cloud applications. It guides developers along a *golden path* of proven [best practices](best-practices), served [out-of-the-box](#served-out-of-the-box), and hence greatly reduces boilerplate code and tedious recurring tasks. +The _Cloud Application Programming Model_ (CAP) is a framework of languages, libraries, and tools for building *enterprise-grade* cloud applications. It guides developers along a *golden path* of proven [best practices](best-practices), served [out of the box](#served-out-of-the-box), and hence greatly reduces boilerplate code and tedious recurring tasks. In effect, CAP-based projects benefit from a primary [focus on domain](#focus-on-domain) in close collaboration with domain experts, and from [accelerated development](#grow-as-you-go) at minimised costs. CAP's *agnostic design* shields developers from overly technical disciplines, and fosters evolution w/o disruption in a world of rapidly changing technologies. -## Focus on Domain +## Jumpstart & Grow As You Go... +###### grow-as-you-go -CAP places **primary focus on domain**, by capturing _domain knowledge_ and _intent_ instead of imperative coding — that means, _What, not How_ — which promotes the following: -- Close collaboration of _developers_ and _domain experts_ in domain modeling. -- _Out-of-the-box_ implementations for _best practices_ and recurring tasks. -- _Platform-agnostic_ approach to _avoid lock-ins_, hence _protecting investments_. -## Grow As You Go +### Jumpstarting Projects -Following the principle of **convention over configuration**, there's no need to set up things upfront. CAP allows you to **jumpstart** projects within seconds and have a team starting development right away, using generic providers, on top of a lightweight in-memory database → see [*Getting Started in a Nutshell*](/get-started/in-a-nutshell). +Following the principle of **convention over configuration**, there's no need to set up things upfront. CAP allows you to **jumpstart** projects within seconds and have a team starting development right away, using generic providers, on top of a lightweight in-memory database → see [*Getting Started in a Nutshell*](../get-started/in-a-nutshell). -CAP also offers **mocks for many platform features**, which allow **fast dev-test-run cycles** with minimal development environment complexity — aka *Airplane Mode*. Similarly, CAP facilitates **integration scenarios** by importing an API from, for example, an SAP S/4HANA backend or from SAP Business Accelerator Hub and running mocks for this locally. +### Accelerated Inner Loops -Over time, you **add things gradually**, only when they're needed. For example, you can move ahead to running your apps in close-to-productive setups for integration tests and delivery, without any change in models or code. +CAP offers mocks for many platform features, which allow fast dev-test-run cycles with minimal development environment complexity — aka *Airplane Mode*. + +Similarly, CAP facilitates integration scenarios by importing an API from, for example, an SAP S/4HANA backend or from SAP Business Accelerator Hub and running mocks for this locally. + +### Loose Coupling Finally, projects are encouraged to **parallelize workloads**. For example, following a **contracts-first** approach, a service definition is all that is required to automatically run a full-fledged REST or OData service. So, projects could spawn two teams in parallel: one working on the frontend, while the other one works on the backend part. A third one could start setting up CI/CD and delivery in parallel. +### Minimized Costs + +Over time, you **add things gradually**, only when they're needed. For example, you can move ahead to running your apps in close-to-productive setups for integration tests and delivery, without any change in models or code. + +### Growing as You Go... + + + +### Late-cut Microservices + + +## Proven Best Practices - ## Served Out Of The Box The CAP runtimes in Node.js and Java provide many generic implementations for recurring tasks and best practices, distilled from proven SAP applications. Benefits are significantly **accelerated** development, **minimized boilerplate** code, as well as **increased quality** through single points to fix and optimize, hence **reduced technical debt**. -#### Automatically Serving Requests +### CAP's Generic Service Providers -- [Serving CRUD Requests](/guides/providing-services#generic-providers) -- [Serving Nested Documents](/guides/providing-services#deep-reads-writes) -- [Serving Media Data](/guides/providing-services#serving-media-data) -- [Serving Draft Choreography](/advanced/fiori#draft-support) +- [Serving CRUD Requests](../guides/providing-services#generic-providers) +- [Serving Nested Documents](../guides/providing-services#deep-reads-and-writes) +- [Serving Media Data](../guides/providing-services#serving-media-data) +- [Serving Draft Choreography](../advanced/fiori#draft-support) #### Handling Recurring Tasks -- [Implicit Pagination](/guides/providing-services#implicit-pagination) -- [Input Validation](/guides/providing-services#input-validation) -- [Authentication](/node.js/authentication) -- [Authorization](/guides/security/authorization) -- [Localization / i18n](/guides/i18n) -- [Concurrency Control](/guides/providing-services#concurrency-control) +- [Implicit Pagination](../guides/providing-services#implicit-pagination) +- [Input Validation](../guides/providing-services#input-validation) +- [Authentication](../node.js/authentication) +- [Authorization](../guides/security/authorization) +- [Localization / i18n](../guides/i18n) +- [Concurrency Control](../guides/providing-services#concurrency-control) #### Enterprise Best Practices -- [Common Reuse Types & Aspects](/cds/common) -- [Managed Data](/guides/domain-modeling#managed-data) -- [Localized Data](/guides/localized-data) -- [Temporal Data](/guides/temporal-data) -- [Verticalization & Extensibility](/guides/extensibility/) +- [Common Reuse Types & Aspects](../cds/common) +- [Managed Data](../guides/domain-modeling#managed-data) +- [Localized Data](../guides/localized-data) +- [Temporal Data](../guides/temporal-data) +- [Verticalization & Extensibility](../guides/extensibility/) + +### CAP-level Integrations ('Calesi') -#### Intrinsic Cloud Qualities +- [Open Telemetry → SAP Cloud Logging, Dynatrace, ...](../plugins/#telemetry) +- [Attachments → SAP Object Store](../plugins/#attachments) +- [Attachments → SAP Document Management Service](../plugins/#@cap-js/sdm) +- [Messaging → SAP Cloud Application Event Hub](../plugins/#event-broker-plugin) +- [Change Tracking](../plugins/#change-tracking) +- [Notifications](../plugins/#notifications) +- [Audit Logging](../plugins/#audit-logging) +- [Personal Data Management](../guides/data-privacy/) -- Multitenancy -- Extensibility -- Security -- Scalability -- Resilience +[Find more in the **CAP Plugins** page](../plugins/){.learn-more} -#### **CAP-level Service Integrations ('Calesi')** +[See also the **Features Overview**](./features){.learn-more} -- [Open Telemetry → SAP Cloud Logging, Dynatrace, ...](/plugins/#telemetry) -- [Attachments → SAP Object Store](/plugins/#attachments) -- [Attachments → SAP Document Management Service](/plugins/#@cap-js/sdm) -- [Messaging → SAP Cloud Application Event Hub](/plugins/#event-broker-plugin) -- [Change Tracking](/plugins/#change-tracking) -- [Notifications](/plugins/#notifications) -- [Audit Logging](/plugins/#audit-logging) -- [Personal Data Management](/guides/data-privacy/) -[Find more in the **CAP Plugins** page](/plugins/){.learn-more} +### Intrinsic Extensibility -[See also the **Features Overview**](./features){.learn-more} +SaaS customers, verticalization partners, or your teams can... + +- Add/overide annotations, translations, initial data +- Add extension fields, entities, relationships +- Add custom logic → in-app + side-by-side +- Bundle and share that as reuse extension packages +- Feature-toggle such pre-built extension packages per tenant + +All of that done in the same ways that you can do that in your developments + +- Using the same techniques of CDS Aspects and Event Handlers +- Including adaption ad extensions of reuse types/models +- Including extensions to framework-provided services + +And all of that available out-of-the-box, i.e. without you having to create extension points. You would want to restrict who can extend what, though. - +### Less Code → Less Mistakes -## Open _and_ Opinionated +### Single Points to Fix +### Minimized Lock-Ins -That might sound like a contradiction, but isn't: While CAP certainly gives *opinionated* guidance, we do so without sacrificing openness and flexibility. At the end of the day, you stay in control of which tools or technologies to choose, or which architecture patterns to follow as depicted in the table below. +### Evolution w/o Disruption -| CAP is *Opinionated* in... | CAP is *Open* as... | -| ------------------------------------------------------------ | ------------------------------------------------------------ | -| **Higher-level concepts and APIs** abstracting from and avoiding lock-ins to low-level platform features and protocols | All abstractions follow a glass-box pattern that allows unrestricted access to lower-level things, if required | -| **Best Practices served out of the box** with generic solutions for many recurring tasks | You can always handle things your way in [custom handlers](/guides/providing-services#custom-logic), decide whether to adopt CQRS or Event Sourcing, for example ... while CAP simply tries to get the tedious tasks out of your way. | -| **Out-of-the-box support** for
**[SAP Fiori](https://developers.sap.com/topics/ui-development.html)** and **[SAP HANA](https://developers.sap.com/topics/hana.html)** | You can also choose other UI technologies, like [Vue.js](/get-started/in-a-nutshell#vue), or databases, by providing new database integrations. | -| **Dedicated tools support** provided in [SAP Business Application Studio](/tools/cds-editors#bas) or [Visual Studio Code](/tools/cds-editors#vscode). | CAP doesn't depend on those tools. Everything in CAP can be done using the [`@sap/cds-dk`](/tools/cds-cli) CLI and any editor or IDE of your choice. | - \ No newline at end of file +- AI provides tremendous boosts to productivity → for example: + - **Coding Assicts** → e.g. by [Copilot](https://en.wikipedia.org/wiki/Microsoft_Copilot) in `.cds`, `.js`, even `.md` sources + - **Code Analysis** → detecting [bad practices](bad-practices) → guiding to [best practices](best-practices) + - **Code Generation** → e.g. for tests, test data, ... + - **Project Scaffolding** → for quick head starts + - **Search & Learning Assists** → like Maui, ... +- But doesn't replace the need for **Human Intelligence**! + - There's a different between a GPT-generated one-off thesis and long-lived enterprise software, which needs to adapt and scale to new requirements +- **CAP itself** is a major contribution to AI → its simple, clear concepts, uniform ways to implement and consume services, capire, its openness and visibility in public world, ... + + + +## Caveats + +- diff --git a/advanced/fiori.md b/advanced/fiori.md index cdea58cf5..c9c93fc87 100644 --- a/advanced/fiori.md +++ b/advanced/fiori.md @@ -461,12 +461,12 @@ If you're editing data in multiple languages, the _General_ tab in the example a You can add [custom handlers](../guides/providing-services#custom-logic) to add specific validations, as usual. In addition, for a draft, you can register handlers to the `PATCH` events to validate input per field, during the edit session, as follows. -###### ... in Java +##### ... in Java You can add your validation logic before operation event handlers. Specific events for draft operations exist. See [Java > Fiori Drafts > Editing Drafts](../java/fiori-drafts#draftevents) for more details. -###### ... in Node.js +##### ... in Node.js You can add your validation logic before the operation handler for either CRUD or draft-specific events. See [Node.js > Fiori Support > Handlers Registration](../node.js/fiori#draft-support) for more details about handler registration. diff --git a/advanced/hana.md b/advanced/hana.md index f2b9ea68e..b000cb117 100644 --- a/advanced/hana.md +++ b/advanced/hana.md @@ -20,13 +20,13 @@ You create a new database object or there's an existing object (table, view, tab ### Add Existing SAP HANA Objects from Other HDI Containers -To access database artifacts residing in other HDI containers, you need the permissions granted for that container and you need to introduce them into your own container using synonyms. This synonym establishes a link between both needed HDI containers. The _.hdbsynonym_ file you create for this, [is a native SAP HANA object in your project](#create-native-sap-hana-object). +To access database artifacts residing in other HDI containers, you need the permissions granted for that container and you need to introduce them into your own container using synonyms. This synonym establishes a link between both needed HDI containers. The _.hdbsynonym_ file you create for this, [is a native SAP HANA object in your project](#create-native-sap-hana-objects). ::: tip Synonyms can be used to rename database objects. ::: -### Create Native SAP HANA Object in Your Project { #create-native-sap-hana-object} +### Create Native SAP HANA Objects To create SAP HANA native tables or use SAP HANA native features, use the folder _db/src_ at design time and build, for example, your _.hdbtable_ or _.hdbsynonym_ files. This folder stays untouched during the `cds` build and the content is copied over to the _gen/db/src_ folder during the build. Use this process for all tables and features that can't be modeled using _CDS_. @@ -50,7 +50,7 @@ Steps to match the signature of a database object in a facade entity: * For a view, table function, or calculation view with parameters, check that the parameter names and types match, too. Functions with table-like input parameters are not supported. -> Note: If a field of that entity is defined as `not null` and you want to disable its runtime check, you can add [`@assert.notNull: false`](../guides/providing-services#assert-notNull). This is important if you want to use, for example [SAP HANA history tables](https://help.sap.com/docs/SAP_HANA_PLATFORM/6b94445c94ae495c83a19646e7c3fd56/d0b2c5142a19405fb912f71782cd0a84.html). +> Note: If a field of that entity is defined as `not null` and you want to disable its runtime check, you can add [`@assert.notNull: false`](../guides/providing-services#assert-notnull). This is important if you want to use, for example [SAP HANA history tables](https://help.sap.com/docs/SAP_HANA_PLATFORM/6b94445c94ae495c83a19646e7c3fd56/d0b2c5142a19405fb912f71782cd0a84.html). As a result, the database name is defined by the name of the entity or its elements, after applying the SQL name mapping. @@ -396,7 +396,7 @@ FROM AddressUDF() AS AddressUDF_0; This section describes how associations and compositions to artifacts with `@cds.persistence.skip/exists` are treated during the generation of the database model with `forHana`. -###### `@cds.persistence.skip` +##### `@cds.persistence.skip` Denotes that the artifact isn't available in the database but eventually implemented by custom code. No association can point to a nonexisting database object and no query can be executed against such a nonexisting source. As `@cds.persistence.skip` is *propagated*, projections also don't become part of the database schema. @@ -430,7 +430,7 @@ view ItemSelection as select from Items; The view `Orders` will be rejected with an error message as `items.name` isn't resolvable to a valid JOIN expression and view `ItemSelection` is effectively annotated with `@cds.persistence.skip`. -###### `@cds.persistence.exists` +##### `@cds.persistence.exists` Denotes that there already exists a native database object, which should be used during runtime. diff --git a/advanced/odata.md b/advanced/odata.md index ec2151848..13f1ad0ec 100644 --- a/advanced/odata.md +++ b/advanced/odata.md @@ -336,14 +336,16 @@ Primitive annotation values, meaning Strings, Numbers, `true`, and `false` are m ``` -Rendering a `null` value must be done as dynamic expression or as an [annotation expression](#expression-annotations): +#### Null Value { #null-value } + +A `null` value can be set either as an [annotation expression](#expression-annotations) or as a [dynamic expression](#dynamic-expressions): ```cds -@Some.Null: { $edmJson: { $Null } } -// or -@Some.Null: (null) +@Some.NullXpr: (null) // annotation expression, short form +@Some.NullFunc: ($Null()) // annotation expression, functional form +@Some.NullDyn: { $edmJson: { $Null } } // dynamic expression ``` -Both result in the following: +All three expressions result in the following rendering: ```xml @@ -662,7 +664,8 @@ The following operators and clauses of CDL are supported: * Logical: `and`, `or`, `not` * Relational: `=`, `<>`, `!=`, `<`, `<=`, `>`, `>=`, `in`, `between ... and ...` * Unary `+` and `-` -* Arithmetic: `+`, `-`, `*`, `/`, `||` +* Arithmetic: `+`, `-`, `*`, `/` +* Concat: `||` * `cast(...)` Example: @@ -718,7 +721,7 @@ service S { In addition, the following functions are supported: -* `$Null()` representing the `null` value +* `$Null()` representing the `null` value [`Null`]([annotation expression](#null-value)). * `Div(...)` (or `$Div(...)`) and `Mod(...)` (or `$Mod(...)`) for integer division and modulo * [`Has(...)`](https://docs.oasis-open.org/odata/odata/v4.02/csd01/part2-url-conventions/odata-v4.02-csd01-part2-url-conventions.html#Has) (or `$Has(...)`) * the functions listed in sections diff --git a/cds/annotations.md b/cds/annotations.md index 68a35a0f8..88e837ee9 100644 --- a/cds/annotations.md +++ b/cds/annotations.md @@ -40,12 +40,12 @@ uacp: Used as link target from Help Portal at https://help.sap.com/products/BTP/ |---------------------|----------------------------------------------------------------------| | `@readonly ` | see [Input Validation](../guides/providing-services#readonly) | | `@mandatory` | see [Input Validation](../guides/providing-services#mandatory) | -| `@assert.unique` | see [Input Validation](../guides/providing-services#unique) | -| `@assert.integrity` | see [Input Validation](../guides/databases#db-constraints) | +| `@assert.unique` | see [Input Validation](../guides/providing-services#assert-unique) | +| `@assert.integrity` | see [Input Validation](../guides/databases#database-constraints) | | `@assert.target` | see [Input Validation](../guides/providing-services#assert-target) | | `@assert.format` | see [Input Validation](../guides/providing-services#assert-format) | | `@assert.range` | see [Input Validation](../guides/providing-services#assert-range) | -| `@assert.notNull` | see [Input Validation](../guides/providing-services#assert-notNull) | +| `@assert.notNull` | see [Input Validation](../guides/providing-services#assert-notnull) | diff --git a/cds/cdl.md b/cds/cdl.md index 6f74e7d8e..a404526f2 100644 --- a/cds/cdl.md +++ b/cds/cdl.md @@ -32,8 +32,8 @@ The *Conceptual Definition Language (CDL)* is a human-readable language for defi - [Keywords & Identifiers](#keywords-identifiers) - [Built-in Types](#built-in-types) - [Literals](#literals) -- [Model Imports](#imports) -- [Namespaces](#namespace) +- [Model Imports](#model-imports) +- [Namespaces](#namespaces) - [Comments](#comments) @@ -146,7 +146,7 @@ Within those strings, escape sequences from JavaScript, such as `\t` or `\u0020` -### Model Imports {#imports} +### Model Imports @@ -208,7 +208,7 @@ To allow for loading from precompiled _.json_ files it's recommended to **omit _ ### Namespaces -#### The `namespace` Directive {#namespace} +#### The `namespace` Directive To prefix the names of all subsequent definitions, place a `namespace` directive at the top of a model. This is comparable to other languages, like Java. @@ -348,21 +348,24 @@ In CAP Java, doc comments are automatically enabled by the [CDS Maven Plugin](.. ## Entities & Type Definitions -- [Entity Definitions](#entities) -- [Type Definitions](#types) +- [Entity Definitions](#entity-definitions) +- [Type Definitions](#type-definitions) - [Structured Types](#structured-types) - [Arrayed Types](#arrayed-types) - [Virtual Elements](#virtual-elements) - [Calculated elements](#calculated-elements) - [Default Values](#default-values) -- [Type References](#typereferences) +- [Type References](#type-references) - [Constraints](#constraints) - [Enums](#enums) -### Entity Definitions {#entities} + +### Entity Definitions +{#entities} + Entities are structured types with named and typed elements, representing sets of (persisted) data that can be read and manipulated using usual CRUD operations. They usually contain one or more designated primary key elements: @@ -379,7 +382,9 @@ define entity Employees { > The `define` keyword is optional, that means `define entity Foo` is equal to `entity Foo`. -### Type Definitions {#types} +### Type Definitions +{#types} + You can declare custom types to reuse later on, for example, for elements in entity definitions. Custom-defined types can be simple, that is derived from one of the predefined types, structure types or [Associations](#associations). @@ -486,7 +491,8 @@ entity Employees { -### Calculated Elements {#calculated-elements} + +### Calculated Elements Elements of entities and aspects can be specified with a calculation expression, in which you can refer to other elements of the same entity/aspect. @@ -625,7 +631,7 @@ type Complex { ``` -### Type References {#typereferences} +### Type References If you want to base an element's type on another element of the same structure, you can use the `type of` operator. @@ -869,7 +875,7 @@ This example is equivalent to the [unmanaged example above](#unmanaged-associati key element `address_ID` being added automatically upon activation to a SQL database. The names of the automatically added foreign key elements cannot be changed. -> Note: For adding foreign key constraints on database level, see [Database Constraints.](../guides/databases#db-constraints). +> Note: For adding foreign key constraints on database level, see [Database Constraints.](../guides/databases#database-constraints). If the target has a single primary key, a default value can be provided. This default applies to the generated foreign key element `address_ID`: @@ -1670,7 +1676,7 @@ the `extend` from `c.cds` is applied, as it is the last in the dependency chain. ### The `annotate` Directive {#annotate} -The `annotate` directive allows to annotate already existing definitions that may have been [imported](#imports) from other files or projects. +The `annotate` directive allows to annotate already existing definitions that may have been [imported](#model-imports) from other files or projects. ```cds annotate Foo with @title:'Foo'; @@ -1880,7 +1886,8 @@ entity C { /*...*/ }; ::: -### (Auto-) Redirected Associations {#auto-redirect} +### (Auto-) Redirected Associations +{#auto-redirect} When exposing related entities, associations are automatically redirected. This ensures that clients can navigate between projected entities as expected. For example: @@ -1938,7 +1945,8 @@ service AdminService { -### Auto-Exposed Entities {#auto-expose} +### Auto-Exposed Entities +{#auto-expose} Annotate entities with `@cds.autoexpose` to automatically expose them in services containing entities with associations referring to them. diff --git a/cds/cql.md b/cds/cql.md index dd57db843..22c941803 100644 --- a/cds/cql.md +++ b/cds/cql.md @@ -14,7 +14,9 @@ CDS Query Language (CQL) is based on standard SQL, which it enhances by... [[toc]] -## Postfix Projections {#postfix-projections} + +## Postfix Projections +{#postfix-projections} CQL allows to put projections, that means, the `SELECT` clause, behind the `FROM` clause enclosed in curly braces. For example, the following are equivalent: @@ -25,7 +27,8 @@ SELECT name, address.street from Authors SELECT from Authors { name, address.street } ``` -### Nested Expands {#nested-expands} +### Nested Expands +{#nested-expands} Postfix projections can be appended to any column referring to a struct element or an association and hence be nested. This allows **expand** results along associations and hence read deeply structured documents: diff --git a/cds/csn.md b/cds/csn.md index 5f12ce5d6..039fb6e6e 100644 --- a/cds/csn.md +++ b/cds/csn.md @@ -189,7 +189,7 @@ Foo2 = { type:"cds.String", kind:"type" } ``` -## Type Definitions {#type-definitions} +## Type Definitions [type definitions]: #type-definitions @@ -216,8 +216,6 @@ Custom-defined types are entries in [`definitions`](#definitions) with an option #### Properties -[kind]: #kind -[type]: #type * `kind` – omitted or _`"type"`_ * `type` – the base type, this definition is derived from @@ -233,7 +231,6 @@ Custom-defined types are entries in [`definitions`](#definitions) with an option ### Scalar Types -[scalar]: #scalar-types Scalar types always have property `type` specified, plus optional type-specific parameter properties. @@ -432,9 +429,8 @@ Use the `projection` property for views if you don't need the full power of SQL. ## Associations -[Associations]: #associations -Associations are like [scalar type definitions][scalar] with `type` being `cds.Association` or `cds.Composition` plus additional properties specifying the association's `target` and optional information like `on` conditions or foreign `keys`. +Associations are like [scalar type definitions](#scalar-types) with `type` being `cds.Association` or `cds.Composition` plus additional properties specifying the association's `target` and optional information like `on` conditions or foreign `keys`. ### Basic to-one Associations diff --git a/cds/cxn.md b/cds/cxn.md index d27818cdf..15c8c7503 100644 --- a/cds/cxn.md +++ b/cds/cxn.md @@ -9,10 +9,6 @@ uacp: Used as link target from Help Portal at https://help.sap.com/products/BTP/ # Expression Notation (CXN) { #expressions} -[expression]: #expressions -[expr]: #expressions -[CQN]: ./cqn - Expressions in CDS definitions and queries can be one of: @@ -33,7 +29,6 @@ expr = // one of... ## Literal Values -[val]: #literal-values Literal values are represented as `{val:...}` with property `val` holding the actual literal value as specified in JSON. @@ -56,7 +51,6 @@ cds.parse.expr(`timestamp'2023-04-15T13:05:23Z'`) == {val: '2023-04-15T13:05:23 ## References -[ref]: #references A reference is represented as `{ ref: … }` with property `ref`. This property holds an array of reference segments as plain identifier strings. Only in case of infix filters and/or arguments, the property holds an object `{ id: 'identifier', … }` and all properties except `id` are optional, as shown in the following snippet: @@ -85,7 +79,6 @@ cqn4(`foo[where a=1 group by b having b>2 order by c limit 7].bar`) ## Function Calls -[func]: #functions Function calls are represented as follows: @@ -116,8 +109,6 @@ cqn4(`new ST_Point(2, 3)`) ## Lists { #lists} -[list]: #lists - Lists or tupels are represented as `{list:...}`, with property `list` holding an array of the list entries. Examples: @@ -129,8 +120,6 @@ cds.parse.expr(`(foo, bar)`) == {list: [{ref: ['foo']}, {ref: ['bar']}]} ## Operator Expressions { #operators} -[xpr]: #operators -[_xpr]: #operators Operators join one or more expressions into complex ones, represented as `{xpr:...}`. The property `xpr` holds a sequence of operators and operands. @@ -141,7 +130,7 @@ _operand = expr _operator = string ``` -* *Operands* can be any kind of [expression] +* *Operands* can be any kind of expression * *Operators* are represented as plain strings, like `'='` or `'and'` * Parentheses `( ... )` around sub-expressions are represented as nested `xpr` @@ -179,7 +168,6 @@ cds.parse.expr(`x<10 ? y : z`) ==//> returns: ## Binding Parameters -[param]: #parameters Binding parameters for prepared statements are represented as `{ref:..., param:true}` with values for `ref` as follows. @@ -196,4 +184,4 @@ cds.parse.expr(`x=?`) == [{ref:['x']}, '=', {ref:['?'], param:true}] ## Sub Queries -[See CQN][CQN]{.learn-more} +[See CQN](cqn){.learn-more} diff --git a/get-started/troubleshooting.md b/get-started/troubleshooting.md index 7f3c8c884..9fceb5a02 100644 --- a/get-started/troubleshooting.md +++ b/get-started/troubleshooting.md @@ -15,7 +15,7 @@ uacp: This page is linked from the Help Portal at https://help.sap.com/products/ ## Setup {#setup} -### Can't start VSCode from Command Line on macOS {#vscode-macos} +### Can't start VS Code from Command Line on macOS {#vscode-macos} In order to start VS Code via the `code` CLI, users on macOS must first run a command (*Shell Command: Install 'code' command in PATH*) to add the VS Code executable to the `PATH` environment variable. Read VS Code's [macOS setup guide](https://code.visualstudio.com/docs/setup/mac) for help. @@ -284,8 +284,8 @@ The project skeleton generated by the CAP Java archetype adds the relevant Sprin However, using an SQL database in CAP Java is fully optional. You can also develop CAP applications that don't use persistence at all. To remove the SQL database support, you need to exclude the JDBC-related dependencies of Spring Boot and CAP Java. This means that CAP Java won't create a Persistence Service instance. -::: tip -Keep in mind, that the default event handlers of Application Services delegate to the Persistence Service. You need to implement your own custom handlers in case you remove the SQL database support. +::: tip Default Application Service event handlers delegate to Persistence Service +You need to implement your own custom handlers in case you remove the SQL database support. ::: You can exclude those dependencies from the `cds-starter-spring-boot` dependency in the `srv/pom.xml`: @@ -378,7 +378,7 @@ In case you want a visual interface tool to work with SQLite, you can use [SQLTo To configure this service in the SAP BPT cockpit on trial, refer to the [SAP HANA Cloud Onboarding Guide](https://www.sap.com/documents/2021/09/7476f8c4-f77d-0010-bca6-c68f7e60039b.html). See [SAP HANA Cloud](https://help.sap.com/docs/HANA_CLOUD) documentation or visit the [SAP HANA Cloud community](https://pages.community.sap.com/topics/hana/cloud) for more details. -::: tip +::: warning HANA needs to be restarted on trial accounts On trial, your SAP HANA Cloud instance will be automatically stopped overnight, according to the server region time zone. That means you need to restart your instance every day before you start working with your trial. ::: @@ -393,7 +393,7 @@ On trial, your SAP HANA Cloud instance will be automatically stopped overnight, | _Solution_ | Add an _undeploy.json_ file to the root of your database module (the _db_ folder by default). This file defines the files **and data** to be deleted. See section [HDI Delta Deployment and Undeploy Allow List](https://help.sap.com/docs/HANA_CLOUD_DATABASE/c2b99f19e9264c4d9ae9221b22f6f589/ebb0a1d1d41e4ab0a06ea951717e7d3d.html) for more details. ::: tip -If you want to keep the data from _.csv_ files and data you've already added, see [SAP Note 2922271](https://launchpad.support.sap.com/#/notes/2922271) for more details. +If you want to keep the data from _.csv_ files and data you've already added, see [SAP Note 2922271](https://me.sap.com/notes/2922271) for more details. ::: You can apply this solution also when using the `cds-mtxs` library. You can either set the options via the environment variable [`HDI_DEPLOY_OPTIONS`](https://help.sap.com/docs/SAP_HANA_PLATFORM/4505d0bdaf4948449b7f7379d24d0f0d/a4bbc2dd8a20442387dc7b706e8d3070.html), the CDS configuration or you can add them to the model update request as `hdi` parameter: @@ -434,13 +434,6 @@ Options in [Saas Provisioning Service upgrade API](../guides/multitenancy/mtxs#e } ``` -### How Do I Resolve Service Creation Errors? - -- If there's more than one SAP HANA database mapped to your Cloud Foundry space, service creation fails. In this case, you need to specify the database: `cf create-service [...] -c "{\"database_id\":\"XXX\" }"` where `XXX` is the ID of the database instance. -- On trial landscapes, you need to use `hanatrial` instead of `hana` as service type: `cf create-service hanatrial [...]` -- When using the `cds-mtx` library with more than one SAP HANA database mapped to your Cloud Foundry space, you can add the service creation parameters via the environment variable `CDS_MTX_PROVISIONING_CONTAINER="{\"provisioning_parameters\":{\"database_id\":\"XXX\"}}"`, where `XXX` represents the ID of the database instance. You can also pass the ID of the database with the subscription request. - - ### How Do I Resolve Deployment Errors? #### Deployment fails — _Cyclic dependencies found_ or _Cycle between files_ @@ -545,60 +538,6 @@ Please check the [configuration for extensibility](../guides/extensibility/custo If data loss is intended, you can disable the check by adding cds.requires.cds.xt.DeploymentService.upgrade.skipExtensionCheck = true to the configuration. ::: -## MTX (legacy) - -This refers to potential problems with the **deprecated** [@sap/cds-mtx](../guides/multitenancy/old-mtx-apis) package. - -### How do I set up MTX with App Router? { #mtx-as-sidecar-with-approuter} - -See [Deploy to Cloud Foundry](../guides/deployment/to-cf) for the basic project and deployment setup. - -### I get a 401 error when logging in to MTX through App Router { #mtx-sidecar-approuter-401} - -See [App Router configuration](../guides/multitenancy/old-mtx-apis#approuter-config) to ensure a correct handling of authentication by both `@sap/approuter` and `@sap/cds-mtx`. - -When logging in, remember to specify the same subdomain you used to get a passcode. Normally this will be the subdomain of the customer subaccount: - -```sh -cds login … -s -``` - -Alternatively, without login: - -```sh -cds extend … -s -``` - -### I get errors with response code 429 from the service-manager service when subscribing a tenant - -You can reduce the number of request by adapting the configuration of the `@sap/instance-manager` library. See also [`@sap/instance-manager` documentation](https://www.npmjs.com/package/@sap/instance-manager). - ```json - "cds": { - "mtx": { - "provisioning": { - "instancemanageroptions": { - "polling_interval_millis": 3000 - } - } - } - } - ``` - -### I get errors with response code 429 from the service-manager service when running a tenant upgrade for all tenants - -You can disable the database clustering for the update. - ```json - "cds": { - "mtx": { - "jobs": { - "clusterbydb": false - } - } - } - ``` -This setting requires at least `@sap/cds-mtx@2.6.2`. - - ## MTA { #mta} ### Why Does My MTA Build Fail? diff --git a/guides/databases.md b/guides/databases.md index 685a1f589..31e1514f7 100644 --- a/guides/databases.md +++ b/guides/databases.md @@ -807,7 +807,7 @@ Find here a collection of resources on selected databases and their reference do -## Database Constraints {#db-constraints} +## Database Constraints The information about foreign key relations contained in the associations of CDS models can be used to generate foreign key constraints on the database tables. Within CAP, referential consistency is established only at commit. The ["deferred" concept for foreign key constraints](https://www.sqlite.org/foreignkeys.html) in SQL databases allows the constraints to be checked and enforced at the time of the [COMMIT statement within a transaction](https://www.sqlite.org/lang_transaction.html) rather than immediately when the data is modified, providing more flexibility in maintaining data integrity. diff --git a/guides/providing-services.md b/guides/providing-services.md index 6177e51cf..69d08b0a3 100644 --- a/guides/providing-services.md +++ b/guides/providing-services.md @@ -15,7 +15,8 @@ uacp: Used as link target from Help Portal at https://help.sap.com/products/BTP/ [[toc]] -## Intro: Core Concepts {#introduction} +## Intro: Core Concepts +{#introduction} The following sections give a brief overview of CAP's core concepts. @@ -160,7 +161,8 @@ The CAP runtimes for [Node.js](../node.js/) and [Java](../java/) provide a wealt In effect, a service definition [as introduced above](#service-definitions) is all we need to run a full-fledged server out of the box. The need for coding reduces to real custom logic specific to a project's domain → section [Custom Logic](#custom-logic) picks that up. -### Serving CRUD Requests {#serving-crud} +### Serving CRUD Requests +{#serving-crud} The CAP runtimes for [Node.js](../node.js/) and [Java](../java/) provide generic handlers, which automatically serve all CRUD requests to entities for CDS-modelled services on top of a default [primary database](databases). @@ -180,7 +182,7 @@ filtering and sorting is not available for `virtual` elements. ::: -### Deep Reads / Writes +### Deep Reads and Writes CDS and the runtimes have advanced support for modeling and serving document-oriented data. The runtimes provide generic handlers for serving deeply nested document structures out of the box as documented in here. @@ -728,7 +730,7 @@ Pessimistic locking is not supported by SQLite. H2 supports exclusive locks only CAP runtimes automatically validate user input, controlled by the following annotations. -### `@readonly` {#readonly} +### `@readonly` Elements annotated with `@readonly`, as well as [_calculated elements_](../cds/cdl#calculated-elements), are protected against write operations. That is, if a CREATE or UPDATE operation specifies values for such fields, these values are **silently ignored**. @@ -738,7 +740,7 @@ The same applies for fields with the [OData Annotations](../advanced/odata#annot ::: -### `@mandatory` {#mandatory} +### `@mandatory` Elements marked with `@mandatory` are checked for nonempty input: `null` and (trimmed) empty strings are rejected. @@ -761,7 +763,7 @@ In addition to server-side input validation as introduced above, this adds a cor -### `@assert.unique` {#unique} +### `@assert .unique` Annotate an entity with `@assert.unique.`, specifying one or more element combinations to enforce uniqueness checks on all CREATE and UPDATE operations. For example: @@ -790,7 +792,7 @@ You don't need to specify `@assert.unique` constraints for the primary key eleme -### `@assert.target` {#assert-target} +### `@assert .target` Annotate a [managed to-one association](../cds/cdl#managed-associations) of a CDS model entity definition with the `@assert.target` annotation to check whether the target entity referenced by the association (the reference's target) @@ -806,14 +808,14 @@ supported, in this case, you will get an error. The `@assert.target` check constraint is meant to **validate user input** and not to ensure referential integrity. Therefore only `CREATE`, and `UPDATE` events are supported (`DELETE` events are not supported). To ensure that every non-null foreign key in a table has a corresponding primary key in the associated/referenced target table -(ensure referential integrity), the [`@assert.integrity`](databases#db-constraints) constraint must be used instead. +(ensure referential integrity), the [`@assert.integrity`](databases#database-constraints) constraint must be used instead. If the reference's target doesn't exist, an HTTP response (error message) is provided to HTTP client applications and logged to stdout in debug mode. The HTTP response body's content adheres to the standard OData specification for an error [response body](https://docs.oasis-open.org/odata/odata-json-format/v4.01/cs01/odata-json-format-v4.01-cs01.html#sec_ErrorResponse). -#### Example {#assert-target-example} +#### Example Add `@assert.target` annotation to the service definition as previously mentioned: @@ -867,7 +869,7 @@ Cross-service checks are not supported. It is expected that the associated entit The `@assert.target` check constraint relies on database locks to ensure accurate results in concurrent scenarios. However, locking is a database-specific feature, and some databases don't permit to lock certain kinds of objects. On SAP HANA, for example, views with joins or unions can't be locked. Do not use `@assert.target` on such artifacts/entities. ::: -### `@assert.format` {#assert-format} +### `@assert .format` Allows you to specify a regular expression string (in ECMA 262 format in CAP Node.js and java.util.regex.Pattern format in CAP Java) that all string input must match. @@ -877,7 +879,7 @@ entity Foo { } ``` -### `@assert.range` {#assert-range} +### `@assert .range` Allows you to specify `[ min, max ]` ranges for elements with ordinal types — that is, numeric or date/time types. For `enum` elements, `true` can be specified to restrict all input to the defined enum values. @@ -914,8 +916,7 @@ Support for open intervals and infinity has been added to CAP Node.js, i.e. `@sa ::: - -### `@assert.notNull` {#assert-notNull} +### `@assert .notNull` Annotate a property with `@assert.notNull: false` to have it ignored during the generic not null check, for example if your persistence fills it automatically. @@ -1339,7 +1340,8 @@ To disable this default behavior, you can set the environment variable c -## Single-Purposed Services {.best-practice} +## Single-Purposed Services +{.best-practice} We strongly recommend designing your services for single use cases. diff --git a/guides/using-services.md b/guides/using-services.md index 399e8fa7a..69d775245 100644 --- a/guides/using-services.md +++ b/guides/using-services.md @@ -234,7 +234,7 @@ To work with remote services, add the following dependency to your Maven project -## Local Mocking {#local-mocking} +## Local Mocking When developing your application, you can mock the remote service. diff --git a/java/change-tracking.md b/java/change-tracking.md index 596810f74..e31edcf89 100644 --- a/java/change-tracking.md +++ b/java/change-tracking.md @@ -276,7 +276,7 @@ If you change the values of the `OrderItems` entity directly via an OData reques ## Reacting on Changes -You can write an event handler to observe the change log entries. Keep in mind, that the change log entries +You can write an event handler to observe the change log entries. Keep in mind, that the change log entries are created for each statement and this event will not be bound to any kind of transaction or a batch operation. ```java @@ -285,7 +285,7 @@ import cds.gen.sap.changelog.Changes; @Component @ServiceName("ChangeTrackingService$Default") public class ChangeTrackingHandler implements EventHandler { - + @After(event = "createChanges") void afterCreate(EventContext context) { Result result = (Result) context.get("result"); diff --git a/java/cqn-services/persistence-services.md b/java/cqn-services/persistence-services.md index 7efa46778..1205d9c22 100644 --- a/java/cqn-services/persistence-services.md +++ b/java/cqn-services/persistence-services.md @@ -150,7 +150,7 @@ cds.sql.hana.optimizationMode: legacy Use the [hints](../working-with-cql/query-execution#hana-hints) `hdb.USE_HEX_PLAN` and `hdb.NO_USE_HEX_PLAN` to overrule the configured optimization mode per statement. ::: warning Rare error in `HEX` mode -In some corner cases, particularly when using [native HANA views](../../advanced/hana#create-native-sap-hana-object), queries in `HEX` optimization mode may fail with a "hex enforced but cannot be selected" error. This is the case if the statement execution requires the combination of HEX only features with other features that are not yet supported by the HEX engine. If CAP detects this error it will, as a fallback, execute the query in _legacy_ mode. +In some corner cases, particularly when using [native HANA views](../../advanced/hana#create-native-sap-hana-objects), queries in `HEX` optimization mode may fail with a "hex enforced but cannot be selected" error. This is the case if the statement execution requires the combination of HEX only features with other features that are not yet supported by the HEX engine. If CAP detects this error it will, as a fallback, execute the query in _legacy_ mode. If you know upfront that a query can't be executed by the HEX engine, you can add a `hdb.NO_USE_HEX_PLAN` hint to the query, so the SQL generator won't use features that require the HEX engine. ::: @@ -547,7 +547,7 @@ cds: ### Native SQL with JDBC Templates { #jdbctemplate} -The JDBC template is the Spring API, which in contrast to the CQN APIs allows executing native SQL statements and call stored procedures (alternative to [Native HANA Object](../../advanced/hana#create-native-sap-hana-object)). It seamlessly integrates with Spring's transaction and connection management. The following example shows the usage of `JdbcTemplate` in the custom handler of a Spring Boot enabled application. It demonstrates the execution of the stored procedure and native SQL statement. +The JDBC template is the Spring API, which in contrast to the CQN APIs allows executing native SQL statements and call stored procedures (alternative to [Native HANA Object](../../advanced/hana#create-native-sap-hana-objects)). It seamlessly integrates with Spring's transaction and connection management. The following example shows the usage of `JdbcTemplate` in the custom handler of a Spring Boot enabled application. It demonstrates the execution of the stored procedure and native SQL statement. ```java @Autowired diff --git a/java/developing-applications/building.md b/java/developing-applications/building.md index 7d963c3a2..c3131f6c5 100644 --- a/java/developing-applications/building.md +++ b/java/developing-applications/building.md @@ -17,7 +17,8 @@ One of the key [CAP design principles](../../about/#open-and-opinionated) is to Giving a clear guidance for cutting-edge technologies on the one hand and still keeping the door wide open for custom choice on the other hand, demands a highly flexible CAP Java runtime stack. The [modular architecture](#modular_architecture) reflects this requirement, allowing a fine-grained and flexible [configuration](#stack_configuration) based on standard or custom modules. -## Modular Stack Architecture { #modular_architecture} +## Modular Stack Architecture +{ #modular_architecture} ### Overview @@ -56,7 +57,7 @@ You can recognize five different areas of the stack, which comprise components a * [Application features](#application-features) are optional application extensions, for instance to add multitenancy capabilities or a platform service integration. -### Application Framework { #application-framework} +### Application Framework Before starting the development of a new CAP-based application, an appropriate application framework to build on needs to be chosen. The architecture of the chosen framework not only has a strong impact on the structure of your project, but it also affects efforts for maintenance as well as support capabilities. @@ -75,7 +76,7 @@ In this case, a solution based on plain Java Servlets could be favorable. Lastly, in case you want to run your application on a 3rd party application framework, you're free to bundle it with CAP modules and provide the glue code, which is necessary for integration. -### Protocol Adapters { #protocol-adapters} +### Protocol Adapters The CAP runtime is based on an [event](../../about/best-practices#events) driven approach. @@ -339,7 +340,8 @@ It supports the following command-line options: | `-DcdsdkVersion=` | Sets the provided cds-dk version in the project. If not specified, the default of CAP Java is used. | -## Building Projects with Maven { #maven-build-options } +## Building Projects with Maven +{ #maven-build-options } You can build and run your application by means of the following Maven command: @@ -348,7 +350,7 @@ mvn spring-boot:run ``` -### CDS Maven Plugin { #cds-maven-plugin} +### CDS Maven Plugin CDS Maven plugin provides several goals to perform CDS-related build steps. For instance, the CDS model needs to be compiled to a CSN file which requires a Node.js runtime with module `@sap/cds-dk`. diff --git a/java/working-with-cql/query-api.md b/java/working-with-cql/query-api.md index 1768f570d..2bed83504 100644 --- a/java/working-with-cql/query-api.md +++ b/java/working-with-cql/query-api.md @@ -534,7 +534,7 @@ Object authorId = book.get("author.Id"); // path access ``` ::: tip -Only to-one associations that are mapped via the primary key elements of the target entity are supported on the select list. The execution is optimized and gives no guarantee that the target entity exists, if this is required use expand or enable [integrity constraints](../../guides/databases#db-constraints) on the database. +Only to-one associations that are mapped via the primary key elements of the target entity are supported on the select list. The execution is optimized and gives no guarantee that the target entity exists, if this is required use expand or enable [integrity constraints](../../guides/databases#database-constraints) on the database. ::: diff --git a/java/working-with-cql/query-execution.md b/java/working-with-cql/query-execution.md index 099dc7863..37142d96d 100644 --- a/java/working-with-cql/query-execution.md +++ b/java/working-with-cql/query-execution.md @@ -194,7 +194,7 @@ For inactive draft entities `@cascade` annotations are ignored. ::: ::: warning _❗ Warning_ -The @cascade annotation is not respected by foreign key constraints on the database. To avoid unexpected behaviour you might have to disable a FK constraint with [`@assert.integrity:false`](../../guides/databases#db-constraints). +The @cascade annotation is not respected by foreign key constraints on the database. To avoid unexpected behaviour you might have to disable a FK constraint with [`@assert.integrity:false`](../../guides/databases#database-constraints). ::: #### Deep Insert / Upsert { #deep-insert-upsert} diff --git a/links.md b/links.md deleted file mode 100644 index ae12e91a5..000000000 --- a/links.md +++ /dev/null @@ -1,34 +0,0 @@ - - - -[PostgreSQL]: /guides/databases-postgres -[SAP HANA]: /guides/databases-hana -[SQLite]: /guides/databases-sqlite -[H2]: /guides/databases-h2 - -[Getting Started]: /get-started/ -[Cookbook]: /guides/ -[Advanced]: /guides/ -[Node.js runtime]: /node.js/ -[Java runtime]: /java/ -[CAP Plugins]: /plugins/ -[Plugins]: /plugins/ -[Tools]: /tools/ - -[CDS]: /cds/ -[CDL]: /cds/cdl -[CSN]: /cds/csn -[CQL]: /cds/cql -[CQN]: /cds/cqn - -[cap/samples]: https://github.com/sap-samples/cloud-cap-samples -[cap/sflight]: https://github.com/sap-samples/cap-sflight - -[bookshop]: /get-started/in-a-nutshell - -[Node.js]: https://nodejs.org/ -[Java]: https://www.oracle.com/java/ -[GraphQL]: https://graphql.org/ -[OData]: https://www.odata.org/ -[REST]: https://restfulapi.net/ -[SQL]: https://en.wikipedia.org/wiki/SQL \ No newline at end of file diff --git a/node.js/cds-connect.md b/node.js/cds-connect.md index c8dedd993..e1c3062e9 100644 --- a/node.js/cds-connect.md +++ b/node.js/cds-connect.md @@ -637,7 +637,7 @@ One prominent exception of that, which you would frequently add to your _package "[development]": { "kind": "sqlite", "credentials": { - "database": "db/bookshop.db" + "url": "db/bookshop.sqlite" } } } @@ -694,7 +694,7 @@ The latter is appropriate in test suites. In productive code, you never provide }, "db": { "credentials": { - "database": "sqlite.db" + "url": "db.sqlite" } } } diff --git a/node.js/cds-env.md b/node.js/cds-env.md index c17c66bcd..965802780 100644 --- a/node.js/cds-env.md +++ b/node.js/cds-env.md @@ -105,7 +105,7 @@ For example, given the following sources: "db": { "kind": "sql", "model": "./db", - "credentials": { "database": ":memory:" } + "credentials": { "url": ":memory:" } } } }