Call a class method from ABAP CDS View?

12.9k views Asked by At

I would like to call a method from a class in an existing CDS view to get certain data, which can only be called by this method. So I want to call a method from a CDS View.

What is the easiest way to do this?

I would be very happy about an example with code.

2

There are 2 answers

0
Oguz On

NOTE: Your abap logic will only be executed when the CDS view is consumed by something that handles annotations i.e. exposed as an Odata service, but not in transaction SE16N or the preview in Eclipse. There two ways actually. First option:

@AbapCatalog.sqlViewName: 'ZV_TEST_ABAP'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'ABAP code in cds'
@OData.publish: true
define view YCDS_WITH_ABAP as select from sflight
{

  //sflight
  key carrid,
  key connid,
  key fldate,
      seatsocc_f,
      @ObjectModel.readOnly: true
      @ObjectModel.virtualElement: true 
      @ObjectModel.virtualElementCalculatedBy: 'ABAP:YCL_CDS_FUNCTION' //ycl_cds_function 
      cast( '' as abap.char(255)) as text
    
}where connid = '0017'

Your abap class:

CLASS ycl_cds_function DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC .



  PUBLIC SECTION.
    INTERFACES: if_sadl_exit_calc_element_read.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.



CLASS ycl_cds_function IMPLEMENTATION.

 METHOD if_sadl_exit_calc_element_read~calculate.

    DATA:
      lt_calculated_data TYPE STANDARD TABLE OF ZV_TEST_ABAP .

    " it_original_data -> data that comes from cds
    " lt_calculated_data -> data that you will manipulate
    MOVE-CORRESPONDING it_original_data TO lt_calculated_data.

    " do your extra logic and append/update your cds view data
    LOOP AT lt_calculated_data ASSIGNING FIELD-SYMBOL(<fs_data>).
        <fs_data>-text = 'hello from abap!'.
    ENDLOOP.

    MOVE-CORRESPONDING lt_calculated_data TO ct_calculated_data.

  ENDMETHOD.

  METHOD if_sadl_exit_calc_element_read~get_calculation_info.

  ENDMETHOD.

ENDCLASS.

View in eclipse: enter image description here View in odata:

  ...,{
                "__metadata": {
                    "id": "lalala')",
                    "uri": "blablabla')",
                    "type": "YCDS_WITH_ABAP_CDS.YCDS_WITH_ABAPType"
                },
                "carrid": "AA",
                "connid": "0017",
                "fldate": "/Date(1535068800000)/",
                "seatsocc_f": 20,
                "text": "hello from abap!"
   },...

Second option:

The second way is to change your service's DPC class with your custom class, which inherits this standard class and do your custom logic in those redefined methods. Personally, I would go with the second option. I haven't tried it but I have a feeling that performance would be better. :)

enter image description here

For more info please check: https://blogs.sap.com/2020/05/11/abap-code-exits-in-cds-views/

0
Florian On

While @Oguz answer is worth knowing from an OData perspective, there is also a pure CDS solution that works in every component that selects from CDS views, independent on whether they support annotations or not.

First, you specify a CDS view as a SELECT FROM <table function>:

@AbapCatalog.sqlViewName: 'MYCDSVIEW'
define view MY_CDS_VIEW as select from MY_TABLE_FUNCTION {    
    A,
    B
}

Then you define a table function. Table functions are like CDS view, only that their execution logic is implemented in ABAP, not in SQL Script:

define table function MY_TABLE_FUNCTION
returns
{
  A : some_type;
  B : some_type;
}
implemented by method
  cl_my_table_function=>provide_data_for_tf_test;

Finally, you provide the ABAP class that implements the table function:

CLASS cl_my_table_function DEFINITION
    PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_amdp_marker_hdb.
    CLASS-METHODS provide_data FOR TABLE FUNCTION MY_TABLE_FUNCTION.
ENDCLASS.

CLASS cl_my_table_function IMPLEMENTATION.

  METHOD provide_data 
    BY DATABASE FUNCTION FOR HDB LANGUAGE SQLSCRIPT
    USING some_table.

    RETURN
      SELECT A, B
       FROM some_table;

  ENDMETHOD.

ENDCLASS.

When you do something like this, spare some extra time to test the client handling. This combination of ways often brings down the automatic client additions ABAPers know from the SELECT statement and regular CDS views. There is a chance that you will need annotations like @ClientHandling: { type: #CLIENT_DEPENDENT } on the involved CDS views and have the table function provide the CLIENT or MANDT columns explicitly.