RAP Basics Part 10: EML — Entity Manipulation Language
Use EML to read and change RAP business objects from ABAP: READ ENTITIES, MODIFY ENTITIES (create, update, delete, create by association, execute action), the response parameters mapped/failed/reported, COMMIT ENTITIES and its rules, and when EML is used inside versus outside the BO.
Explanation
📌 KEY POINTS
✅ EML is the ABAP syntax for RAP BOs: READ ENTITIES, MODIFY ENTITIES, COMMIT ENTITIES, ROLLBACK ENTITIES.
✅ Changes go to the transactional buffer first; nothing is on the database until COMMIT ENTITIES (outside the BO).
✅ %cid (content ID) links a new instance to its children in the same request before keys exist; mapped returns the final keys.
✅ Inside the behavior pool use EML IN LOCAL MODE and never COMMIT ENTITIES; outside (reports, jobs, other BOs' save) you commit.
⚠️ Ignoring failed and reported after MODIFY or COMMIT hides errors — always check them.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 9 used EML inside the behavior pool. Here is the full language and its use from outside the BO.
━━━━━━━━━━━━━━━━━━━━
▶ 1. READ ENTITIES
- READ ENTITIES OF zi_travel ENTITY Travel FIELDS ( … ) WITH … RESULT lt_travel.
- Read by association: ENTITY Travel BY \_Booking ALL FIELDS WITH … RESULT lt_booking.
- Reads through the buffer — sees uncommitted changes of the same LUW.
━━━━━━━━━━━━━━━━━━━━
▶ 2. MODIFY ENTITIES
- CREATE FIELDS ( … ) WITH VALUE #( ( %cid = 'T1' … ) ).
- CREATE BY \_Booking … ( %cid_ref = 'T1' %target = … ) — children for a new parent.
- UPDATE FIELDS ( … ) WITH …; DELETE FROM …; EXECUTE acceptTravel FROM ….
- Response: MAPPED ls_mapped FAILED ls_failed REPORTED ls_reported.
━━━━━━━━━━━━━━━━━━━━
▶ 3. COMMIT ENTITIES
- COMMIT ENTITIES RESPONSE OF zi_travel FAILED … REPORTED ….
- Triggers the save sequence (finalize, check_before_save, save).
- Check sy-subrc and failed; ROLLBACK ENTITIES on error.
- Not allowed inside behavior pool handler/saver methods.
━━━━━━━━━━━━━━━━━━━━
▶ 4. WHERE EML IS USED
- Inside the BO: determinations/actions (IN LOCAL MODE).
- Outside: background jobs, migration programs, other BOs, unit tests.
- Consuming SAP released BOs (e.g. I_SalesOrderTP) from custom code — the clean-core alternative to BAPIs.
━━━━━━━━━━━━━━━━━━━━
▶ 5. PRIVILEGED AND LOCAL MODE
- IN LOCAL MODE: only inside the implementing BO; skips feature/authorization checks.
- PRIVILEGED: skip authorization for BOs that support it (with a privileged mode in the BDEF).
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Write a report that creates a travel with two bookings using %cid.
- Check failed/reported after MODIFY.
- COMMIT ENTITIES and check the response.
- Read the created travel with READ ENTITIES and display it.
✅ CHECKPOINT: the report creates a travel with bookings, prints the new TravelID, and shows messages if a validation fails.
Code example
REPORT ztravel_eml_demo. * ===== STEP 1: create a travel and two bookings in one MODIFY (%cid) =====DATA ls_mapped TYPE RESPONSE FOR MAPPED EARLY zi_travel.DATA ls_failed TYPE RESPONSE FOR FAILED EARLY zi_travel.DATA ls_reported TYPE RESPONSE FOR REPORTED EARLY zi_travel.DATA ls_fail_l TYPE RESPONSE FOR FAILED LATE zi_travel.DATA ls_rep_l TYPE RESPONSE FOR REPORTED LATE zi_travel.DATA ls_map_tr LIKE LINE OF ls_mapped-travel.DATA lt_travel TYPE TABLE FOR READ RESULT zi_travel\travel.DATA ls_travel LIKE LINE OF lt_travel.DATA lv_lines TYPE i. MODIFY ENTITIES OF zi_travel ENTITY Travel CREATE FIELDS ( AgencyID CustomerID BeginDate EndDate CurrencyCode ) WITH VALUE #( ( %cid = 'T1' AgencyID = '070001' CustomerID = '000010' BeginDate = sy-datum EndDate = sy-datum + 7 CurrencyCode = 'EUR' ) ) CREATE BY \_Booking FIELDS ( FlightDate ) WITH VALUE #( ( %cid_ref = 'T1' %target = VALUE #( ( %cid = 'B1' FlightDate = sy-datum ) ( %cid = 'B2' FlightDate = sy-datum + 7 ) ) ) ) MAPPED ls_mapped FAILED ls_failed REPORTED ls_reported. * ===== STEP 2: check the interaction-phase response =====DESCRIBE TABLE ls_failed-travel LINES lv_lines.IF lv_lines > 0. WRITE: / 'Create failed in interaction phase'. ROLLBACK ENTITIES. RETURN.ENDIF. * ===== STEP 3: commit - runs validations and save sequence =====COMMIT ENTITIES RESPONSE OF zi_travel FAILED ls_fail_l REPORTED ls_rep_l. IF sy-subrc <> 0. WRITE: / 'Save rejected - check validations'. ROLLBACK ENTITIES. RETURN.ENDIF. * ===== STEP 4: read back the committed travel =====READ TABLE ls_mapped-travel INTO ls_map_tr INDEX 1.READ ENTITIES OF zi_travel ENTITY Travel ALL FIELDS WITH VALUE #( ( TravelUUID = ls_map_tr-TravelUUID ) ) RESULT lt_travel. READ TABLE lt_travel INTO ls_travel INDEX 1.IF sy-subrc = 0. WRITE: / 'Travel created:', ls_travel-TravelID, ls_travel-OverallStatus.ENDIF.Real project scenario
A migration team loaded 40,000 open travel requests into a new RAP BO with a report that looped over the legacy file and called MODIFY ENTITIES plus COMMIT ENTITIES per record, without checking the response. The run finished "successfully", but 3,100 records were missing — validations had rejected them and nobody read failed/reported. The architect rewrote the program to process packages of 500 records per MODIFY/COMMIT, collect failed/reported into an error log with the legacy key (via %cid), and rerun only failed records. Runtime dropped from 6 hours to 50 minutes and every rejected record was explained.
Common mistakes
- Not checking failed/reported after MODIFY ENTITIES and COMMIT ENTITIES.
- Calling COMMIT ENTITIES inside a determination, action or saver method.
- Committing per record in mass programs instead of in packages.
- Forgetting %cid/%cid_ref when creating parent and children in one request.
- Using IN LOCAL MODE outside the implementing BO (not allowed).
Best practices
- Always evaluate mapped, failed and reported; log messages with the business key.
- Commit in packages for mass processing.
- Use %cid values derived from the source key to trace errors.
- Prefer EML on released SAP BOs over BAPIs in S/4HANA clean-core development.
- Use EML in ABAP Unit tests to test BO behavior end to end.
Interview angle
Questions: "What is EML?", "What is %cid used for?", "Can you use COMMIT ENTITIES in a determination?"
Strong answer: EML is the ABAP language for RAP BOs — READ/MODIFY/COMMIT/ROLLBACK ENTITIES — working on the transactional buffer. %cid identifies new instances before keys exist so children can be created in the same request; mapped returns the final keys. COMMIT ENTITIES triggers the save sequence and is only allowed outside the BO's handler and saver methods; results must be checked via failed/reported and sy-subrc.
Practice this lesson
Quick check
1. In MODIFY ENTITIES, what is %cid used for?
2. A report calls MODIFY ENTITIES OF zi_travel to create travels, checks failed (empty), but no data reaches the database. What is missing?
3. Where is COMMIT ENTITIES not allowed?
Interview questions
1. A batch program called MODIFY ENTITIES to create orders and immediately reported success, but nothing appeared in the database and some records were never explained. What is wrong?
Answer it in your own words first, then compare.
2. Why should direct database updates be avoided for RAP business objects?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- RAP Basics Part 1: RAP Architecture — Layers, Artifacts and When RAP Fits
- RAP Basics Part 11: Draft, Locking and Authorization
- RAP Basics Part 2: Data Model Design — Tables, Keys, Administrative Fields and Interface Views
- RAP Basics Part 3: Projection Layer and Metadata Extensions
- RAP Basics Part 4: Implementation Types — Managed, Unmanaged, Additional Save and Unmanaged Save
- RAP Basics Part 5: Root Entity, Child Entity and Composition
- RAP Basics Part 6: Behavior Definition — CRUD, Field Control and Features
- RAP Basics Part 7: Actions, Determinations and Validations — Design Decisions