Skip to Content
Technical Articles

How to generate the DDL source code for custom entities that are implemented by remote function calls

Introduction

SAP CP ABAP environment can serve as a platform to built side-by-side extensions for:

  • SAP S/4HANA Cloud via OData
  • SAP S/4HANA (on-Premises) via OData and RFC
  • SAP Business Suite (on-Premises) via OData (using SAP Gateway) and RFC

To implement such scenarios the ABAP Restful Programming Model offers the option to built CDS views as custom entities.

Using the Annotation @QueryImplementedBy a class is specified that implements the select method of the interface if_a4c_rap_query_provider.

Rather than querying the data from database tables or other CDS views the developer can retrieve the data via OData or RFC calls. In SAP CP ABAP Environment these are remote calls to one of the system types mentioned above.

For an example that uses OData calls see the SAP Online Documentation:

https://help.sap.com/viewer/c0d02c4330c34b3abca88bdd57eaccfc/Cloud/en-US/6a064c09c508435a81357898e8e65d06.html

Blog series

This blog is part of a blog series about developing a side-by-side Extension for on-premise SAP Systems in SAP Cloud Platform ABAP Environment using RFC communication

The challenge

As I wrote in a previous blog How to call a remote function module in your on-premise SAP system from SAP Cloud Platform – ABAP Environment it is now possible to call RFC function modules in an SAP on-premise system from SAP CP ABAP environment.

The problem that a developer faces is however that the SAP CP ABAP environment is an “empty” platform.

Opposed to a SAP Business Suite or SAP S/4HANA System the structures of table or input parameters of BAPI’s are not available.

On the other hand RFC function modules must be called with appropriate structures or internal tables as importing or tables parameters.

The solution

I developed a small class zcl_rfc_custom_entity_helper that you can run in your development system that generates the appropriate DDL source code for a custom entity as well as ABAP source Code for a type defintion based on the basic data Elements available in SAP CP ABAP environment.

I used the following documents from the SAP Online Help.

ABAP DDIC types
https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenddic_builtin_types.htm
ABAP CDS types
https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abencds_typing.htm

Please note:

If you use the report you have to replace the value ‘bapi_epm_product_header’ for the variable lv_rfc_input_structure by the name of the DDIC structure you are interested in.

The output for the DDIC struture BAPI_EPM_PRODUCT_HEADER which is used by the BAPI BAPI_EPM_PRODUCT_GET_LIST is the following:

//######################### DDL source code ################################
// DDL source code for custom entity for BAPI_EPM_PRODUCT_HEADER
// generated on: 20190301 at: 140243 in: UIA 
ProductId : abap.char( 10 ) ; 
TypeCode : abap.char( 2 ) ; 
Category : abap.sstring( 40 ) ; 
Name : abap.sstring( 255 ) ; 
Description : abap.sstring( 255 ) ; 
SupplierId : abap.char( 10 ) ; 
SupplierName : abap.sstring( 80 ) ; 
TaxTarifCode : abap.int1 ; 
@Semantics.unitOfMeasure: true
MeasureUnit : abap.unit( 3 ) ; 
@Semantics.quantity.unitOfMeasure: 'WeightUnit' 
WeightMeasure : abap.quan( 13, 3 ) ; 
@Semantics.unitOfMeasure: true
WeightUnit : abap.unit( 3 ) ; 
Price : abap.dec( 23, 4 ) ; 
@Semantics.currencyCode: true
CurrencyCode : abap.cuky( 5 ) ; 
@Semantics.quantity.unitOfMeasure: 'DimUnit' 
Width : abap.quan( 13, 3 ) ; 
@Semantics.quantity.unitOfMeasure: 'DimUnit' 
Depth : abap.quan( 13, 3 ) ; 
@Semantics.quantity.unitOfMeasure: 'DimUnit' 
Height : abap.quan( 13, 3 ) ; 
@Semantics.unitOfMeasure: true
DimUnit : abap.unit( 3 ) ; 
ProductPicUrl : abap.char( 255 ) ; 

 

