Ever found yourself writing repetitive validation handlers or debugging complex imperative code? Declarative programming in SAP Cloud Application Programming Model (CAP) offers a better way. Declarative programming means describing what you want to achieve rather than how to achieve it. Instead of writing step-by-step instructions, you express the problem itself and let the system determine the solution automatically.
There are a couple of benefits using a declarative approach:
In CAP, developers can declaratively define numerous CAP features - including queries and view definitions, input validations or annotation based constraints. The result? Less imperative code, consistent validations between backend and OData annotations, and logic that is intuitive to understand. This post walks you through the core concepts of declarative programming in CAP, covering declarative expressions, different kinds of input validations, how to use expressions as annotation values and the new @assert feature. These techniques work in both CAP Java and CAP Node.js.
With CAP, you can use declarative expressions in queries, view definitions, and calculated elements by defining them directly in your model. For example, you can use the exists predicate to select only those authors whose associated books contain elements with a price greater than 20:
Select from Authors { name } where exists books[price > 20.00]In another example, you can use declarative expressions to compute free seats on a flight:
entity Flights : cuid {
...
max_seats : Integer;
occupied_seats : Integer;
free_seats : Integer = max_seats - occupied_seats;
}In all cases you can reduce the need for imperative code by using declarative expressions.
Please read our documentation for further information about views and projections and calculated elements.
Instead of writing custom event handlers for every validation, CAP provides several built-in annotations that handle common scenarios declaratively. These validations are executed at the database layer, reducing round trips and enabling efficient error aggregation:
In the following example, you check that a description has a minimum length of 3 characters:
Description @assert.format: '.{3,}' @assert.format.message: 'Description too short’In CAP, Core Data Services (CDS) is used to define service definitions, data models, queries, and expressions. Using declarative annotations in CDS models reduces custom logic while keeping validations consistent across services and UI.
Learn more about event handlers in CAP Java and events in CAP Node.js , read our documentation on declarative constraints and check out DJ Adams’ blog post Constraints, expressions and axioms in action.
Annotations can use CXL (CDS Expression Language) expressions as values. This is particularly useful for instance-based authorizations. The following code snippet ensures that users can only read, update, or delete orders they created:
annotate Orders with @(restrict: [
{ grant: ['READ', 'UPDATE', 'DELETE'], where: (createdBy = $user) }
]);Using parentheses ensures that the CDS compiler can validate and optimize the expression.
You can also use dynamic expressions in UI annotations. The compiler translates these expressions automatically to the corresponding OData annotations:
@UI.Hidden: (status <> 'visible')Learn more about expressions as annotation values.
If you are interested to learn more about CXL check out this mini-series on CXL by our Developer Advocate DJ Adams and Patrice Bender.
The @assert annotation is a new feature in CAP, released in December 2025. It enables complex, custom validations using CXL. This annotation provides a powerful way to enforce specific checks on inputs and raise appropriate errors if those checks fail. Error messages can be configured as either static strings or i18n message keys.
The annotation takes the form @assert: (<constraints>), where <constraints> are standard SQL case expressions containing one or more 'when' branches. The following example shows how to validate that a description is specified correctly:
annotate TravelService.Travels with {
Description @assert: (case
when Description is null then 'Description must be specified'
when trim(Description) = '' then 'Description must not be empty'
when length(Description) < 3 then 'Description too short'
end);
}It is also possible to formulate complex validations that would typically require a lot of code. The following example validates that the end date of a trip is not before the begin date and that all flight bookings fall within the travel period:
EndDate @assert: (case
when EndDate < BeginDate then 'End Date must be after Begin Date'
when exists Bookings [Flight.date > Travel.EndDate] then 'All bookings must be within the travel period'
end);The new @assert feature enables you to leverage the full potential of the CXL expression language while ensuring that validations are executed efficiently directly on the database. It integrates tightly with the Fiori user interface, providing rich error feedback and reducing the need for custom code.
Embracing declarative programming in CAP can transform the way you develop cloud applications. By reducing the need for custom code, ensuring consistency, and facilitating the expression of business logic, you can efficiently create applications that are easy to maintain and intuitive. Whether you're new to CAP or a seasoned developer, consider exploring the benefits of declarative programming. Start by reading our documentation.
Happy coding!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 31 | |
| 29 | |
| 26 | |
| 25 | |
| 22 | |
| 22 | |
| 22 | |
| 21 | |
| 19 | |
| 19 |