Sunday, August 17, 2025

Mastering SAP ABAP EML: A Deep Dive into Reading, Updating, and Custom Projections

Introduction to Entity Manipulation Language (EML) in ABAP RAP

Welcome to the world of the ABAP RESTful Application Programming Model (RAP)! At its core, RAP provides a standardized, efficient way to build Fiori apps and Web APIs on SAP S/4HANA and the SAP Business Technology Platform. A key component of this model is the Entity Manipulation Language (EML). EML is a powerful, type-safe ABAP language extension designed specifically to interact with RAP Business Objects (BOs). It allows developers to perform CRUD-Q operations (Create, Read, Update, Delete, Query) and execute actions on BOs from within other ABAP code, such as in a custom report, a BAPI, or a different BO's implementation.

In this post, we'll explore the practical aspects of using EML, focusing on reading and updating data, and we'll answer a crucial architectural question: can you create custom projections for EML consumption? Let's dive in.

Reading Data with EML: The READ ENTITIES Statement

The fundamental statement for retrieving data from a RAP BO is READ ENTITIES. Unlike traditional SELECT statements that target database tables, EML targets the semantic business object entity. This means all business logic, determinations, and validations defined in the BO's behavior are respected during the read operation.

Let's consider a scenario where we have a simple Travel BO (e.g., Z_I_TRAVEL_U) and we want to read the data for a specific Travel ID.

Code Snippet: Reading a Single Entity


REPORT z_eml_read_example.

START-OF-SELECTION.
  DATA: lv_travel_id TYPE /dmo/travel_id VALUE '00000105'.

  READ ENTITIES OF z_i_travel_u IN LOCAL MODE
    ENTITY Travel
    ALL FIELDS WITH VALUE #(
      ( %key-TravelID = lv_travel_id )
     )
    RESULT DATA(lt_travel_result)
    FAILED DATA(ls_failed)
    REPORTED DATA(ls_reported).

  IF ls_failed IS INITIAL AND lt_travel_result IS NOT INITIAL.
    " Success! Data is in the first line of lt_travel_result
    cl_demo_output=>display( lt_travel_result ).
  ELSE.
    " Handle errors
    cl_demo_output=>display( ls_failed ).
    cl_demo_output=>display( ls_reported ).
  ENDIF.

Breakdown of the Syntax:

  • READ ENTITIES OF z_i_travel_u: Specifies the root entity of the Business Object you want to interact with.
  • IN LOCAL MODE: This is crucial. It tells the EML statement to execute in the current ABAP session without triggering the entire RAP save sequence or requiring a COMMIT. It's the standard for using EML within ABAP programs.
  • ENTITY Travel: Specifies the alias of the entity within the BO you are targeting. This alias is defined in the Behavior Definition.
  • ALL FIELDS WITH: Indicates you want to retrieve all fields of the entity. You can also specify a list of fields (FIELDS ( Field1 Field2 )).
  • VALUE #(( %key-TravelID = ... )): A modern constructor expression providing the key(s) of the entity instance(s) you want to read.
  • RESULT DATA(lt_travel_result): The result table, which will contain the successfully read data. It will be typed automatically based on the entity.
  • FAILED DATA(ls_failed) and REPORTED DATA(ls_reported): These structures capture any failures or messages that occurred during the read process, allowing for robust error handling.

Updating Data with EML: The MODIFY ENTITIES Statement

Updating data follows a similar pattern but uses the MODIFY ENTITIES statement. A best practice for updates is a two-step process: first, read the entity to get its current state and ETag (if used), then provide the modified data to the update statement.

Let's update the description of the Travel instance we just read.

Code Snippet: Updating an Entity


REPORT z_eml_update_example.

