cancel
Showing results for 
Search instead for 
Did you mean: 

ABAP RAP complex logic for read

patrick_weber11
Participant
0 Kudos
5,284

Hello,

as a beginner in ABAP RAP, i looked at several tutorials. Most of them cover Create, Update and Delete scenarios as well as validation. For READ operation, they commonly rely on simple CDS Views.

But in some cases, we can't simple read a CDS view. Imagine you have complex business logic to create your result set. We might use BAPI to get the data or we might use some special logic to set some columns depending on special conditions (based on seletion screen data, customizing data and so on). Things we hard coded in good old ABAP days.

How do you handle such situation, where READ of Entity or EntitySet is not a trivial read of a CDS View in RAP?

Do you such things also with RAP or is it still valid to use SEGW in such situation?

Accepted Solutions (1)

Accepted Solutions (1)

Andre_Fischer
Product and Topic Expert
Product and Topic Expert

Hi Patrick,

if the data is not a simple read from a CDS view you have to use so called custom entities.

So something like this:

@ObjectModel.query.implementedBy: 'ABAP:ZCL_CE_AF_SALESORDER'
@UI: {
  headerInfo: {
    typeName: 'SalesOrder', 
    typeNamePlural: 'SalesOrders', 
    title: {
      type: #STANDARD, 
      label: 'SalesOrder', 
      value: 'ID'
    }
  }
, 
  presentationVariant: [ {
    sortOrder: [ {
      by: 'ID', 
      direction: #DESC
    } ], 
    visualizations: [ {
      type: #AS_LINEITEM
    } ]
  } ]
}

define root custom entity ZR_AF_SALESORDERTP
{
  _SalesOrderItem : composition [0..*] of ZR_AF_SALESORDERITEMTP;
....
}

The child entity would look similar as the following code

@ObjectModel.query.implementedBy: 'ABAP:ZCL_CE_AF_SALESORDERITEM'
@UI: {
  headerInfo: {
    typeName: 'SalesOrderItem', 
    typeNamePlural: 'SalesOrderItems', 
    title: {
      type: #STANDARD, 
      label: 'SalesOrderItem', 
      value: 'SALESORDERITEM'
    }
  }
, 
  presentationVariant: [ {
    sortOrder: [ {
      by: 'SALESORDERITEM', 
      direction: #DESC
    } ], 
    visualizations: [ {
      type: #AS_LINEITEM
    } ]
  } ]
}


