Enhancing RAP Performance : The Impact of Virtual Elements on Key Metrics

Estimated read time 14 min read

Virtual elements and  Performance :

What are Virtual Elements? 

A virtual element is typically used in CDS views to derive calculated fields dynamically without storing them in the database.
Suppose if we want to use any ABAP resources that would get more info for us Such as any informative fields or any function modules needed to be included in cds  
We go for virtual element 

Virtual Elements, those little pieces of code that are helpful to calculate certain things and add certain fields during runtime. . 
Anyway, there is no way around: 

For instance, taking the example: 

Suppose we need to calculate Delivery Lead Time of a particular order based on Order Date and Delivery Date 
Assume for a moment that this calculation couldn’t be done with CDS Views. 
In that case, you could create a Virtual Element in a CDS View. 
Because that Virtual Element would execute ABAP code to perform the logic mentioned above, Subtracting (ORDER DATE – DELIVERY DATE ) 
And you surely can solve the problem with ABAP. 
Then, that ABAP code would be executed each time the Virtual Element is accessed on the CDS View, solve the problem, and return the result to the CDS View.  

Code PushDown :
Code pushdown results in improved performance, as the amount of data that needs to be transferred between the database and application is reduced. 
Code push down can be achieved by using SQL Script or by using the HANA-optimized CDS language syntax 
Well, the concept of Code Pushdown is to handle logic on the database instead of the application server. 

Why? 

CDS Views get executed on the database. 
CDS Views are actually nothing more than syntactic sugar for SQL. 
If you execute a CDS View, you execute a SQL statement at the end. 
Well, and SQL gets executed on the database. 
Again, RAP has the execution of logic on the database layer as a fundamental concept. 
CDS Views execute logic on the database layer. 
Surprise, CDS Views as part of RAP are a perfect match. 
So why do I bother you with those details above you ask? 
Well, now with those things being said and keeping those in mind, let’s make the transition to what Virtual Elements actually are. 

  

Before anything else, why avoid Virtual Elements? 
Because . . . if you use Virtual Elements, you undermine one of the fundamental principles of RAP (Restful ABAP Programming). 
CDS Views are a cornerstone of RAP. 
Thus, the entire purpose of CDS Views is to support RAP. 
And one of the core objectives of RAP is the Code Pushdown. 

 Annotations used for virtual elements :

 

@ObjectModel.virtualElementCalculatedBy: ‘ABAP:ZCL_PD_SALES_VE’
@EndUserText.label: ‘Delivery Lead Time’//
virtual DeliveryLeadTime : abap.int4Interfaces used :

 

INTERFACES : if_sadl_exit .

INTERFACES : if_sadl_exit_calc_element_read .

Methods :

Methods : get_calculation_info

Methods : calculate

Method GET_CALCULATION_INFO is used to provide the list of fields which is required for the calculation.Method CALCULATE is actual method where we implement the custom logic.

Virtual Elements  Vs CDS view

Well, CDS Views can solve any problem that a computer can, with enough time and memory. 
CDS Views can do any computation that doesn’t require infinite resources. 
Therefore, take a closer look at your requirement at hand and ask yourself whether the logic necessary can’t be done in a reasonable way with CDS Views. 
I say “reasonable way” because, while CDS Views might be Turing-complete, that doesn’t mean you should do any computation with CDS Views. 
Especially due to performance reasons. 

scenario :

Calculated Field: Delivery Lead Time Input Fields: Order Date , Delivery Date. 

Formula: 

Delivery Lead Time = Order Date – Delivery Date 

Steps :

1.Create a db table with respective fields.

 

@EndUserText.label : ‘table for virtual element’

@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE

@AbapCatalog.tableCategory : #TRANSPARENT

@AbapCatalog.deliveryClass : #A

@AbapCatalog.dataMaintenance : #RESTRICTED

