ABAP Restful Application Programming : Custom actions => Merge Draft entities into Active and switch to display mode
In this blog post, I will explain about “Custom actions” that can merge draft entities into Active and switch to display mode. An action in RAP is a non-standard modifying operation that is part of the business logic. The standard use case of an action is to change specific fields of a business object entity.
In General, MODIFY ENTITIES can be used to change the required fields in an entity. That means, Active instance remains as active and Draft instance remains as Draft. But some business requirements expect us to convert those draft instances into active instances.
This can be achieved using “EXECUTE Activate” on MODIFY ENTITIES. With this, Active instance is prepared but the real challenge comes now.
How does the fiori app come to know about this change to show modified information of the entity?
Then “side effects” strike my mind but later I realize that they can be triggered to reflect modified information ( different property / entity ) on change of a field/entity/action .
But, In our case, Own entity needs to be refreshed. Actual challenge here is that the “original key” is “IsActiveEntity=false” while the modified key is “IsActiveEntity=true“.
As the entity instance itself is changing ( key ) through the action , we can declare the result parameter as “entity” with an “entity type” but not $self. That helps the fiori app to identify that the result instance is different from the initial instance.
$self keeps the same instance even after action execution.
Let us take an example action “CompletePR” that sets status code to “CMPL” on the header entity.
Please note that Base/Interface view entities need to be declared in Base Behavior Definition.
action CompletePR result  entity ZRK_I_PUR_REQ_H;
The result projection view entities need to be exposed again in projection behaviour definition.
use action CompletePR result entity ZRK_C_PUR_REQ_H;
During method implementation, We have to consider that there can be mixed instances of the input entities. Hence take out draft instances and apply “EXECUTE Activate” on MODIFY ENTITIES.
At this point of time, All the instances should be having active instances. So we have to read new instances to return to the fiori app in “result” .
So let’s prepare new keys where “%is_draft = if_abap_behv=>mk-off ” to read entities to get new instances.
It’s time to populate the result parameter and please note that
%key , %tky to be filled from source instance while %param-%key to be filled from new instance. So that fiori app understands to fire “get” Call and retrive the new instance. As the result entity is an active instance, Fiori app automatically switches to display mode.
Below is the sample implementation.
METHOD CompletePR. *Modify the entities with required fields. MODIFY ENTITIES OF zrk_i_pur_req_h IN LOCAL MODE ENTITY _PRHead UPDATE FIELDS ( StatCode ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky StatCode ='CMPL' ) ). * Check if there are any draft instances? DATA(lt_draft_docs) = keys. DELETE lt_draft_docs WHERE %is_draft = if_abap_behv=>mk-off. IF lt_draft_docs IS NOT INITIAL. * EXECUTE Active only on draft instances. MODIFY ENTITIES OF zrk_i_pur_req_h IN LOCAL MODE ENTITY _PRHead EXECUTE Activate FROM VALUE #( FOR key IN keys ( %key = key-%key ) ) REPORTED DATA(activate_reported) FAILED DATA(activate_failed) MAPPED DATA(activate_mapped). ENDIF. * Change Keys to read active Instance DATA(lt_keys) = keys. LOOP AT lt_keys ASSIGNING FIELD-SYMBOL(<ls_key>). <ls_key>-%is_draft = if_abap_behv=>mk-off. ENDLOOP. * Read the active instance to send back to Fiori App. READ ENTITIES OF zrk_i_pur_req_h IN LOCAL MODE ENTITY _PRHead ALL FIELDS WITH CORRESPONDING #( lt_keys ) RESULT DATA(lt_pur_req). * Populate %key , %tky to be filled from source instance while %param-%key to be filled from new instance. result = VALUE #( for <fs_old_key> in keys for <fs_new_key> IN lt_keys WHERE ( ObjectId = <Fs_old_key>-ObjectId ) ( %key = <fs_old_key>-%key %tky = <fs_old_key>-%tky %param-%key = <fs_new_key>-%key ) ). mapped-_prhead = CORRESPONDING #( lt_pur_req ). ENDMETHOD.
As we can see, “Get” call is fired with new key and fiori app is switched to display mode.
Please share and comment your views in the comments section.
You can find my previous blogs on RAP at here .
This is very useful. Thank you for sharing Ramjee!
Thanks for the article. Could you please help me understand the diff b/w %key and %tky because you have used one modify statement with %tky and other with %key.
Yes, It is really needed to understand it better.
%key is a technical key of the business object where as %tky is a transactional key which has additional identifier whether it is draft instance or active instance.
It is not possible to identify draft or active instance with same key.
Let us take an example.
CDS BO has a key "ObjectId" = '1000001'.
I saw that you made a blog post out of your response to my community question. This is great, so it probably helps many more people. 🙂
Just in case you didn't get a notification from my last comment.
If I use the back button after the execution of the custom action, the application displays the Draft-Version again and does not navigate to the report list page. Do the navigation work correctly on your example? If yes, do you have any idea where i might have made a mistake?
Many thanks for your help!
Kind regards Florian
I checked but I have not found any solution for navigation yet and I think it is not related to custom action but framework problem.
I have compared with standard operation "SAVE" and there is also similar problem.
I'm not sure what you mean with similar error.
With the standard save operation the navigation looks good. After save action (entity was in draft mode when entering the object page) I can directly navigate back to the report list page.
But as described above with this custom action, it looks like we have two object pages. After switch to active version/display mode, it navigates to old object page (draft version/edit mode) when I use the "back button". If I use "back button" on this object page again, it navigates to the report list page.
Thanks for your help with that. Maybe you have any other idea. 🙂
Kind regards Florian
I just tested my application with OData V4 instead of V2, where we don't have the "back button" within the app. With the back navigation of the browser (tested with Edge), the navigation seems to work correctly. 🙂
Maybe you can verify this.
Thank you Florian for the hint and seems to be problem with framework V2.
thanks very much for your post!!
Can I do the same for Child entities?
I would like to merge my root entity together with all its child entities to active.
But "Execute activate" doesn't work for the child entity.
How can I do this?
As far as I remember, "Execute Active" merges all the entities of BO at once and you don't need to do for child entities separately.
Doesn't it work automatically when you Executed at parent level?
Hi Ramjee ,
I need to download a text file ( CSV ) for AR/AP and upload to an application server in Al11 .Is it possible to do end to end Fiori Elements App out of it using the RAP programing model. If so do I need to follow all the steps from creating Interface view/consumption view till expose the service bindings.