define custom entity ZR_AF_SALESORDERITEMTP
{
  _SalesOrder : association to parent ZR_AF_SALESORDERTP on $projection.ID = _SalesOrder.ID;
  @UI.facet: [ {
    id: 'idSalesOrderItem', 
    purpose: #STANDARD, 
    type: #IDENTIFICATION_REFERENCE, 
    label: 'SalesOrderItem', 
    position: 10 
  } ]
  @UI.lineItem: [ {
    position: 10 , 
    importance: #HIGH, 
    label: 'ID'
  } ]
  @UI.identification: [ {
    position: 10 , 
    label: 'ID'
  } ]
  key ID : sysuuid_x16 ;
<br>

And you would use the abap class ZCL_CE_AF_SALESORDER to retrieve the data for the root entity and a class ZCL_CE_AF_SALESORDERITEM to retrieve the items.

CLASS ZCL_CE_AF_SALESORDER IMPLEMENTATION.


METHOD IF_RAP_QUERY_PROVIDER~SELECT.
DATA business_data TYPE TABLE OF ZR_AF_SalesOrderTP.
DATA query_result  TYPE TABLE OF ZPMSEPM_I_SALESORDER_E.
DATA total_number_of_records type int8.
DATA(top)               = io_request->get_paging( )->get_page_size( ).
DATA(skip)              = io_request->get_paging( )->get_offset( ).
DATA(requested_fields)  = io_request->get_requested_elements( ).
DATA(sort_order)        = io_request->get_sort_elements( ).
TRY.
 DATA(filter_condition) = io_request->get_filter( )->get_as_ranges( ).
 "Here you have to implement your custom query
 "and store the result in the internal table query_result
 IF io_request->is_total_numb_of_rec_requested(  ).
   io_response->set_total_number_of_records( total_number_of_records ).
 ENDIF.
 io_response->set_data( business_data ).
CATCH cx_root INTO DATA(exception).
DATA(exception_message) = cl_message_helper=>get_latest_t100_exception( exception )->if_message~get_longtext( ).
ENDTRY.
ENDMETHOD.
ENDCLASS.<br>

So from an implementation perspective this is similar to the implementation of the GET_ENTITY and GET_ENTITYSET method.

But here you don't use two methods but one so you would have to check beforehand if the select option defines the complete key so that you would call the BAPI_..._GETDETAIL rather then the BAPI_..._GETLIST.

Please note the following restrictions when using custom entities:

1. Custom entities do not offer projections and no metadata extensions, so you have to add all UI annotations and all other annotations that you normally would put into the projection view into your custome entity.

2. Custom entities do not support draft.

Since OData V4 Fiori Elements App do require the support of draft you will NOT be able to use a SAP Fiori V4 Elements for such a service.

You would be limited to either build a custom V4 based SAP Fiori app or you would have to go for an OData V2 binding where SAP Fiori Elements V2 template coud be used (however without draft).

Also OData V2 and V4 Web API should work.

When you are already using SAP S/4HANA 2021 you can use my openSource project The RAP Generator to build custom entity based RAP business objects that are using the abstract entities generated when creating a service consumption model as a "datasource".

Kind regards,

Andre

patrick_weber11
Participant
0 Kudos

Thank you Andre,

that was exactly what I was looking for. I found you blog post about this but it was written in 2019 and I was curious, if this is still valid. Things changes rapidly with S/4 and often, a good looking solution is already out-dated.

patrick_weber11
Participant
0 Kudos

May I ask and additional, related question? I know that SAP provides a VDM and from my understanding, it is just there to ease development as most "common" entities are already well-defined.

When it comes to RAP, do you also use VDM CDS views for your application? Most examples don't and I was curious if there is a special reason or only to keep examples simple.

BR Patrick

0 Kudos

Hi Andre,

I can see OData V4 creation options in Service Binding. I also see data and service previews.

Is it really OData v4 is not supported for custom entity based RAP OData?

Thanks and regards,

Amit

dominik_ee
Advisor
Advisor
0 Kudos

Hi Amit, Custom Entites are supported in V4, only draft is not supported for custom entities. Andre adopted his response accordingly.

rammel
Participant
0 Kudos

Hi,

Do we have something similar to GET_EXPANDED_ENTITY and GET_EXPANDED_ENTITYSET methods in SEGW implementation? I noticed there will be 2 method calls, one is for the header and one is for the item. Also, can we pass error messages back to the response? I noticed the response method SET_DATA only has the actual data parameter.

Previously for the error handling, we can do it by raising an exception and passing the message container.

Ramjee_korada
Active Contributor
0 Kudos

Hi Rammel,

I have replied your question.

https://answers.sap.com/answers/14012966/view.html

BW,

Ramjee Korada

Answers (3)

Answers (3)

dominik_ee
Advisor
Advisor

I would recommend to start here in the documentation: https://help.sap.com/docs/BTP/923180ddb98240829d935862025004d6/ffef7e02127e442793f24e3dc902c824.html

Once you have identified a suitable scenario, you might also look into the unmanaged query: https://help.sap.com/docs/BTP/923180ddb98240829d935862025004d6/254f68c7d5374e94a88241b7ce3bd414.html

The unmanaged query offers an exit during the query runtime (HTTP GET) to implement the data retrieval in a classic ABAP class instead of querying the data from the database. An overview about the query implementation types can be found here: https://help.sap.com/docs/BTP/923180ddb98240829d935862025004d6/5ab5677116664c31b4a397493d61485e.html

former_member504384
Discoverer
0 Kudos

andre.fischer how to call behaviour implementation for create operation using Header and Item Custom Entity as separate . And how to call same as URI from Gateway ?

meriton
Explorer
0 Kudos

What you are looking for is combine a select option, CDS and Call AMDP methods.

Remember when working with CDS you only work with tables, but you are able to go through AMDP for abap coding (BAPI). Else you need to redefine "********_READ_ENTITYSET" in order to achive what you want.

patrick_weber11
Participant
0 Kudos

Thank you for your answer. Do you have a link to a tutorial or a short example which explains this in more detail?

meriton
Explorer