Skip to Content

Hello Everyone, this blog explains how to create Dynamic Entity type/Entity Set in SAP Gateway. We can easily create an Static entity type using Gateway service builder (SEGW). But sometimes requirements can be tricky where you need to generate Entity model at runtime. Recently, i got a requirement to develop an OData service which could not be fulfilled using static entity model.

The requirement was to create an SAPUI5 application (running on SAP OData) that will have dynamic selection screen. On execution, it should generate a dynamic report based on output fields selected by the user (relevant to the selection screen input fields). Dynamic selection screen part was easily achieved using static entity set. But the real challenge was to send multiple output records as part of odata service response since user can select any number of fields to display in the dynamic report.

The approach which i followed in developing OData service was:

  1. Created a static entity with properties: Field_Name, Data_Element & Table_Name. In GET_ENTITYSET method, exposed all the fields that need to be selected as part of Dynamic report.
  2. When an user selects output fields, application calls POST method of OData service to store relevant properties(Field_Name, Data_Element & Table_Name) in a custom table.
  3. Now, Create an entity with some dummy field inside it. We will change the properties of this entity at run time reading entry from the custom table. MPC_EXT class will be used here.
  4. Once response gets sent successfully, delete the whole custom table entries stored.

 

Steps:

Create a custom table (that will store user selected fields along with data element):

Insert some records for fields in the custom table:

Now, create a project ‘ZDYMANIC_ENTITY’ using t-code SEGW. Create an entity ‘TEST’ with one dummy attribute (VBELN).

Create an entityset ‘TESTSet’ for the entity. Generate runtime artifacts.

To create dynamic properties(fields) inside the entity, Redefine DEFINE method of MPC_EXT class. Create a private instance method ‘DEFINE_TEST’.

Call ‘DEFINE_TEST’ method inside DEFINE method.

DYNAMIC PROPERTIES Creation (MPC_EXT Class):

Inside the method ‘DEFINE_TEST’. Fetch the properties to be created as well as the data element (needed for binding). Loop in above properties and create properties as below:

METHOD define_test.

DATA:
lo_annotation     TYPE REF TO /iwbep/if_mgw_odata_annotation,
lo_entity_type    TYPE REF TO /iwbep/if_mgw_odata_entity_typ,
lo_complex_type   TYPE REF TO /iwbep/if_mgw_odata_cmplx_type,
lo_property       TYPE REF TO /iwbep/if_mgw_odata_property,
lo_entity_set     TYPE REF TO /iwbep/if_mgw_odata_entity_set.

DATA: lt_output TYPE STANDARD TABLE OF ztable_fields_op,
ls_output TYPE ztable_fields_op.
**********************************************************************
*   ENTITY – TEST
**********************************************************************

lo_entity_type = model->create_entity_type( iv_entity_type_name = ‘TEST’ iv_def_entity_set = abap_false ). “#EC NOTEXT

**********************************************************************
*Properties
**********************************************************************

SELECT * FROM ztable_fields_op INTO TABLE lt_output.
IF sy-subrc = 0.
LOOP AT lt_output INTO ls_output.
lo_property = lo_entity_type->create_property( iv_property_name = ls_output- field_label ).
lo_property->set_is_key( ).
lo_property->set_type_edm_string( ).
lo_property->set_nullable( abap_false ).

TRY.
DATA: lv_element TYPE string.
lv_element = ls_output-data_element.

CALL METHOD lo_property->bind_data_element
EXPORTING
iv_element_name = lv_element.

CATCH /iwbep/cx_mgw_med_exception .
ENDTRY.
ENDLOOP.
ENDIF.

**********************************************************************
*   ENTITY SETS
**********************************************************************
lo_entity_set = lo_entity_type->create_entity_set( ‘TESTSet’ ). “#EC NOTEXT

lo_entity_set->set_has_ftxt_search( abap_false ).
lo_entity_set->set_subscribable( abap_false ).
lo_entity_set->set_filter_required( abap_false ).

ENDMETHOD.

POPULATE Records(DPC_EXT Class):

Now, Inside DPC_EXT class, Redefine the method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITYSET to populate records in the dynamic entityset:

  METHOD /iwbep/if_mgw_appl_srv_runtime~get_entityset.

DATA: lt_output TYPE STANDARD TABLE OF ztable_fields_op,
ls_output TYPE ztable_fields_op.

DATA: lt_cat TYPE TABLE OF lvc_s_fcat,
ls_cat LIKE LINE OF lt_cat,
d_ref TYPE REF TO data.

FIELD-SYMBOLS : <f_fs> TYPE table.

IF iv_entity_name = ‘TEST’.

SELECT * FROM ztable_fields_op INTO TABLE lt_output.
IF sy-subrc = 0.

