cancel
Showing results for 
Search instead for 
Did you mean: 

Associations in custom entities in SAP RAP

Domae
Participant

Hi,

I have a simple RAP based OData Service with two custom entities which are associated one to another like so:

Root entity "RUN"

Root entity "MESSAGE"

So when I call all or a single "run" entity/ies, everything works fine.

Now I want to call the navigation property "to_Messages" of a single "run" entity, to display the results in a lineitem annotation like so:

/sap/opu/odata/sap/ZBI_MXF_RUN/ZDD_I_MXF_RUN(vtype='AB02FG',run_id='206')/to_Messages

I thought that as soon as I call the association, the RAP framework would call the if_rap_query_provider~select method of the class, which I defined in the child(associated) entity, like ZCL_CE_MXF_MESSAGE but instead, the framework calls the select method of the "run" entity in the ZCL_CE_MXF_RUN class.

If this works as intended how can I distinguish, which association was called? In the debugger it seems that it is a normal getEntity call of the "Run" entity with no additional information about the association or anything else, that could help me.

When I call the "Message" entity itself, the corresponding select method in the "Message" class is called. But not when I call it as an association of the "Run" Entity. I configured the relation between the two entities as composition in the first place, like in the answer of andre.fischer in the question https://answers.sap.com/questions/13631104/abap-rap-complex-logic-for-read.html, but it was no difference.

Did I configured something wrong?

Best Regards

Dominik

Accepted Solutions (1)

Accepted Solutions (1)

dominik_ee
Advisor
Advisor

Hi Dominik,

when querying data via navigation, the framework checks for the existence of unmanaged queries (@Objectmodel.Query.Implementedby) in the navigation path and splits the query in subqueries for each involved unmanaged query. In your case, the "run" is queried with a filter containing the instance keys vtype = 'AB02FG' and run_id = '206'. This is the "existence check" for the source of a navigation. If the unmanaged query returns the instance, the information from that query is used to query the unmanaged query of the target.

In the assocation condition you have defined that _messages.run_id = run.run_id and _messages.vtype = run.vtype. The values from the existence check query of "run" are used and replaced in the assocation condition resulting in:
_messages.vtype= 'AB02FG' and _messages.run_id = '206'

This filter is then passed to your unmanaged query of the "message" entity.

In general you can use the ABAP Cross Trace to check the orchestration and execution of a query/request by the RAP frameworks: https://help.sap.com/docs/BTP/5371047f1273405bb46725a417f95433/290647b75cea46f491907889251ad067.html

When creating a configuration ensure that you have selected the RAP Orchestration and Query entries.

Best regards,
Dominik

nishantbansal91
Active Contributor
0 Kudos

Hello @dominikeiraelias

I have implemented the same functionality and everything works as expected. Now, I need to implement the Deep Post operation on it.define root custom entity ZC_CE_GET_QUESTION
{....... tags : association [0..*] to ZC_QUEST_TAG_MAP on tags.abc = ZC_CE_GET_QUESTION.abc;}

I am able to post the data for the entity ZC_CE_GET_QUESTION, Now I want to send the structure for Tags in the post call.

I am not able to define the behavior for TAGS entity. ? Any suggestion?

Just to update- TAGS is not custom CDS entity it is normal Data definition

Below is my behavior definition:-

Behavior Definition:- unmanaged implementation in class zbp_c_ce_get_question unique

Entity strict ( 2 );

define behavior for ZC_CE_GET_QUESTION

lock master

authorization master ( instance )

{ create; update; delete; association tags { create; } // this statement gives me error }

Answers (2)

Answers (2)

Domae
Participant

Hi Dominik :),

thanks for this clarification! My logic stopped at the existence check, because in my getEntity Method I did not call the paging methods, so the framework threw an error regarding this. I fixed that, and now the select method of the associated entity is getting called!

Thank a lot!!

Best Regards

Dominik

S0018810432
Newcomer
0 Kudos

Hi Dominik,

I have the same issue, how to get the data for both header and line item in a single query?

One custom entity to get header and another one for line items data.

Thank you,

Gangadhar

0 Kudos

Hi Dominik,

I am facing the same issue which you fixed at your end. I want to show the item data information on the Object Page using Custom CDS entity upon choosing a record in List Page but somehow the association is not working. It doesn't call the Select method of the Item class upon clicking a record on List Page.

Appreciate your help.

Code Snippet -

Root Entity -

Item Entity

Root Class Implementation -

METHOD if_rap_query_provider~select.

DATA business_data TYPE TABLE OF vbak.

DATA query_result TYPE TABLE OF vbak.

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

SELECT * FROM vbak INTO TABLE business_data WHERE vbeln = '0000000001'.

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.

Item Class Implementation -

TRY.

IF io_request->is_data_requested( ).

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

lt_range = VALUE #( FOR ls_filter IN filter_condition WHERE ( name EQ 'VBELN' )

FOR ls_range IN ls_filter-range

( sign = ls_range-sign

option = ls_range-option

low = ls_range-low ) ).

* DATA(lv_salesorder) = VALUE #( lt_range[ 1 ]-low OPTIONAL ).

* FREE lt_range.

SELECT * FROM vbap INTO TABLE business_data WHERE vbeln IN lt_range.

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 ).

ENDIF.

CATCH cx_root INTO DATA(exception).

DATA(exception_message) = cl_message_helper=>get_latest_t100_exception( exception )->if_message~get_longtext( ).

ENDTRY.

Regards,

Insaf

AnuragSri
Explorer
0 Kudos

Hi Insaf,

Were you able to resolve this ? I am also facing the same issue.

Thanks.

Anurag

kazbek
Member
0 Kudos

It seems, that total_number_of_records equals 0.

You need to change your code to:

IF io_request->is_total_numb_of_rec_requested( ).
  io_response->set_total_number_of_records( lines( business_data ) ).
ENDIF.

Best Regards, Kazbek.

catalinfeidi
Participant
0 Kudos

Hi,

We just implemented the custom entity on root and child having both classes implemented and they are called sequentially.

If we expand the child, both root and child classes are called. I don't see how you have a different behaviour.

vijay_kamath2
Explorer
0 Kudos
Hi - I am facing this issue of the child entity not getting called. Instead when I click on the line in the list report, I see that the header entity gets called again. Can you share sample of the 2 entities, so that I can check if I have done something wrong.