This is a test message to test the length of the message box.
Login
ABAP RAP Entity Manipulation Language
Created by Software-Heroes

RAP - Entity Manipulation Language (EML)

In this article we deal with a new language construct to access our RAP Business Object.

How do you easily access a business object from the outside and what does it entail? In this article you will learn more about the new language construct EML and what is behind it. We try to show you the basic concepts and the first possibilities that EML puts at your disposal.

 

EML

The Entity Manipulation Language is a new SQL-like language construct that allows you to access RAP business objects and their data. All validations, determinations and other settings are taken into account, so that you have the same functions as with the Fiori app. When using you also get full support for actions and the draft functions if they are configured in the object.

 

READ

In this section we'll talk about reading data from an object, but you have to keep in mind that it's not a SELECT, it's more of a READ. So we have to read the appropriate keys in one way beforehand, there is currently no query function for business objects.

Let's look at two different forms of access, which differ slightly in detail. In the first example, we read all the data for a data record and fill the selection table before accessing it:

DATA:
  lt_selection TYPE TABLE FOR READ IMPORT ZBS_I_RAPPartner.

lt_selection = VALUE #(
  ( PartnerNumber = '1000000001' )
  ( PartnerNumber = '1000000003' )
).

READ ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
  ALL FIELDS WITH lt_selection
  RESULT DATA(lt_partner_long)
  FAILED DATA(ls_failed)
  REPORTED DATA(ls_reported).

out->write( lt_partner_long ).

 

To do this, we start by defining a table for access that contains the appropriate partner numbers that we want to read. We then call READ ENTITIES to have the result returned for the selection. The second example is a bit shorter because we pass the selection directly. In this example we only read some fields of the entity:

READ ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
  FIELDS ( PartnerName Street City ) WITH VALUE #(
    ( PartnerNumber = '1000000001' )
    ( PartnerNumber = '1000000003' )
  )
  RESULT DATA(lt_partner_short)
  FAILED ls_failed
  REPORTED ls_reported.

out->write( lt_partner_short ).

 

After the selection has been made and the output has been made to the console, you will receive the following result. The upper result is the long form, below the short form. The resulting table of results always represents the entire entity:

 

So what is it about the individual components of the statement, briefly explained here:

  • READ ENTITIES - Specification of the RAP business object, usually corresponds to the root node of the object.
  • ENTITY - Specification of the entity to be read from the RAP object, the alias of the entity is particularly important here.
  • FIELDS - Specification of the fields to be read as a table, expression of the fields or all fields.
  • WITH - pass the keys to the read function, table is defined with "TABLE FOR READ IMPORT".
  • RESULT - Table with the read data, can be created using an inline declaration and has the type "TABLE FOR READ RESULT".
  • FAILED - Key of the erroneous entries if reading did not work.
  • REPORTED - Contains error messages when there are problems reading.

 

CREATE

In the next step, we want to create a new data record, for this there is the statement MODIFY ENTITIES, which contains all important operations (Create, Update, Delete, Action). In our example, we fill a table again, this time of the "TABLE FOR CREATE" type, since we want to create a new data record. The following example:

DATA:
  lt_creation  TYPE TABLE FOR CREATE ZBS_I_RAPPartner.

lt_creation = VALUE #(
  (
    %cid = 'DummyKey1'
    PartnerNumber = '1000000007'
    PartnerName = 'Amazon'
    Country = 'US'
    %control-PartnerNumber = if_abap_behv=>mk-on
    %control-PartnerName = if_abap_behv=>mk-on
    %control-Country = if_abap_behv=>mk-on
  )
).

MODIFY ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
  CREATE FROM lt_creation
  FAILED ls_failed
  MAPPED DATA(ls_mapped)
  REPORTED ls_reported.

TRY.
    out->write( ls_mapped-partner[ 1 ]-PartnerNumber ).
    COMMIT ENTITIES.

  CATCH cx_sy_itab_line_not_found.
    out->write( ls_failed-partner[ 1 ]-%cid ).
ENDTRY.

 

What you will notice when filling the table is that we not only take over the data fields, but also fill in the CID and CONTROL fields. These fields are important so that the data in the object is correctly transferred:

  • %CID - Dummy ID identifying a record within Create, Update and Delete. Can be assigned freely, but should be unambiguous.
  • %CONTROL - Specifies which fields are taken into account during the operation. If the fields in the structure are not active, no data is transferred and the new data record is empty.
  • MAPPED - return the changed key and mapping from CID to table key. Especially important when the keys are generated within the business object.

 

Finally, the new key is output in the log and a COMMIT ENTITIES is sent. This roughly corresponds to COMMIT WORK in ABAP, but is used specifically for RAP operations.

 

UPDATE

In the last step we created a relatively incomplete data set on the database, which we now want to enrich with some data. In addition, for the initial situation, the current data record on the database:

 

To do this, we define a table of the "TABLE FOR UPDATE" type suitable for the action and fill in the required fields. We don't have to specify a CID for the update because the key is already known. However, we should also specify the appropriate key. Furthermore, the CONTROL structure is important again. This results in the following code:

DATA:
  lt_update    TYPE TABLE FOR UPDATE ZBS_I_RAPPartner.