define table zpd_dt_ve_dlt {

key client : abap.clnt not null;

key order_id : sysuuid_x16 not null;

order_date : abap.dats;

deliverydate : abap.dats;

local_created_by : abp_creation_user;

local_created_at : abp_creation_tstmpl;

local_last_changed_by : abp_locinst_lastchange_user;

local_last_changed_at : abp_locinst_lastchange_tstmpl;

last_changed_at : abp_lastchange_tstmpl;

}

 

2.Create a root view entity for the table 

 

@AccessControl.authorizationCheck: #CHECK

@Metadata.allowExtensions: true

@EndUserText.label: ‘###GENERATED Core Data Service Entity’

define root view entity ZR_PD_DT_VE_DLT

as select from zpd_dt_ve_dlt

{

key order_id as OrderId,

order_date as OrderDate,

deliverydate as Deliverydate,

@Semantics.user.createdBy: true

local_created_by as LocalCreatedBy,

@Semantics.systemDateTime.createdAt: true

local_created_at as LocalCreatedAt,

@Semantics.user.localInstanceLastChangedBy: true

local_last_changed_by as LocalLastChangedBy,

@Semantics.systemDateTime.localInstanceLastChangedAt: true

local_last_changed_at as LocalLastChangedAt,

@Semantics.systemDateTime.lastChangedAt: true

last_changed_at as LastChangedAt

}

 

3.Now create a projection view  on top of that and deifne the interface and class for virtual element as well.

 

@Metadata.allowExtensions: true

@EndUserText.label: ‘###GENERATED Core Data Service Entity’

@AccessControl.authorizationCheck: #CHECK

define root view entity ZC_PD_DT_VE_DLT

provider contract transactional_query

as projection on ZR_PD_DT_VE_DLT

{

key OrderId,

OrderDate,

Deliverydate,

LocalCreatedBy,

LocalCreatedAt,

LocalLastChangedBy,

LocalLastChangedAt,

LastChangedAt,

@ObjectModel.virtualElementCalculatedBy: ‘ABAP:ZCL_PD_SALES_VE1’

@EndUserText.label: ‘Delivery Lead Time’

virtual DeliveryLeadTime : abap.int4

}

 

Interface we need to select before creating class. Virtual key and respective data element is mandatory

4.Now create behavior definition – projection behaviour defintion  projection implementation in class 

 

projection implementation in class ZBP_C_PD_DT_VE_DLT unique;

strict ( 2 );

use draft;

define behavior for ZC_PD_DT_VE_DLT alias ZcPdDtVeDlt

use etag

{

use create;

use update;

use delete;

use action Edit;

use action Activate;

use action Discard;

use action Resume;

use action Prepare;

}

 

5.Behaviour definition for zr_pd_dt_ve_dlt

 

managed implementation in class ZBP_R_PD_DT_VE_DLT unique;

strict ( 2 );

with draft;

define behavior for ZR_PD_DT_VE_DLT alias ZrPdDtVeDlt

persistent table zpd_dt_ve_dlt

draft table zpd_dt_ve_dlt_d

etag master LocalLastChangedAt

lock master total etag LastChangedAt

authorization master ( global )

{

field ( readonly )

OrderId,

LocalCreatedBy,

LocalCreatedAt,

LocalLastChangedBy,

LocalLastChangedAt,

LastChangedAt;

field ( numbering : managed )

OrderId;

create;

update;

delete;

draft action Activate optimized;

draft action Discard;

draft action Edit;

draft action Resume;

draft determine action Prepare;

mapping for zpd_dt_ve_dlt

{

OrderId = order_id;

OrderDate = order_date;

Deliverydate = deliverydate;

LocalCreatedBy = local_created_by;

LocalCreatedAt = local_created_at;

LocalLastChangedBy = local_last_changed_by;

LocalLastChangedAt = local_last_changed_at;

LastChangedAt = last_changed_at;

}

}

 

6.Create service definition for consumption view

 

@EndUserText: {

label: ‘Service Definition for ZC_PD_DT_VE_DLT’

}

