Chapter 18 · Modern ABAP
EML, Validations & Determinations
How to add real business logic to your RAP business object — data manipulation, validation rules, and automatic field calculation.
In Chapter 17, you built a RAP business object. You created CDS Views, a Behavior Definition, and a Service Binding. But a business object that only reads data is a snapshot — not a living application.
Real business objects need behavior. Users should be able to create records. Data should be validated before saving. Fields should be filled automatically. Business actions like “Approve” or “Cancel” should be triggered by the click of a button.
This chapter teaches you the three pillars of RAP behavior: EML (how to manipulate data), Validations (how to check it), and Determinations (how to shape it automatically). Together, these turn a static model into a real SAP application.
🎯 What You Will Learn in This Chapter
- What EML is and how it differs from Open SQL
- How to use READ ENTITIES, MODIFY ENTITIES, and COMMIT ENTITIES
- What the REPORTED and FAILED parameters do
- How to write and register a Validation in a RAP business object
- How to write and register a Determination
- How to implement Actions (custom business operations)
- Understanding when to use Validation vs Determination vs Action
- How RAP handles errors, messages, and transactions
📘 What is EML?
EML stands for Entity Manipulation Language. It is a specialized ABAP syntax for interacting with RAP business objects — reading, creating, updating, deleting, and calling actions.
You can think of EML as the RAP counterpart of Open SQL. But while Open SQL talks directly to the database, EML talks to the business object — which means the framework enforces validations, determinations, authorizations, and transactional consistency automatically.
EML reads or writes a business object — with all the rules attached.
If your code modifies business data, use EML. If your code just reads for a report, Open SQL is fine.
The main EML statements
| Statement | What It Does |
|---|---|
READ ENTITIES | Reads data from a business object |
MODIFY ENTITIES | Creates, updates, or deletes business object data |
EXECUTE ACTION | Triggers a custom action defined on the business object |
COMMIT ENTITIES | Saves all changes made in the current transaction |
ROLLBACK ENTITIES | Discards all changes if something went wrong |
📖 READ ENTITIES — Reading Business Object Data
Use READ ENTITIES to read data from the business object. This ensures the framework applies authorizations correctly.
Basic READ ENTITIES
DATA: lt_keys TYPE TABLE FOR READ IMPORT ZI_Travel,
lt_travel TYPE TABLE FOR READ RESULT ZI_Travel.
" 1. Prepare the keys
lt_keys = VALUE #( ( TravelId = '00000001' )
( TravelId = '00000002' ) ).
" 2. Read the entities
READ ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
ALL FIELDS WITH CORRESPONDING #( %key )
WITH lt_keys
RESULT lt_travel
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
" 3. Use the result
LOOP AT lt_travel INTO DATA(ls_travel).
WRITE: / ls_travel-TravelId, ls_travel-TotalPrice.
ENDLOOP.
READ ENTITIES respects the DCL, uses buffered data, and returns the current state of any in-progress changes.
✏️ MODIFY ENTITIES — Creating, Updating, Deleting
Use MODIFY ENTITIES to change data. In a Managed RAP scenario, the framework handles the persistence automatically — you provide the data, and it takes care of the database.
Create a new record
DATA: lt_create TYPE TABLE FOR CREATE ZI_Travel.
" 1. Prepare the new entity data
lt_create = VALUE #(
( %cid = 'CID_1'
TravelId = '00000099'
AgencyId = '070001'
CustomerId = '000077'
BeginDate = '20260501'
EndDate = '20260510'
TotalPrice = '1200.00'
CurrencyCode = 'USD'
) ).
" 2. Execute the create
MODIFY ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
CREATE FIELDS ( TravelId AgencyId CustomerId
BeginDate EndDate TotalPrice CurrencyCode )
WITH lt_create
MAPPED DATA(lt_mapped)
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
Update an existing record
DATA: lt_update TYPE TABLE FOR UPDATE ZI_Travel.
lt_update = VALUE #(
( TravelId = '00000099'
TotalPrice = '1500.00' ) ).
MODIFY ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( TotalPrice )
WITH lt_update
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
Delete a record
DATA: lt_delete TYPE TABLE FOR DELETE ZI_Travel.
lt_delete = VALUE #( ( TravelId = '00000099' ) ).
MODIFY ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
DELETE FROM lt_delete
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
💾 COMMIT ENTITIES, REPORTED, and FAILED
COMMIT ENTITIES
After a MODIFY ENTITIES call, the changes are held in the transactional buffer. They are not yet in the database. You must call COMMIT ENTITIES to save them.
" Check for errors first
IF lt_failed IS INITIAL.
" No failures — commit
COMMIT ENTITIES
RESPONSE OF ZI_Travel
FAILED DATA(lt_commit_failed)
REPORTED DATA(lt_commit_reported).
IF lt_commit_failed IS INITIAL.
MESSAGE 'Changes saved successfully' TYPE 'S'.
ENDIF.
ELSE.
" Handle errors
LOOP AT lt_reported INTO DATA(ls_rep) WHERE %msg->severity = 'E'.
MESSAGE ls_rep-%msg TYPE 'E'.
ENDLOOP.
" Explicit rollback (optional — happens automatically if you exit)
ROLLBACK ENTITIES.
ENDIF.
REPORTED and FAILED — the diagnostic pair
| Parameter | What It Contains | Why It Matters |
|---|---|---|
| REPORTED | Table of messages — including errors, warnings, and success messages | Tells you exactly what the framework detected |
| FAILED | List of entity keys that could not be processed | Tells you which records need fixing |
✅ Validations — Checking Data Before Save
A Validation is a rule that checks data before saving. If the rule fails, the framework returns an error and blocks the save.
Step 1 — Declare the validation in the BDEF
validation validateDates on save
{ field BeginDate, EndDate; }
Step 2 — Implement the validation method
METHOD validateDates.
READ ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
FIELDS ( BeginDate EndDate )
WITH CORRESPONDING #( %key )
WITH keys
RESULT DATA(lt_travel).
LOOP AT lt_travel INTO DATA(ls_travel).
IF ls_travel-EndDate < ls_travel-BeginDate.
APPEND VALUE #(
%tky = ls_travel-%tky
%msg = new_message(
id = 'ZMSG_TRAVEL'
number = '001'
severity = if_abap_behv_message=>severity-error )
%element-EndDate = if_abap_behv=>element->state->error )
TO reported-Travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
Types of validations
| Type | When It Runs |
|---|---|
on save | When the user clicks Save — most common |
on modify | When data is changed — for real-time validation |
on prepare | Just before the save process starts — for final cross-checks |
⚙️ Determinations — Automatic Field Calculations
A Determination fills or adjusts data automatically. It never blocks the save — it just shapes the data before it is written.
Common uses:
- Default a Status field to “New” when a record is created
- Calculate Total Price by summing line-item amounts
- Set the current timestamp on a “Last Changed At” field
- Derive a category field based on other field values
Step 1 — Declare the determination in the BDEF
determination setStatus on modify
{ field Status; }
Step 2 — Implement the determination method
METHOD setStatus.
" Read the entities being processed
READ ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
FIELDS ( Status )
WITH CORRESPONDING #( %key )
WITH keys
RESULT DATA(lt_travel).
" Modify Status to 'N' (New)
DATA lt_update TYPE TABLE FOR UPDATE ZI_Travel.
LOOP AT lt_travel INTO DATA(ls_travel).
IF ls_travel-Status IS INITIAL.
APPEND VALUE #(
%tky = ls_travel-%tky
Status = 'N' )
TO lt_update.
ENDIF.
ENDLOOP.
" Write the changes back
MODIFY ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( Status )
WITH lt_update.
ENDMETHOD.
Types of determinations
| Type | When It Runs | Typical Use |
|---|---|---|
on modify | Immediately when data is changed | Default values, calculated fields |
on save | When the user saves | Update timestamps, aggregate totals |
precheck | Before modifications are accepted | Set up context for other logic |
Determination says “Let me fix this data for you” — it never blocks.
🎬 Actions — Custom Business Operations
An Action is a business operation the user can trigger, like Approve, Cancel, Duplicate, or Submit. Actions can change data, call other business objects, and return results.
Declaring an action in the BDEF
action ( features : instance ) approve;
action ( features : instance ) cancel
parameter ZD_CANCEL_PARAM " optional abstract entity
result [1] $self;
Implementing the action
METHOD approve.
" Read the current state
READ ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
FIELDS ( Status )
WITH CORRESPONDING #( %key )
WITH keys
RESULT DATA(lt_travel).
" Set Status to 'A' (Approved)
DATA lt_update TYPE TABLE FOR UPDATE ZI_Travel.
LOOP AT lt_travel INTO DATA(ls_travel).
APPEND VALUE #(
%tky = ls_travel-%tky
Status = 'A' )
TO lt_update.
ENDLOOP.
MODIFY ENTITIES OF ZI_Travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( Status )
WITH lt_update
REPORTED DATA(reported).
" Return a success message
APPEND VALUE #(
%tky = ls_travel-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-success
text = 'Travel approved' ) )
TO reported-Travel.
ENDMETHOD.
🚨 Error Handling in RAP
RAP has a structured way to return errors and messages. Understanding this is critical.
The message pattern
- Reported messages — errors, warnings, or success messages from the framework or your code
- Failed entities — which records could not be processed
- Transitions — state changes (from “New” to “Approved”, etc.)
Severities of messages
| Severity | Meaning |
|---|---|
severity-error | Blocks the operation |
severity-warning | User can proceed but is warned |
severity-information | Informational only |
severity-success | Operation completed successfully |
📝 Chapter Summary
- EML (Entity Manipulation Language) is the RAP syntax for reading and modifying business objects.
- READ ENTITIES reads business object data with authorization enforced.
- MODIFY ENTITIES creates, updates, or deletes records.
- COMMIT ENTITIES saves changes to the database. Always check REPORTED and FAILED first.
- Validations check data and can block the save.
- Determinations fill or adjust data automatically.
- Actions are custom business operations that users can trigger.
- RAP has structured error handling with
REPORTED,FAILED, and severity levels.
🎤 Interview Questions & Answers
EML, Validations, and Determinations are core RAP topics. Expect these questions in any modern ABAP interview.
EML (Entity Manipulation Language) is a specialized ABAP syntax for interacting with RAP business objects. It provides statements like READ ENTITIES, MODIFY ENTITIES (CREATE, UPDATE, DELETE), EXECUTE ACTION, and COMMIT ENTITIES. EML ensures that all business logic, validations, and authorizations defined in the Behavior Definition are automatically enforced.
Open SQL reads and writes database tables directly — bypassing RAP business logic. EML operates on business objects and triggers the full RAP framework: validations, determinations, authorizations, draft handling, and transactional consistency. Use EML to modify business data; use Open SQL only to read data for non-transactional purposes.
A Validation in RAP is a rule that checks data before it is saved. If the rule fails, an error message is returned and the save is rejected. Validations are declared in the Behavior Definition using the validation keyword, and implemented as methods in the Behavior Implementation class. Example: check that Travel end date is after begin date.
A Determination in RAP is automatic business logic that runs when data changes. It fills or adjusts fields without user intervention — for example, setting a Total Price by summing line items, or defaulting a Status field to ‘New’. Determinations are declared in the Behavior Definition using the determination keyword and implemented in the Behavior Implementation class.
A Validation checks data and returns an error if the rule fails — it can block the save. A Determination automatically fills or adjusts data — it never blocks the save. Both are declared in the BDEF and implemented in the Behavior Implementation. In one sentence: Validations gate data, Determinations shape data.
An Action in RAP is a custom business operation that a user can trigger — like Approve, Cancel, or Duplicate. Actions are declared in the Behavior Definition with an optional parameter interface and implemented as a method. Actions can modify multiple entities, invoke determinations, and return success or error messages.
The REPORTED parameter in EML is an output parameter that returns messages and failed entities from a MODIFY or action call. It contains a table of messages (with type, ID, number, and text) and a list of failed entity keys. You check the REPORTED parameter to detect errors after an EML call and decide whether to COMMIT or ROLLBACK.
The FAILED parameter in EML is an output parameter that lists the entity keys that could not be processed. Combined with REPORTED, it tells you exactly which records failed and why. If FAILED is empty, the operation succeeded for all entities and you can COMMIT; if it contains entries, you must handle the errors and likely call ROLLBACK.
COMMIT ENTITIES is used after successful MODIFY ENTITIES calls to persist the changes to the database. Without COMMIT ENTITIES, the changes remain in the transactional buffer and are not saved. You must call COMMIT ENTITIES at the end of your RAP transaction. If any error occurred during the modify, call ROLLBACK ENTITIES instead.
You can debug a RAP business object by setting breakpoints in the Behavior Implementation class (usually named ZBP_*), then triggering the business object via the Service Binding preview or by calling EML from a test report. External breakpoints work for OData calls. Use ST05 to trace the SQL performed by the framework, and the ADT Console to view returned messages.
🛠 Practice Task for This Chapter
Extend the RAP business object you built in Chapter 17 with real business logic.
- Add a Validation: In your BDEF, add
validation validateDates on save { field BeginDate, EndDate; }. Implement the method to check that EndDate is not before BeginDate. Test by saving a Travel with reversed dates. - Add a Determination: Add
determination setStatus on modify { field Status; }. Implement the method to default Status to ‘N’ (New) if it is empty when the entity is created. - Add an Action: Declare
action approve;in the BDEF. Implement it to change Status from ‘N’ to ‘A’. In the Fiori preview, an “Approve” button should now appear. - Test with EML: Write a small ABAP report that creates a Travel using
MODIFY ENTITIES, then callsCOMMIT ENTITIES. Verify the record appears in the database. - Check the error flow: Send a broken request (reversed dates) via EML. Inspect the REPORTED parameter to see the error message. Confirm the record was not saved.
Test: Kon Banega Crorepati?
5 questions. ₹1 Crore. Prove you understood EML, Validations & Determinations. No pressure — restart anytime.
Explore Our Instructor-Led SAP & IT Courses
Self-study works. But if you want guided training, real project practice, and placement support — here are the courses we offer. Book a free demo before you decide.
WhatsApp us