"######################### ABAP source code ################################
" ABAP source code for type definition for BAPI_EPM_PRODUCT_HEADER
" generated on: 20190301 at: 140243 in: UIA 
TYPES : BEGIN OF ty_BAPI_EPM_PRODUCT_HEADER, 
ProductId TYPE c LENGTH 10, 
TypeCode TYPE c LENGTH 2, 
Category TYPE c LENGTH 40, 
Name TYPE c LENGTH 255, 
Description TYPE c LENGTH 255, 
SupplierId TYPE c LENGTH 10, 
SupplierName TYPE c LENGTH 80, 
TaxTarifCode TYPE int1 , 
MeasureUnit TYPE c LENGTH 3, 
WeightMeasure TYPE p LENGTH 7 DECIMALS 3, 
WeightUnit TYPE c LENGTH 3, 
Price TYPE p LENGTH 12 DECIMALS 4 , 
CurrencyCode TYPE c LENGTH 5, 
Width TYPE p LENGTH 7 DECIMALS 3, 
Depth TYPE p LENGTH 7 DECIMALS 3, 
Height TYPE p LENGTH 7 DECIMALS 3, 
DimUnit TYPE c LENGTH 3, 
ProductPicUrl TYPE c LENGTH 255, 
end OF ty_BAPI_EPM_PRODUCT_HEADER. 

Source code

The source code of this class will be published on GitHub soon.

CLASS zcl_rfc_custom_entity_helper DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .

  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.



CLASS zcl_rfc_custom_entity_helper IMPLEMENTATION.

  METHOD if_oo_adt_classrun~main.