@ObjectModel: {

leadingEntity: {

name: ‘ZC_PD_DT_VE_DLT’

}

}

define service ZUI_PD_DT_VE_DLT_O4 provider contracts odata_v4_ui {

expose ZC_PD_DT_VE_DLT;

}

 

7. Create virtual element class for writing respective logic.

 

CLASS zcl_pd_sales_ve1 DEFINITION

PUBLIC

FINAL

CREATE PUBLIC .

PUBLIC SECTION.

INTERFACES if_sadl_exit .

INTERFACES if_sadl_exit_calc_element_read .

PROTECTED SECTION.

PRIVATE SECTION.

ENDCLASS.

CLASS zcl_pd_sales_ve1 IMPLEMENTATION.

METHOD if_sadl_exit_calc_element_read~calculate.

TYPES : BEGIN OF ty_date_cal,

OrderDate TYPE dats,

DeliveryDate TYPE dats,

DeliveryLeadTime TYPE int4,

END OF ty_date_cal.

DATA : int_tab TYPE TABLE OF ty_date_cal.

int_tab = CORRESPONDING #( it_original_data ).

LOOP AT int_tab INTO DATA(wa) .

DATA(order_date) = wa-orderdate.

DATA(delivery_date) = wa-deliverydate.

wa-deliveryleadtime = delivery_date – order_date.

MODIFY int_tab FROM wa.

ENDLOOP.

ct_calculated_data = CORRESPONDING #( int_tab ).

ENDMETHOD.

METHOD if_sadl_exit_calc_element_read~get_calculation_info.

ENDMETHOD.

ENDCLASS.

 

 8.Bind the service  .

9.After this select the entity and preview the data.

Here we can see that virtual element field ‘Delivery Lead Time’ holding the calculated value at runtime  After the successful calculation of ‘ Delivery Lead Time’ with respect to order date. 

Virtual Element Calculation:  
This involves: Calling the associated ABAP class or method (CALCULATE in the example above). 
Performing the computation for each record at runtime. 
Virtual elements are calculated dynamically and not stored in the database. 
This means the system performs these calculations in memory, adding a small overhead compared to fetching static fields.

 

Thank you—-

Regards 

Pradeep Ishwar

 

​ Virtual elements and  Performance :What are Virtual Elements? A virtual element is typically used in CDS views to derive calculated fields dynamically without storing them in the database.Suppose if we want to use any ABAP resources that would get more info for us Such as any informative fields or any function modules needed to be included in cds  We go for virtual element Virtual Elements, those little pieces of code that are helpful to calculate certain things and add certain fields during runtime. . Anyway, there is no way around: For instance, taking the example: Suppose we need to calculate Delivery Lead Time of a particular order based on Order Date and Delivery Date Assume for a moment that this calculation couldn’t be done with CDS Views. In that case, you could create a Virtual Element in a CDS View. Because that Virtual Element would execute ABAP code to perform the logic mentioned above, Subtracting (ORDER DATE – DELIVERY DATE ) And you surely can solve the problem with ABAP. Then, that ABAP code would be executed each time the Virtual Element is accessed on the CDS View, solve the problem, and return the result to the CDS View.  Code PushDown :Code pushdown results in improved performance, as the amount of data that needs to be transferred between the database and application is reduced. Code push down can be achieved by using SQL Script or by using the HANA-optimized CDS language syntax Well, the concept of Code Pushdown is to handle logic on the database instead of the application server. Why? CDS Views get executed on the database. CDS Views are actually nothing more than syntactic sugar for SQL. If you execute a CDS View, you execute a SQL statement at the end. Well, and SQL gets executed on the database. Again, RAP has the execution of logic on the database layer as a fundamental concept. CDS Views execute logic on the database layer. Surprise, CDS Views as part of RAP are a perfect match. So why do I bother you with those details above you ask? Well, now with those things being said and keeping those in mind, let’s make the transition to what Virtual Elements actually are.   Before anything else, why avoid Virtual Elements? Because . . . if you use Virtual Elements, you undermine one of the fundamental principles of RAP (Restful ABAP Programming). CDS Views are a cornerstone of RAP. Thus, the entire purpose of CDS Views is to support RAP. And one of the core objectives of RAP is the Code Pushdown.  Annotations used for virtual elements : @ObjectModel.virtualElementCalculatedBy: ‘ABAP:ZCL_PD_SALES_VE’
@EndUserText.label: ‘Delivery Lead Time’//
virtual DeliveryLeadTime : abap.int4Interfaces used : INTERFACES : if_sadl_exit .INTERFACES : if_sadl_exit_calc_element_read .Methods :Methods : get_calculation_infoMethods : calculateMethod GET_CALCULATION_INFO is used to provide the list of fields which is required for the calculation.Method CALCULATE is actual method where we implement the custom logic.Virtual Elements  Vs CDS viewWell, CDS Views can solve any problem that a computer can, with enough time and memory. CDS Views can do any computation that doesn’t require infinite resources. Therefore, take a closer look at your requirement at hand and ask yourself whether the logic necessary can’t be done in a reasonable way with CDS Views. I say “reasonable way” because, while CDS Views might be Turing-complete, that doesn’t mean you should do any computation with CDS Views. Especially due to performance reasons. scenario :Calculated Field: Delivery Lead Time Input Fields: Order Date , Delivery Date. Formula: Delivery Lead Time = Order Date – Delivery Date Steps :1.Create a db table with respective fields. @EndUserText.label : ‘table for virtual element’