LOOP AT lt_output INTO ls_output.
ls_cat-tabname = ls_output-table_name.
ls_cat-fieldname =  ls_output-field_label.
ls_cat-ref_field = ls_output-field_label.
ls_cat-ref_table = ls_output-table_name.
APPEND ls_cat TO lt_cat.
ENDLOOP.
ENDIF.

“”create a dynamic internal table
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = lt_cat
IMPORTING
ep_table        = d_ref.

ASSIGN d_ref->* TO <f_fs>.

**–Fetch records dynamically
SELECT * FROM (ls_output-table_name)
INTO CORRESPONDING FIELDS OF TABLE <f_fs>.

** Call methos copy_data_to_ref and export entity set data
copy_data_to_ref( EXPORTING is_data = <f_fs>
CHANGING cr_data = er_entityset ).

ENDIF.

ENDMETHOD.

Register the service in the gateway and test the service using Gateway client using URI /sap/opu/odata/sap/ZDYNAMIC_ENTITY_SRV/TESTSet?$format=json:

You can see status code is 200 and multiple records are coming as part of entityset in the response.

Cheers!!

To report this post you need to login first.

11 Comments

You must be Logged on to comment or reply to a post.

  1. Joseph BERTHE

    Hello,

    I have a question, how do you handle the cache? Because as I can know, the define method is called only when the cache is invalidated.

    Regards,

    Joseph

    (0) 
    1. Pranay Patel Post author

      Hello Joseph,

      ‘Define’ method is used to generate metadata of the odata service. You can have a look at the code in the method (MPC class) in any Gateway project, you’ll get a better understanding.

      Regards,

      Pranay Patel

      (0) 
      1. Joseph BERTHE

        Hi,

        I understand what you did in the MPC, but what I want to say is, all the methods from MPC are executed only once when the model cache is empty/cleared. When the cache is full fill, then the define method is not executed anymore.

        So if I’m rigth, you can only have a dynamic data model if you clear the cache for each call.

        If it’s works, i’m verry surprise and I should test it.

        Regards,

        Joseph

        (2) 
        1. Manuel Hofmann

          Hello,

          you are absolutely right. Metadata cache will not update once it has been generated. I imagine the table to store the dynamic fields could be a customizing table. The metadata cache in gateway and backend (assuming a hub scenarioa) will not be updated if a new customizing transport has been transported to target system. In development this is not a problem because it is recommended to deactivate caching, so it will be generated again.

          One way to do it however to redefine method GET_LAST_MODIFIED. However author didnt mention it  and i would not recommend it.

          I also disagree with the authors statement to not be able to fulfill the requirement with a static model. It is possible i have done it myself. You only need to have a static entity type which represents the “Fields”. This entity set can then be filled during runtime. With deep entity you can also send those fields again back to backend and do whatever you want.

          (3) 
          1. Pranay Patel Post author

            Hi Manuel,

            Thanks for your inputs. To handle Metadata cache issue, we can redefine method GET_LAST_MODIFIED. I missed that point in the blog.

            However, i don’t agree with your statement that you can achieve it using static entity. Since you are never certain about what fields are going to be selected by the user to display in the report, how can you make an static entity with those fields. And different users can select fields of their choice in the output.

            And another reason going for dynamic entity is that there can be N number of field choices (which an user can select for output), you don’t want to overburden your entity with 100 fields inside it.

            Regards.

             

            (0) 
            1. Former Member

              Hello Pranay,

              Thanks for this article. I have created a dynamic metadata on similar lines ..however, i am not able to clear the cache issue . Can you please tell about the usage of get_last_modified method in this context.

              (0) 
  2. Frederik Devinck

    Hi,

    I’ve faced a similar development, and we were looking into this solution.

    Cache may be one facet, but how do you handle sorting/filtering on the (dynamic) EntitySet?

    (0) 
    1. Pranay Patel Post author

      Hi Frederik,

      /IWBEP/IF_MGW_APPL_SRV_RUNTIME~GET_ENTITYSET method has all the importing paramters which you can find in normal GET method of an entityset. You can handle filter/sort in the same way as you do in normal scenario.

      (0) 
  3. Former Member

    HI Pranay,

     

    Very Nice article,it really makes a new learner understand how to go for a Dynamic entity set if at all required in our projects.

     

    Thanks.

    (1) 
  4. Former Member

    Hi Pranay,

    Very nice Post, thanks for sharing.

    At first glance I do not see how can I change the attributes dynamically,I mean

    Let suppose that I perform a scenario to read some vbak data, just like you shown , until here it’s OK, and right after I perform the same method TESTSet but I wanna to load some data from KNA1, here is the trick to me, is it possible to handle by using DEFINE method?.

    How to do it ( the logic ) is clear to me but I have no parameters on DEFINE method, then my question is how to make it realy dinamically?

    Regards,

     

    (0) 

Leave a Reply