ABAP Blog Posts
cancel
Showing results for 
Search instead for 
Did you mean: 
Banasiddha_Patil
Explorer
2,179

Introduction

In modern SAP application development using the ABAP RESTful Application Programming Model, developers often encounter scenarios where data must be retrieved from multiple sources instead of a single database table.

For such cases, Custom Entities provide a flexible solution. They allow developers to implement custom query logic using ABAP classes while still leveraging RAP features such as associations, navigation, and UI annotations.

In this blog, we will implement a Travel–Booking scenario using Custom Entities where data is fetched dynamically through a query implementation class.

Create Query Implementation Class

First, create a class that implements the RAP interface:

INTERFACE if_rap_query_provider

This interface allows developers to implement custom query logic.

CLASS zcl_custom_entitys DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    " Interface used for implementing query logic for Custom Entities
    INTERFACES if_rap_query_provider.

ENDCLASS.


CLASS zcl_custom_entitys IMPLEMENTATION.

  METHOD if_rap_query_provider~select.

    " Variables used for paging, entity identification and filtering
    DATA: lv_top        TYPE i,
          lv_offset     TYPE i,
          lv_entity     TYPE string,
          lv_conditions TYPE string,
          lv_total      TYPE int8.

    " Read paging parameters from OData request
    lv_top    = io_request->get_paging( )->get_page_size( ).
    lv_offset = io_request->get_paging( )->get_offset( ).

    " Identify which custom entity is being queried
    lv_entity = io_request->get_entity_id( ).

    " Ensure page size is valid
    IF lv_top < 0.
      lv_top = 1.
    ENDIF.

    " Retrieve filter conditions from request
    lv_conditions = io_request->get_filter( )->get_as_sql_string( ).

    " Handle Travel Custom Entity request
    IF lv_entity = 'ZI_TRAVEL_CUSTOMENTITY'.

      " Fetch data from travel table with paging and filter conditions
      SELECT travel_id,
             agency_id,
             customer_id,
             begin_date,
             end_date,
             booking_fee,
             total_price,
             currency_code,
             description,
             CASE
               WHEN overall_status = 'O' THEN 'Open'
               WHEN overall_status = 'A' THEN 'Accepted'
               WHEN overall_status = 'X' THEN 'Cancel'
             END AS overall_status
        FROM /dmo/travel_m
        WHERE (lv_conditions)
        ORDER BY travel_id, agency_id
        INTO TABLE (lt_travel)
        OFFSET _offset
        UP TO _top ROWS.

      " Calculate number of records returned
      lv_total = lines( lt_travel ).

      " Send response back to RAP framework
      io_response->set_data( lt_travel ).
      io_response->set_total_number_of_records( lv_total ).

    ENDIF.

  ENDMETHOD.

ENDCLASS.

This class dynamically fetches data using paging parameters such as $top and $skip.

Define Root Custom Entity (Travel)

Next, define the root custom entity in CDS.

@EndUserText.label: 'Travel Custom Entity'
@ObjectModel: {
  query.implementedBy: 'ABAP:ZCL_CUSTOM_ENTITYS'
}
@Metadata.allowExtensions: true

define root custom entity Zi_travel_customentity
{

  key Travel_id : /dmo/travel_id;
  Agency_id     : /dmo/agency_id;
  Customer_id   : /dmo/customer_id;
  Begin_date    : /dmo/begin_date;
  End_date      : /dmo/end_date;

  @Semantics.amount.currencyCode: 'currency_code'
  booking_fee : /dmo/booking_fee;

  @Semantics.amount.currencyCode: 'currency_code'
  Total_price : /dmo/total_price;

  currency_code : /dmo/currency_code;
  description   : /dmo/description;

  overall_status : abap.char(10);

  _Booking : composition [1..*] of ZI_BOOKING_CUSTOMENTITY;

}

Define Item Custom Entity (Booking)

Now create the booking entity and associate it with Travel.

@EndUserText.label: 'Booking Entity'
@ObjectModel : {
  query.implementedBy: 'ABAP:ZCL_CUSTOM_ENTITYS'
}
@Metadata.allowExtensions: true

define custom entity ZI_BOOKING_CUSTOMENTITY
{

  key travel_id  : /dmo/travel_id;
  key booking_id : /dmo/booking_id;

  booking_date : /dmo/booking_date;
  customer_id  : /dmo/customer_id;
  carrier_id   : /dmo/carrier_id;
  connection_id: /dmo/connection_id;
  flight_date  : /dmo/flight_date;

  @Semantics.amount.currencyCode: 'currency_code'
  flight_price : /dmo/flight_price;

  currency_code : /dmo/currency_code;
  booking_status: /dmo/booking_status;

  _Travel : association to parent Zi_travel_customentity
             on $projection.travel_id = _Travel.Travel_id;

}

Add UI Annotations Using Metadata Extensions

Metadata extensions are used to define how the fields appear in SAP Fiori applications.

Example:

.selectionField: [{ position: 10 }]
@UI.lineItem: [{ position: 10 }]
@UI.identification: [{ position: 10 }]
Travel_id;

Create Service Definition

Expose the root entity using a service definition.

define service ZUI_TRAVEL_SERVICE {
  expose Zi_travel_customentity;
}

Create Service Binding

Create a Service Binding for the service definition and activate it to expose the service as an OData service.

Screenshot 2026-03-11 140546.png

Preview the Application

Screenshot 2026-03-11 135827.pngScreenshot 2026-03-11 135856.png

Screenshot 2026-03-11 135928.png

Key Advantages of Custom Entities

Using Custom Entities in unmanaged RAP provides several benefits:

• Fetch data from multiple data sources
• Implement custom query logic using ABAP
• Enable associations and navigation
• Support Fiori UI annotations
• Integrate easily with OData services

Conclusion

Custom Entities are a powerful feature in the ABAP RESTful Application Programming Model that allow developers to implement flexible data retrieval scenarios.

By combining CDS definitions, query implementation classes, and metadata extensions, developers can build scalable services capable of fetching data from multiple sources while still benefiting from RAP architecture.

This approach is particularly useful in scenarios where data cannot be represented by a single CDS view or database table.

4 Comments