@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE

@AbapCatalog.tableCategory : #TRANSPARENT

@AbapCatalog.deliveryClass : #A

@AbapCatalog.dataMaintenance : #RESTRICTED

define table zpd_dt_ve_dlt {

key client : abap.clnt not null;

key order_id : sysuuid_x16 not null;

order_date : abap.dats;

deliverydate : abap.dats;

local_created_by : abp_creation_user;

local_created_at : abp_creation_tstmpl;

local_last_changed_by : abp_locinst_lastchange_user;

local_last_changed_at : abp_locinst_lastchange_tstmpl;

last_changed_at : abp_lastchange_tstmpl;

}  2.Create a root view entity for the table  @AccessControl.authorizationCheck: #CHECK

@Metadata.allowExtensions: true

@EndUserText.label: ‘###GENERATED Core Data Service Entity’

define root view entity ZR_PD_DT_VE_DLT

as select from zpd_dt_ve_dlt

{

key order_id as OrderId,

order_date as OrderDate,

deliverydate as Deliverydate,

@Semantics.user.createdBy: true

local_created_by as LocalCreatedBy,

@Semantics.systemDateTime.createdAt: true

local_created_at as LocalCreatedAt,

@Semantics.user.localInstanceLastChangedBy: true

local_last_changed_by as LocalLastChangedBy,

@Semantics.systemDateTime.localInstanceLastChangedAt: true

local_last_changed_at as LocalLastChangedAt,

@Semantics.systemDateTime.lastChangedAt: true

last_changed_at as LastChangedAt

}  3.Now create a projection view  on top of that and deifne the interface and class for virtual element as well. @Metadata.allowExtensions: true

@EndUserText.label: ‘###GENERATED Core Data Service Entity’

@AccessControl.authorizationCheck: #CHECK

define root view entity ZC_PD_DT_VE_DLT

provider contract transactional_query

as projection on ZR_PD_DT_VE_DLT

{

key OrderId,

OrderDate,

Deliverydate,

LocalCreatedBy,

LocalCreatedAt,

LocalLastChangedBy,

LocalLastChangedAt,

LastChangedAt,

@ObjectModel.virtualElementCalculatedBy: ‘ABAP:ZCL_PD_SALES_VE1’

@EndUserText.label: ‘Delivery Lead Time’

virtual DeliveryLeadTime : abap.int4

}  Interface we need to select before creating class. Virtual key and respective data element is mandatory4.Now create behavior definition – projection behaviour defintion  projection implementation in class  projection implementation in class ZBP_C_PD_DT_VE_DLT unique;