START-OF-SELECTION.
  DATA: lv_travel_id TYPE /dmo/travel_id VALUE '00000105'.

  " STEP 1: READ the entity first (optional but good practice for ETags)
  READ ENTITIES OF z_i_travel_u IN LOCAL MODE
    ENTITY Travel
    ALL FIELDS WITH VALUE #(
      ( %key-TravelID = lv_travel_id )
     )
    RESULT DATA(lt_travel_read).

  IF lt_travel_read IS NOT INITIAL.
    " STEP 2: MODIFY the entity with the new data
    MODIFY ENTITIES OF z_i_travel_u IN LOCAL MODE
      ENTITY Travel
      UPDATE FIELDS ( Description )
      WITH VALUE #(
        ( %key-TravelID = lv_travel_id
          Description = 'Updated via EML at ' && |{ sy-uzeit }| )
       )
      MAPPED DATA(ls_mapped)
      FAILED DATA(ls_failed)
      REPORTED DATA(ls_reported).

    IF ls_failed IS INITIAL.
      cl_demo_output=>display( 'Update successful!' ).
      COMMIT ENTITIES.
    ELSE.
      cl_demo_output=>display( 'Update failed!' ).
      cl_demo_output=>display( ls_failed ).
      cl_demo_output=>display( ls_reported ).
    ENDIF.
  ENDIF.

Breakdown of the Syntax:

  • MODIFY ENTITIES OF ...: The core statement for CUD operations.
  • UPDATE FIELDS ( Description ): We specify the action (UPDATE) and explicitly list the fields we intend to change. This is more efficient than updating all fields.
  • WITH VALUE #( ( ... ) ): We provide a table containing the key of the instance to modify and the new values for the fields listed in the UPDATE FIELDS clause.
  • MAPPED DATA(ls_mapped): Captures information mapping the request to the result, which is very useful when modifying multiple entities at once.
  • COMMIT ENTITIES: Unlike the read, a modification needs to be saved. COMMIT ENTITIES triggers the RAP save sequence, which finalizes the changes in the database. A corresponding ROLLBACK ENTITIES can be used to discard changes in case of an error.

The Power of Projections: Can We Create a Custom Behavior Projection for EML?

Absolutely, yes! Not only can you create a custom behavior projection, but it is also a highly recommended best practice for several reasons:

  • Simplicity: You can expose a simplified version of your BO to the EML consumer, showing only the fields and actions relevant to that specific use case.
  • Security & Robustness: You can make certain fields read-only in the projection, even if they are updatable in the base BO. This prevents EML programs from accidentally or maliciously changing critical data.
  • Stable Interface: A projection acts as a stable contract. You can freely change the underlying base BO, and as long as the projection remains the same, your EML consumer programs will not be affected.

How It Works

You create a CDS Projection View on top of your base BO's interface view and then create a Behavior Definition for that projection. In the projection's Behavior Definition, you explicitly define what is allowed.

Example: Behavior Projection Definition

Let's say we want a projection that only allows updating the Description field of our Travel BO.

1. CDS Projection View: Z_C_TRAVEL_EML_PROJ

2. Behavior Definition for Projection:


projection;
strict;

define behavior for Z_C_TRAVEL_EML_PROJ alias TravelProjection
{
  use etag;

  // Only the 'update' operation is exposed.
  // 'create' and 'delete' are implicitly forbidden.
  use update;
}

Consuming the Projection with EML

Now, in your ABAP program, you simply point your EML statement to the projection's CDS view name instead of the base BO. The syntax remains the same, but the scope of what you can do is now governed by the projection.


" Using the custom projection now!
" Notice the BO name has changed to the projection view name.
MODIFY ENTITIES OF Z_C_TRAVEL_EML_PROJ IN LOCAL MODE
  ENTITY TravelProjection  " <-- Using the projection's alias
  UPDATE FIELDS ( Description )
  WITH VALUE #(
    ( %key-TravelID = '00000105'
      Description = 'Updated via a safe projection!' )
   )
  FAILED DATA(ls_failed)
  REPORTED DATA(ls_reported).

" An attempt to update another field, like 'BeginDate', would result in a runtime error
" because it's not exposed as updatable in our projection.

By using the projection Z_C_TRAVEL_EML_PROJ, you have created a clean, purpose-built interface for your EML consumer, making your code safer and easier to maintain.

No comments:

Post a Comment

SAP IDocs vs. APIs: Choosing the Right Integration Strategy

In the complex world of enterprise resource planning, SAP systems often need to communicate with other applications, both internal and exter...