ABAP for Cloud Development, ©Copyright 2024 SAP SE. All rights reserved.
ABAP - Keyword Documentation → ABAP - RAP Business Objects → RAP - Behavior Definitions → RAP - BDL for Behavior Definitions → RAP - Managed and Unmanaged Behavior Definitions → RAP - EntityBehaviorDefinition → RAP - EntityBehaviorBody →RAP - validation
Syntax
validation ValName on save { CUD1 | {field Field1};
[ CUD2; ...; ] [field Field2; ...] }
Description
A RAP validation checks the consistency of RAP BO instances based on trigger conditions. A validation is automatically invoked by the RAP framework if the trigger condition of the validation is fulfilled. Trigger conditions can be modify operations (create, update, delete) CUD1; CUD2; ..., or modified fields Field1; Field2; .... Validations are invoked during the save sequence at the end of a transaction and this is indicated by the mandatory addition on save. An invoked validation can reject inconsistent instance data from being saved and return messages to the consumer. Validations must be implemented in the RAP handler method FOR VALIDATE in the local ABAP behavior pool (ABP).
The name ValName must comply with the general naming rules for RAP behavior definitions described in the topic RAP BDL - General Syntax Rules. In particular, is can have a maximum of 30 characters.
Trigger Conditions
There can be one or more trigger conditions. The trigger conditions can be changes of field values or the execution of one of the standard operations create, update, or delete. When one of these operations is executed for a draft instance or for an active instance, validations with the respective trigger operations are triggered. The validation is triggered if at least one trigger condition is fulfilled.
Note: Update works only in combination with the trigger operation create.
Note: If a field is tagged with the RAP field characteristic notrigger[:warn], it must not be used in a trigger condition.
If a validation fails for a certain entity instance, the following effect takes place:
Availability
Caution: Not available for unmanaged, non-draft RAP BOs.
Hints
Further Information
Development guide for the ABAP RESTful Application Programming Model, section about
Validations.
Example
The following example shows a managed BDEF that defines the validation ValidateBuyerId.
managed implementation in class bp_demo_sales_cds_so_1 unique;
strict(2);
define behavior for DEMO_SALES_CDS_SO_1 alias SalesOrder
persistent table demo_sales_order
lock master
authorization master (global)
{
create;
update;
field ( readonly, numbering : managed ) SoKey;
validation ValidateBuyerId on save { field BuyerId; }
mapping for DEMO_SALES_ORDER corresponding
{
SoKey = so_key;
BuyerId = buyer_id;
ShipToId = ship_to_id;
QuantitySum = quantity_sum;
UomSum = uom_sum;
AmountSum = amount_sum;
CurrencySum = currency_sum;
CompanyCode = company_code;
CreatedBy = created_by;
CreatedAt = created_at;
CreatedOn = created_on;
LifecycleStatus = lifecycle_status;
LastChangedBy = last_changed_by;
LastChangedOn = last_changed_on;
LastChangedAt = last_changed_at;
}
}
The validation is implemented in the ABAP behavior pool. It checks if the buyer ID specified in a sales order is valid by checking whether this buyer ID exists in the database table that lists all business partners. It is triggered as soon as the field BuyerId is changed. If the buyer ID is not valid, the data changes are rejected and An error message is returned.
METHOD ValidateBuyerId.
" Read relevant sales order data
READ ENTITIES OF demo_sales_cds_so_1 IN LOCAL MODE
ENTITY SalesOrder
FIELDS ( BuyerId ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_salesorder)
FAILED DATA(lt_failed).
failed = CORRESPONDING #( DEEP lt_failed ).
DATA lt_buyer TYPE SORTED TABLE OF demo_sales_bupa
WITH UNIQUE KEY id.
lt_buyer = CORRESPONDING #( lt_salesorder
MAPPING id = BuyerID EXCEPT * ).
DELETE lt_buyer WHERE id IS INITIAL.
IF lt_buyer IS NOT INITIAL.
" Check if customer ID exists
SELECT FROM demo_sales_bupa FIELDS id
FOR ALL ENTRIES IN @lt_buyer
WHERE id = @lt_buyer-id
INTO TABLE @DATA(lt_buyer_db).
ENDIF.
" Raise message for non existing customer id
LOOP AT lt_salesorder INTO DATA(ls_so).
APPEND VALUE #( %tky = ls_so-%tky
%state_area = 'VALIDATE_BUYER' )
TO reported-salesorder.
IF ls_so-BuyerId IS NOT INITIAL
AND NOT line_exists( lt_buyer_db[ id = ls_so-BuyerId ] ).
APPEND VALUE #( %tky = ls_so-%tky ) TO failed-salesorder.
APPEND VALUE #( %tky = ls_so-%tky
%state_area = 'VALIDATE_BUYER'
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'validation failed' )
%element-BuyerID = if_abap_behv=>mk-on )
TO reported-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
EML access 1: Valid instances are committed to the database, for invalid instances, an error message is returned.
The class CL_DEMO_CDS_VALIDATION accesses the business object using EML. It creates three BO instances - one of them is valid, two are invalid. The valid entity instance is committed to the database, while for the invalid instances, error messages are returned. The valid entity instance is created in a different RAP transaction than the invalid ones. If all three entity instances were created in one RAP transaction - in this case, with the same COMMIT ENTITIES statement - all three of them would be rejected.
Result: Valid instances are committed to the database, for invalid instances, an error message is returned.
EML access 2: If a RAP transaction contains only one inconsistent instance, the complete content of the transactional buffer is rejected.
The class CL_DEMO_CDS_VALIDATION_1 demonstrates that validations accept or reject data changes per RAP transaction. It creates the same three BO instances as the report DEMO_CDS_VALIDATION, one of them valid, the other two invalid.
Code snippet:
DELETE FROM demo_sales_order.
MODIFY ENTITIES OF demo_sales_cds_so_1
ENTITY SalesOrder
CREATE FIELDS ( BuyerId ) WITH VALUE #(
( %cid = '1' BuyerId = `a` )
( %cid = '2' BuyerId = `CCC` )
( %cid = '3' BuyerId = 'DDD' ) )
MAPPED FINAL(mapped)
FAILED FINAL(failed)
REPORTED FINAL(reported).
COMMIT ENTITIES.
Since this RAP transaction contains two inconsistent instances, all data changes are rejected, even the valid instance.
Result: The valid instance is not committed to the database.
EML access 3: If an invalid instance is not corrected or deleted proactively, no further data changes are possible.
The class CL_DEMO_CDS_VALIDATION_2 demonstrates how an invalid instance blocks further changes:
Code snippet:
" valid instance: commit works.
MODIFY ENTITIES OF demo_sales_cds_so_1
ENTITY SalesOrder
CREATE FIELDS ( BuyerId ) WITH VALUE #(
( %cid = '1' BuyerId = `a` ) )
MAPPED DATA(mapped)
FAILED DATA(failed)
REPORTED DATA(reported).
COMMIT ENTITIES.
" invalid instances: commit fails.
MODIFY ENTITIES OF demo_sales_cds_so_1
ENTITY SalesOrder
CREATE FIELDS ( BuyerId ) WITH VALUE #(
( %cid = '2' BuyerId = `CCC` )
( %cid = '3' BuyerId = 'DDD' ) )
MAPPED FINAL(mapped1)
FAILED FINAL(failed1)
REPORTED FINAL(reported1).
COMMIT ENTITIES RESPONSE OF demo_sales_cds_so_1
FAILED FINAL(failed_commit)
REPORTED FINAL(reported_commit).
" valid instance: commit fails. Invalid instances must be
" corrected or deleted first.
MODIFY ENTITIES OF demo_sales_cds_so_1
ENTITY SalesOrder
CREATE FIELDS ( BuyerId ) WITH VALUE #(
( %cid = '1' BuyerId = `b` ) )
MAPPED mapped
FAILED failed
REPORTED reported.
COMMIT ENTITIES.
Result: Only the first valid instance is committed to the database. The second valid instance is blocked.
Executable Example
The example above is explained in detail in the executable example RAP BDL - validation.