strict ( 2 );

use draft;

define behavior for ZC_PD_DT_VE_DLT alias ZcPdDtVeDlt

use etag

{

use create;

use update;

use delete;

use action Edit;

use action Activate;

use action Discard;

use action Resume;

use action Prepare;

}  5.Behaviour definition for zr_pd_dt_ve_dlt managed implementation in class ZBP_R_PD_DT_VE_DLT unique;

strict ( 2 );

with draft;

define behavior for ZR_PD_DT_VE_DLT alias ZrPdDtVeDlt

persistent table zpd_dt_ve_dlt

draft table zpd_dt_ve_dlt_d

etag master LocalLastChangedAt

lock master total etag LastChangedAt

authorization master ( global )

{

field ( readonly )

OrderId,

LocalCreatedBy,

LocalCreatedAt,

LocalLastChangedBy,

LocalLastChangedAt,

LastChangedAt;

field ( numbering : managed )

OrderId;

create;

update;

delete;

draft action Activate optimized;

draft action Discard;

draft action Edit;

draft action Resume;

draft determine action Prepare;

mapping for zpd_dt_ve_dlt

{

OrderId = order_id;

OrderDate = order_date;

Deliverydate = deliverydate;

LocalCreatedBy = local_created_by;

LocalCreatedAt = local_created_at;

LocalLastChangedBy = local_last_changed_by;

LocalLastChangedAt = local_last_changed_at;

LastChangedAt = last_changed_at;

}

}  6.Create service definition for consumption view @EndUserText: {

label: ‘Service Definition for ZC_PD_DT_VE_DLT’

}

@ObjectModel: {

leadingEntity: {

name: ‘ZC_PD_DT_VE_DLT’

}

}

define service ZUI_PD_DT_VE_DLT_O4 provider contracts odata_v4_ui {

expose ZC_PD_DT_VE_DLT;

}  7. Create virtual element class for writing respective logic. CLASS zcl_pd_sales_ve1 DEFINITION

PUBLIC

FINAL

CREATE PUBLIC .

PUBLIC SECTION.

INTERFACES if_sadl_exit .

INTERFACES if_sadl_exit_calc_element_read .

PROTECTED SECTION.

PRIVATE SECTION.

ENDCLASS.

CLASS zcl_pd_sales_ve1 IMPLEMENTATION.

METHOD if_sadl_exit_calc_element_read~calculate.

TYPES : BEGIN OF ty_date_cal,

OrderDate TYPE dats,

DeliveryDate TYPE dats,

DeliveryLeadTime TYPE int4,

END OF ty_date_cal.

DATA : int_tab TYPE TABLE OF ty_date_cal.

int_tab = CORRESPONDING #( it_original_data ).

LOOP AT int_tab INTO DATA(wa) .

DATA(order_date) = wa-orderdate.

DATA(delivery_date) = wa-deliverydate.

wa-deliveryleadtime = delivery_date – order_date.

MODIFY int_tab FROM wa.

ENDLOOP.

ct_calculated_data = CORRESPONDING #( int_tab ).

ENDMETHOD.

METHOD if_sadl_exit_calc_element_read~get_calculation_info.

ENDMETHOD.

ENDCLASS.   8.Bind the service  .9.After this select the entity and preview the data.Here we can see that virtual element field ‘Delivery Lead Time’ holding the calculated value at runtime  After the successful calculation of ‘ Delivery Lead Time’ with respect to order date. Virtual Element Calculation:  This involves: Calling the associated ABAP class or method (CALCULATE in the example above). Performing the computation for each record at runtime. Virtual elements are calculated dynamically and not stored in the database. This means the system performs these calculations in memory, adding a small overhead compared to fetching static fields. Thank you—-Regards Pradeep Ishwar   Read More Application Development Blog Posts articles 

#SAP

You May Also Like

More From Author