lt_update = VALUE #(
  (
    PartnerNumber = '1000000007'
    PartnerName = 'Amazon Fake'
    City = 'Seattle'
    PaymentCurrency = 'USD'
    %control-PaymentCurrency = if_abap_behv=>mk-on
    %control-City = if_abap_behv=>mk-on
  )
).

MODIFY ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
  UPDATE FROM lt_update
  FAILED ls_failed
  MAPPED ls_mapped
  REPORTED ls_reported.

IF ls_failed-partner IS INITIAL.
  out->write( 'Updated' ).
  COMMIT ENTITIES.
ENDIF.

 

As you can see in the example above, we also pass a new name for the partner, but do not fill the CONTROL structure. So we assume that the Name field is not updated and keeps the original value. After running the code, we get the following result, and our guess is true:

 

IF_ABAP_BEHV

In our examples we had already used constants from the interface IF_ABAP_BEHV. The interface provides various constants for use around the behavior implementation and also provides information about where these constants can be used via ABAP Docs. Here is an example of the MK constants used:

 

Usage

Where do you actually need EML? Above all, it is used for external access to the business object, as our examples are currently structured. Later there will be many RAP objects that function as BAPIs in the system, so you have to address them in this way. Furthermore, RAP is also used within the business object if you implement validations, determinations or actions, since you have to access and change data from the BO again and again.

 

Complete example

As always, at the end the complete source code of the example, you can also find the whole thing via commit in the corresponding GitHub repository from us:

CLASS zcl_bs_demo_simple_eml DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_bs_demo_simple_eml IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    DATA:
      lt_selection TYPE TABLE FOR READ IMPORT ZBS_I_RAPPartner,
      lt_creation  TYPE TABLE FOR CREATE ZBS_I_RAPPartner,
      lt_update    TYPE TABLE FOR UPDATE ZBS_I_RAPPartner.

    " Long form for selection (ALL FIELDS)
    lt_selection = VALUE #(
      ( PartnerNumber = '1000000001' )
      ( PartnerNumber = '1000000003' )
    ).

    READ ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
      ALL FIELDS WITH lt_selection
      RESULT DATA(lt_partner_long)
      FAILED DATA(ls_failed)
      REPORTED DATA(ls_reported).

    out->write( lt_partner_long ).

    " Short form for selection (SOME FIELDS)
    READ ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
      FIELDS ( PartnerName Street City ) WITH VALUE #(
        ( PartnerNumber = '1000000001' )
        ( PartnerNumber = '1000000003' )
      )
      RESULT DATA(lt_partner_short)
      FAILED ls_failed
      REPORTED ls_reported.

    out->write( lt_partner_short ).

    " Create new partner
    lt_creation = VALUE #(
      (
        %cid = 'DummyKey1'
        PartnerNumber = '1000000007'
        PartnerName = 'Amazon'
        Country = 'US'
        %control-PartnerNumber = if_abap_behv=>mk-on
        %control-PartnerName = if_abap_behv=>mk-on
        %control-Country = if_abap_behv=>mk-on
      )
    ).

    MODIFY ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
      CREATE FROM lt_creation
      FAILED ls_failed
      MAPPED DATA(ls_mapped)
      REPORTED ls_reported.

    TRY.
        out->write( ls_mapped-partner[ 1 ]-PartnerNumber ).
        COMMIT ENTITIES.

      CATCH cx_sy_itab_line_not_found.
        out->write( ls_failed-partner[ 1 ]-%cid ).
    ENDTRY.

    " Update partner
    lt_update = VALUE #(
      (
        PartnerNumber = '1000000007'
        PartnerName = 'Amazon Fake'
        City = 'Seattle'
        PaymentCurrency = 'USD'
        %control-PaymentCurrency = if_abap_behv=>mk-on
        %control-City = if_abap_behv=>mk-on
      )
    ).

    MODIFY ENTITIES OF ZBS_I_RAPPartner ENTITY Partner
      UPDATE FROM lt_update
      FAILED ls_failed
      MAPPED ls_mapped
      REPORTED ls_reported.

    IF ls_failed-partner IS INITIAL.
      out->write( 'Updated' ).
      COMMIT ENTITIES.
    ENDIF.

  ENDMETHOD.
ENDCLASS.

 

Conclusion

With EML, you first have to learn some new language constructs and how they work exactly. The new table types can also be overwhelming at first and some of the content makes no sense at first. But once you get into the language, it's fun to work with. In a later article we will delve even deeper into the topic of EML, here are just the basics for the following articles.


Included topics:
RAPBTPEMLIF_ABAP_BEHV
Comments (0)

RAP - Build a simple app

Category - ABAP

In the RAP series, we looked at how to build a simple app with RAP, design the interface and test everything with a preview. Here's a little recap.

01/27/2023

RAP - ABAP Unit (Service)

Category - ABAP

How do you actually test the service of an interface or RAP app automatically? In this article we look at unit tests for OData services.

01/20/2023

RAP - ABAP Unit (Business Object)

Category - ABAP

At this point, we'll take a look at how we can test our RAP Business Object automatically in order to check all important functions at the touch of a button.

01/13/2023

RAP - Draft (Part 2)

Category - ABAP

The second part on the subject of draft handling in RAP objects is about better displaying the draft status at the individual positions in the list.

12/16/2022

RAP - Draft

Category - ABAP

In this article you will learn more about draft handling within a business object and how to implement it on an existing object.

12/09/2022