***************************************************************************************
* ABAP DDIC types
* https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenddic_builtin_types.htm
***************************************************************************************
* ABAP CDS types
* https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abencds_typing.htm
***************************************************************************************
    DATA:
      lo_struct_desc           TYPE REF TO cl_abap_structdescr,
      lo_type_desc             TYPE REF TO cl_abap_typedescr,
      lo_elem_desc             TYPE REF TO cl_abap_elemdescr,
      lt_comp_table            TYPE cl_abap_structdescr=>component_table,
      lv_length                TYPE i,
      lv_p_length              TYPE i,
      lv_decimals              TYPE i,
      lv_abap_cds_data_type    TYPE abap_typename,
      lv_abap_ddic_data_type   TYPE string,
      lv_property              TYPE string,
      ls_ddic_fields           TYPE dfies,
      lv_ddl_source_code_line  TYPE string,
      lt_ddl_source_code       TYPE STANDARD TABLE OF string,
      lv_abap_source_code_line TYPE string,
      lt_abap_source_code      TYPE STANDARD TABLE OF string,
      lv_reffield_abap         TYPE dd03l-reffield,
      lv_refproperty           TYPE string.

    DATA: lv_rfc_input_structure TYPE string VALUE 'bapi_epm_product_header'.

    "name of structure must be in uppercase because otherwise reference fields for currency and unit
    "are not found in DD03L
    lv_rfc_input_structure = to_upper( lv_rfc_input_structure ).

    lo_type_desc =  cl_abap_typedescr=>describe_by_name( lv_rfc_input_structure ).

    "check that the object is a structure
    TRY.
        IF lo_type_desc->kind = lo_type_desc->kind_struct.
          lo_struct_desc ?= lo_type_desc.
          "this method retrieves the components also from structures with append structures
          /iwbep/cl_mgw_med_model_util=>get_structure_components(
            EXPORTING
              io_structure_descriptor = lo_struct_desc
            CHANGING
              ct_components = lt_comp_table ).
        ELSE.
          "@todo: raise a more meaningful exception here
          RAISE EXCEPTION TYPE /iwbep/cx_mgw_med_exception
            EXPORTING
              textid = /iwbep/cx_mgw_med_exception=>otr_text_read_error.
        ENDIF.

      CATCH /iwbep/cx_mgw_med_exception.
        "handle exception
        EXIT.
    ENDTRY.

    "add a comment that contains the name of the structure being used as input
    lv_ddl_source_code_line = |// DDL source code for custom entity for { lv_rfc_input_structure }|.
    lv_abap_source_code_line = |" ABAP source code for type definition for { lv_rfc_input_structure }|.
    APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
    APPEND lv_abap_source_code_line TO lt_abap_source_code.
    "add a comment that contains information when and where the code has been generated
    lv_ddl_source_code_line = |// generated on: { sy-datum } at: { sy-uzeit } in: { sy-sysid } |.
    lv_abap_source_code_line = |" generated on: { sy-datum } at: { sy-uzeit } in: { sy-sysid } |.
    APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
    APPEND lv_abap_source_code_line TO lt_abap_source_code.

    "first line of TYPES statement
    lv_abap_source_code_line = |TYPES : BEGIN OF ty_{ lv_rfc_input_structure }, | .
    APPEND lv_abap_source_code_line TO lt_abap_source_code.

    LOOP AT lt_comp_table INTO DATA(ls_comp_table)  .

      "only elements
      IF ls_comp_table-type->kind <> cl_abap_typedescr=>kind_elem.
        CONTINUE.
      ENDIF.

      lo_elem_desc  ?= ls_comp_table-type.

      lo_elem_desc->get_ddic_field(
          EXPORTING
              p_langu      = sy-langu
          RECEIVING
              p_flddescr   = ls_ddic_fields
          EXCEPTIONS
              not_found    = 1
              no_ddic_type = 2
              OTHERS       = 3
              ).


      lv_property = to_mixed( val = ls_comp_table-name sep = '_' ).
      lv_length = ls_ddic_fields-leng.
      lv_p_length = lv_length DIV 2 + 1.
      lv_decimals = ls_ddic_fields-decimals.

      "add the ABAP field name of the structure as a comment
      "lv_ddl_source_code_line = |// { ls_comp_table-name } |.
      "APPEND lv_ddl_source_code_line TO lt_ddl_source_code.

      "first check for the domain name
      CASE ls_ddic_fields-domname.

        WHEN 'TZNTSTMPL' OR 'TZNTSTMPSL' OR 'TZNTSTMPS' OR 'TIMESTAMP_CHAR'.
          lv_ddl_source_code_line  = |{ lv_property } : timestampl; | .
          lv_abap_source_code_line = |{ lv_property } TYPE timestampl , | .
        WHEN 'TZNTIMELOC'.
          lv_abap_cds_data_type = 'tims'.
          lv_abap_ddic_data_type = ls_ddic_fields-domname.
          lv_ddl_source_code_line = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
          lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
        WHEN OTHERS.

          "if none of the obvious domain names is found check the data type
          CASE ls_ddic_fields-datatype.

            WHEN 'CHAR'.
              "if char is used sap.displayformat = uppercase is enforced
              IF ls_ddic_fields-lowercase = abap_true.
                lv_abap_cds_data_type = 'sstring'.
                lv_abap_ddic_data_type = 'c'.
              ELSE.
                lv_abap_cds_data_type = 'char'.
                lv_abap_ddic_data_type = 'c'.
              ENDIF.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_length }, | .
            WHEN 'CLNT'.
              lv_abap_cds_data_type = 'clnt'.
              lv_abap_ddic_data_type = 'c'.
              lv_p_length = 3.
              lv_ddl_source_code_line = |//{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length }, | .
            WHEN  'CUKY'.
              lv_ddl_source_code_line = '@Semantics.currencyCode: true'.
              APPEND lv_ddl_source_code_line TO lt_ddl_source_code.

              lv_abap_cds_data_type = 'cuky'.
              lv_abap_ddic_data_type = 'c'.
              lv_p_length = 5.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length }, | .
            WHEN  'CURR'.
              SELECT SINGLE reffield INTO lv_reffield_abap FROM dd03l WHERE tabname = lv_rfc_input_structure AND fieldname = ls_comp_table-name.
              IF lv_reffield_abap IS NOT INITIAL.
                lv_refproperty = to_mixed( val = lv_reffield_abap sep = '_' ).
              ELSE.
                lv_refproperty = '<enter property name>'.
              ENDIF.
              lv_ddl_source_code_line = |@Semantics.amount.currencyCode: '{ lv_refproperty }' |.
              APPEND lv_ddl_source_code_line TO lt_ddl_source_code.

              lv_abap_cds_data_type = 'curr'.
              lv_abap_ddic_data_type = 'p'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length }, { lv_decimals } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length } DECIMALS { lv_decimals } , | .

            WHEN  'DATS' .
              lv_abap_cds_data_type = 'dats'.
              lv_abap_ddic_data_type = 'dats'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'DEC'.
              lv_abap_cds_data_type = 'dec'.
              lv_abap_ddic_data_type = 'p'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length }, { lv_decimals } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length } DECIMALS { lv_decimals } , | .
            WHEN  'FLTP'.
              lv_abap_cds_data_type = 'fltp'.
              lv_abap_ddic_data_type = 'f'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'INT1'.
              lv_abap_cds_data_type = 'int1'.
              lv_abap_ddic_data_type = 'int1'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'INT2'.
              lv_abap_cds_data_type = 'int2'.
              lv_abap_ddic_data_type = 's'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'INT4'.
              lv_abap_cds_data_type = 'int4'.
              lv_abap_ddic_data_type = 'i'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'INT8'.
              lv_abap_cds_data_type = 'int8'.
              lv_abap_ddic_data_type = 'int8'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'NUMC'.
              lv_abap_cds_data_type = 'numc'.
              lv_abap_ddic_data_type = 'n'.
              lv_ddl_source_code_line = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_length }, | .
            WHEN  'QUAN'.
              SELECT SINGLE reffield INTO lv_reffield_abap FROM dd03l WHERE tabname = lv_rfc_input_structure AND fieldname = ls_comp_table-name.
              IF lv_reffield_abap IS NOT INITIAL.
                lv_refproperty = to_mixed( val = lv_reffield_abap sep = '_' ).
              ELSE.
                lv_refproperty = '<enter property name>'.
              ENDIF.
              lv_ddl_source_code_line = |@Semantics.quantity.unitOfMeasure: '{ lv_refproperty }' |.
              APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
              lv_abap_cds_data_type = 'quan'.
              lv_abap_ddic_data_type = 'p'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length }, { lv_decimals } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length } DECIMALS { lv_decimals }, | .
            WHEN  'STRG'.
              lv_abap_cds_data_type = 'string'.
              lv_abap_ddic_data_type = 'string'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'DATS' .
              lv_abap_cds_data_type = 'dats'.
              lv_abap_ddic_data_type = 'd'.
              lv_ddl_source_code_line = |{ lv_property } : timestampl; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN 'TIMS'.
              lv_abap_cds_data_type = 'tims'.
              lv_abap_ddic_data_type = 't'.
              lv_ddl_source_code_line = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN  'UNIT'.
              lv_ddl_source_code_line = '@Semantics.unitOfMeasure: true'.
              APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
              lv_abap_cds_data_type = 'unit'.
              lv_abap_ddic_data_type = 'c'.
              lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
              lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_length }, | .
            WHEN OTHERS.
              lv_ddl_source_code_line  = |// { ls_comp_table-name } could not be mapped to a standard data element.|.
              lv_abap_source_code_line = |" { ls_comp_table-name } could not be mapped to a standard data element.|.

          ENDCASE.

      ENDCASE.

      APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
      APPEND lv_abap_source_code_line TO lt_abap_source_code.

    ENDLOOP.

    "last line of TYPES statement
    lv_abap_source_code_line = |end OF ty_{ lv_rfc_input_structure }. | .
    APPEND lv_abap_source_code_line TO lt_abap_source_code.

    out->write( |//######################### DDL source code ################################| ).

    LOOP AT lt_ddl_source_code INTO lv_ddl_source_code_line.
      out->write( lv_ddl_source_code_line ).
    ENDLOOP.

    out->write( |"######################### ABAP source code ################################| ).

    LOOP AT lt_abap_source_code INTO lv_abap_source_code_line.
      out->write( lv_abap_source_code_line ).
    ENDLOOP.

  ENDMETHOD.

ENDCLASS.

 

4 Comments
You must be Logged on to comment or reply to a post.
  • Thanks for this great series, very useful step-by-step guide.

    To get the same information from an on premise SAP ERP system I had to make some adaptations. I made some minor changes so that I could do everything from the ABAP Cloud system by calling the code through RFC using an adaption of your RFC code from the first article in your series. I’ve attached my code.

     

    Class to execute RFC

    class Z_CL_RFC_CUSTOM_ENTITY_HELPER definition
      public
      final
      create public .
    
    public section.
    interfaces if_oo_adt_classrun.
    protected section.
    private section.
    ENDCLASS.
    
    
    CLASS Z_CL_RFC_CUSTOM_ENTITY_HELPER IMPLEMENTATION.
    
    METHOD IF_OO_ADT_CLASSRUN~MAIN.
    
    DATA: lv_ddl_source TYPE string,
          lv_abap_source TYPE string.
    
    TRY.
    
    DATA(lo_rfc_dest) = cl_rfc_destination_provider=>create_by_cloud_destination(
                                   i_name = |S4H_ON_PREM_RFC|
                                   i_service_instance_name = |OutboundCommunication| ).
    DATA(lv_rfc_dest) = lo_rfc_dest->get_destination_name( ).
    
    CALL FUNCTION 'Z_RFC_CUSTOM_ENTITY_HELPER' DESTINATION lv_rfc_dest
       EXPORTING
             IM_RFC_INPUT_STRUCTURE = 'bapi_epm_product_header'
    
       IMPORTING
             EX_DDL_SOURCE    = lv_ddl_source
             EX_ABAP_SOURCE   = lv_abap_source
       EXCEPTIONS
             entity_not_found = 1
             OTHERS           = 2.
    
    CASE sy-subrc.
              WHEN 0.
                out->write( |DDL Source: { lv_ddl_source  }.| ).
                out->write( |ABAP Source: { lv_abap_source  }.| ).
              WHEN 1.
                out->write( |EXCEPTION ENITY_NOT_FOUND| ).
              WHEN 2.
                out->write( |EXCEPTION OTHERS| ).
            ENDCASE.
    
          CATCH cx_root INTO DATA(lx_root).
            out->write( lx_root->get_text( ) ).
        ENDTRY.
    
      ENDMETHOD.
    
    ENDCLASS.

     

    Function module in on prem system (remote enabled, with exception ENTITY_NOT_FOUND)

    FUNCTION Z_RFC_CUSTOM_ENTITY_HELPER
      IMPORTING
        VALUE(IM_RFC_INPUT_STRUCTURE) TYPE STRING
      EXPORTING
        VALUE(EX_DDL_SOURCE) TYPE STRING
        VALUE(EX_ABAP_SOURCE) TYPE STRING
      EXCEPTIONS
        ENTITY_NOT_FOUND.
    
    
    
    ***************************************************************************************
    * ABAP DDIC types
    * https://help.sap.com/doc/abapdocu_751_index_htm/7.51/en-US/abenddic_builtin_types.htm
    ***************************************************************************************
    * ABAP CDS types
    * https://help.sap.com/doc/abapdocu_750_index_htm/7.50/en-US/abencds_typing.htm
    ***************************************************************************************
        DATA:
          lo_struct_desc           TYPE REF TO cl_abap_structdescr,
          lo_type_desc             TYPE REF TO cl_abap_typedescr,
          lo_elem_desc             TYPE REF TO cl_abap_elemdescr,
          lt_comp_table            TYPE cl_abap_structdescr=>component_table,
          lv_length                TYPE i,
          lv_p_length              TYPE i,
          lv_decimals              TYPE i,
          lv_abap_cds_data_type    TYPE abap_typename,
          lv_abap_ddic_data_type   TYPE string,
          lv_property              TYPE string,
          ls_ddic_fields           TYPE dfies,
          lv_ddl_source_code_line  TYPE string,
          lt_ddl_source_code       TYPE STANDARD TABLE OF string,
          lv_abap_source_code_line TYPE string,
          lt_abap_source_code      TYPE STANDARD TABLE OF string,
          lv_reffield_abap         TYPE dd03l-reffield,
          lv_refproperty           TYPE string,
          cr_lf(2)                 TYPE c VALUE cl_abap_char_utilities=>cr_lf.
    
    *    DATA: lv_rfc_input_structure TYPE string VALUE 'bapi_epm_product_header'.
        DATA: lv_rfc_input_structure TYPE string.
        lv_rfc_input_structure = IM_RFC_INPUT_STRUCTURE.
        "name of structure must be in uppercase because otherwise reference fields for currency and unit
        "are not found in DD03L
        lv_rfc_input_structure = to_upper( lv_rfc_input_structure ).
    
        lo_type_desc =  cl_abap_typedescr=>describe_by_name( lv_rfc_input_structure ).
    
        "check that the object is a structure
        TRY.
            IF lo_type_desc->kind = lo_type_desc->kind_struct.
              lo_struct_desc ?= lo_type_desc.
              "this method retrieves the components also from structures with append structures
              /iwbep/cl_mgw_med_model_util=>get_structure_components(
                EXPORTING
                  io_structure_descriptor = lo_struct_desc
                CHANGING
                  ct_components = lt_comp_table ).
            ELSE.
              "@todo: raise a more meaningful exception here
    *          RAISE EXCEPTION TYPE /iwbep/cx_mgw_med_exception
    *            EXPORTING
    *              textid = /iwbep/cx_mgw_med_exception=>ddic_element_not_found.
              RAISE entity_not_found.
            ENDIF.
    
          CATCH /iwbep/cx_mgw_med_exception.
            "handle exception
            RAISE entity_not_found.
    *        EXIT.
        ENDTRY.
    
        "add a comment that contains the name of the structure being used as input
        lv_ddl_source_code_line = |// DDL source code for custom entity for { lv_rfc_input_structure }|.
        lv_abap_source_code_line = |" ABAP source code for type definition for { lv_rfc_input_structure }|.
        APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
        APPEND lv_abap_source_code_line TO lt_abap_source_code.
        "add a comment that contains information when and where the code has been generated
        lv_ddl_source_code_line = |// generated on: { sy-datum } at: { sy-uzeit } in: { sy-sysid } |.
        lv_abap_source_code_line = |" generated on: { sy-datum } at: { sy-uzeit } in: { sy-sysid } |.
        APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
        APPEND lv_abap_source_code_line TO lt_abap_source_code.
    
        "first line of TYPES statement
        lv_abap_source_code_line = |TYPES : BEGIN OF ty_{ lv_rfc_input_structure }, | .
        APPEND lv_abap_source_code_line TO lt_abap_source_code.
    
        LOOP AT lt_comp_table INTO DATA(ls_comp_table)  .
    
          "only elements
          IF ls_comp_table-type->kind <> cl_abap_typedescr=>kind_elem.
            CONTINUE.
          ENDIF.
    
          lo_elem_desc  ?= ls_comp_table-type.
    
          lo_elem_desc->get_ddic_field(
              EXPORTING
                  p_langu      = sy-langu
              RECEIVING
                  p_flddescr   = ls_ddic_fields
              EXCEPTIONS
                  not_found    = 1
                  no_ddic_type = 2
                  OTHERS       = 3
                  ).
    
    
          lv_property = to_mixed( val = ls_comp_table-name sep = '_' ).
          lv_length = ls_ddic_fields-leng.
          lv_p_length = lv_length DIV 2 + 1.
          lv_decimals = ls_ddic_fields-decimals.
    
          "add the ABAP field name of the structure as a comment
          "lv_ddl_source_code_line = |// { ls_comp_table-name } |.
          "APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
    
          "first check for the domain name
          CASE ls_ddic_fields-domname.
    
            WHEN 'TZNTSTMPL' OR 'TZNTSTMPSL' OR 'TZNTSTMPS' OR 'TIMESTAMP_CHAR'.
              lv_ddl_source_code_line  = |{ lv_property } : timestampl; | .
              lv_abap_source_code_line = |{ lv_property } TYPE timestampl , | .
            WHEN 'TZNTIMELOC'.
              lv_abap_cds_data_type = 'tims'.
              lv_abap_ddic_data_type = ls_ddic_fields-domname.
              lv_ddl_source_code_line = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
              lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
            WHEN OTHERS.
    
              "if none of the obvious domain names is found check the data type
              CASE ls_ddic_fields-datatype.
    
                WHEN 'CHAR'.
                  "if char is used sap.displayformat = uppercase is enforced
                  IF ls_ddic_fields-lowercase = abap_true.
                    lv_abap_cds_data_type = 'sstring'.
                    lv_abap_ddic_data_type = 'c'.
                  ELSE.
                    lv_abap_cds_data_type = 'char'.
                    lv_abap_ddic_data_type = 'c'.
                  ENDIF.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_length }, | .
                WHEN 'CLNT'.
                  lv_abap_cds_data_type = 'clnt'.
                  lv_abap_ddic_data_type = 'c'.
                  lv_p_length = 3.
                  lv_ddl_source_code_line = |//{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length }, | .
                WHEN  'CUKY'.
                  lv_ddl_source_code_line = '@Semantics.currencyCode: true'.
                  APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
    
                  lv_abap_cds_data_type = 'cuky'.
                  lv_abap_ddic_data_type = 'c'.
                  lv_p_length = 5.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length }, | .
                WHEN  'CURR'.
                  SELECT SINGLE reffield INTO lv_reffield_abap FROM dd03l WHERE tabname = lv_rfc_input_structure AND fieldname = ls_comp_table-name.
                  IF lv_reffield_abap IS NOT INITIAL.
                    lv_refproperty = to_mixed( val = lv_reffield_abap sep = '_' ).
                  ELSE.
                    lv_refproperty = '<enter property name>'.
                  ENDIF.
                  lv_ddl_source_code_line = |@Semantics.amount.currencyCode: '{ lv_refproperty }' |.
                  APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
    
                  lv_abap_cds_data_type = 'curr'.
                  lv_abap_ddic_data_type = 'p'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length }, { lv_decimals } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length } DECIMALS { lv_decimals } , | .
    
                WHEN  'DATS' .
                  lv_abap_cds_data_type = 'dats'.
                  lv_abap_ddic_data_type = 'dats'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'DEC'.
                  lv_abap_cds_data_type = 'dec'.
                  lv_abap_ddic_data_type = 'p'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length }, { lv_decimals } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length } DECIMALS { lv_decimals } , | .
                WHEN  'FLTP'.
                  lv_abap_cds_data_type = 'fltp'.
                  lv_abap_ddic_data_type = 'f'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'INT1'.
                  lv_abap_cds_data_type = 'int1'.
                  lv_abap_ddic_data_type = 'int1'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'INT2'.
                  lv_abap_cds_data_type = 'int2'.
                  lv_abap_ddic_data_type = 's'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'INT4'.
                  lv_abap_cds_data_type = 'int4'.
                  lv_abap_ddic_data_type = 'i'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'INT8'.
                  lv_abap_cds_data_type = 'int8'.
                  lv_abap_ddic_data_type = 'int8'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'NUMC'.
                  lv_abap_cds_data_type = 'numc'.
                  lv_abap_ddic_data_type = 'n'.
                  lv_ddl_source_code_line = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_length }, | .
                WHEN  'QUAN'.
                  SELECT SINGLE reffield INTO lv_reffield_abap FROM dd03l WHERE tabname = lv_rfc_input_structure AND fieldname = ls_comp_table-name.
                  IF lv_reffield_abap IS NOT INITIAL.
                    lv_refproperty = to_mixed( val = lv_reffield_abap sep = '_' ).
                  ELSE.
                    lv_refproperty = '<enter property name>'.
                  ENDIF.
                  lv_ddl_source_code_line = |@Semantics.quantity.unitOfMeasure: '{ lv_refproperty }' |.
                  APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
                  lv_abap_cds_data_type = 'quan'.
                  lv_abap_ddic_data_type = 'p'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length }, { lv_decimals } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_p_length } DECIMALS { lv_decimals }, | .
                WHEN  'STRG'.
                  lv_abap_cds_data_type = 'string'.
                  lv_abap_ddic_data_type = 'string'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'DATS' .
                  lv_abap_cds_data_type = 'dats'.
                  lv_abap_ddic_data_type = 'd'.
                  lv_ddl_source_code_line = |{ lv_property } : timestampl; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN 'TIMS'.
                  lv_abap_cds_data_type = 'tims'.
                  lv_abap_ddic_data_type = 't'.
                  lv_ddl_source_code_line = |{ lv_property } : abap.{ lv_abap_cds_data_type } ; | .
                  lv_abap_source_code_line = |{ lv_property }   TYPE { lv_abap_ddic_data_type } , | .
                WHEN  'UNIT'.
                  lv_ddl_source_code_line = '@Semantics.unitOfMeasure: true'.
                  APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
                  lv_abap_cds_data_type = 'unit'.
                  lv_abap_ddic_data_type = 'c'.
                  lv_ddl_source_code_line  = |{ lv_property } : abap.{ lv_abap_cds_data_type }( { lv_length } ) ; | .
                  lv_abap_source_code_line = |{ lv_property }  TYPE { lv_abap_ddic_data_type } LENGTH { lv_length }, | .
                WHEN OTHERS.
                  lv_ddl_source_code_line  = |// { ls_comp_table-name } could not be mapped to a standard data element.|.
                  lv_abap_source_code_line = |" { ls_comp_table-name } could not be mapped to a standard data element.|.
    
              ENDCASE.
    
          ENDCASE.
    
          APPEND lv_ddl_source_code_line TO lt_ddl_source_code.
          APPEND lv_abap_source_code_line TO lt_abap_source_code.
    
        ENDLOOP.
    
        "last line of TYPES statement
        lv_abap_source_code_line = |end OF ty_{ lv_rfc_input_structure }. | .
        APPEND lv_abap_source_code_line TO lt_abap_source_code.
    
    *    write / |//######################### DDL source code ################################| .
        ex_ddl_source = |//######################### DDL source code ################################\n| .
    
    
        LOOP AT lt_ddl_source_code INTO lv_ddl_source_code_line.
    *      write /  lv_ddl_source_code_line .
          CONCATENATE ex_ddl_source lv_ddl_source_code_line INTO ex_ddl_source SEPARATED BY cr_lf.
    
        ENDLOOP.
    
    *    write / |"######################### ABAP source code ################################| .
        ex_abap_source = |######################### ABAP source code ################################\n| .
    
        LOOP AT lt_abap_source_code INTO lv_abap_source_code_line.
    *      write / lv_abap_source_code_line .
     CONCATENATE ex_abap_source lv_abap_source_code_line INTO ex_abap_source SEPARATED BY cr_lf.
    
        ENDLOOP.
    
    
    ENDFUNCTION.

     

     

  • Hi AndreFisher and Marc Van Driel

    Thanks, This is be very useful. Tried using this and worked fine for me.

    I am able to convert a structure in Onpremise to ABAP environment basic datatypes  in Eclipse using RFC.