Custom Actions and InvocationGrouping (#CHANGE_SET AND #ISOLATED ) in ABAP Restful Application Programming.

Custom Actions and InvocationGrouping (#CHANGE_SET AND #ISOLATED ) in ABAP Restful Application Programming.

Introduction

Before we dive into the details, let's briefly review the concept of the managed and unmanaged scenarios in Restful ABAP programming.


The managed scenario can handle basic functions of a transactional application on its own, while in the unmanaged scenario, the developer has to use existing pre-defined logic to handle the transactional application.


For the unmanaged implementation type, the application developer must implement essential components of the REST contract manually.


Whereas in managed scenario, all required standard operations (create, update, delete) must only be specified in the behavior definition to obtain a ready to-run business object


Let's revisit the terms "behavior definition" and "implementation class" in the context of Restful ABAP programming. These concepts are similar to the DPC_EXT class, where we define custom logic to handle specific functionalities in Fiori applications. We use these concepts when developing OData services that will be consumed by Fiori applications.





No alt text provided for this image
Development Objects Involved When Implementing Managed Transactional Apps reference link provided at last of article



Designing the business object is a critical aspect when developing a transactional application using ABAP RAP. It plays a vital role in the overall development process and is essential for ensuring the success and effectiveness of the application.





Lets us start with our Agenda i.e. Creation of Custom Action button on UI Screen


Expectation is to create a button on below UI named "Accept Travel" to change the travel status to Approved(A) the moment user is selecting the record and click on Accept Travel Button.


No alt text provided for this image


Since its managed application ,framework is taking care of standard operations such as Create, Update and Delete hence button are provided for the actions.


  1. Define below annotation on projection CDS w.r.t field that has to be manipulated(on which field action has to be performed) .


   @UI: { lineItem: [ 
      { type: #FOR_ACTION, dataAction: 'acceptTravel', label: 'Accept Travel' } ]} 
]                  




Action Annotation
Action Annotation

Activate Binding .





We will talk about additional binding in next article.


2. We need to define this button in behaviour defination ,use below syntax.



action(features : instance) dataAction  result[1] $self ;        

No alt text provided for this image
features : instance

By defining the feature instance for a custom action, we are specifying the specific functionality that will be executed when the action is triggered or invoked. This allows us to extend the capabilities of our application and customize it according to our specific requirements.

We will use this feature in later part of this article .


Now we have defined custom action on behaviour defination level ,framework will ask to create its method in implementation class to write custom logic .



Press CNTRL+1 to quick fix and system will create the method in implementation class .


No alt text provided for this image
Framework has created two methods in implementation class .


Method accepttravel - is to add code to handle action button


Method get_instance_features - is to define button scope ,extend/limit the capabilities .


We need to add action in projection behaviour defination as well .


use action acceptTravel;        

Activate All including service binding and refresh UI.


Action button "Accept Travel " is visible on screen but there is no code written yet to handle user expectations.



No alt text provided for this image




3. Let us write code in Method accepttravel to achieve our expectations i.e. change the travel status to Approved(A) on the click of Approve Travel button.


We are directly updating the field (overall_status) to A (Approved) through Entity manipulation language.


    MODIFY ENTITIES OF zi_travel_m_may IN LOCAL MODE
    ENTITY travel " Alias 
    UPDATE
    FIELDS ( overall_status )
    WITH VALUE #( FOR key IN  keys ( %tky = key-%tky overall_status = 'A' ) )
    FAILED DATA(lt_failed)
    REPORTED DATA(lt_reported).        



No alt text provided for this image


We have discussed about EML in my last article .


Activate all including service binding and refresh UI.


Lets select record 11 that is having travel status as O (Open)


No alt text provided for this image


Click "Accept Travel" Button.

Status changed to A(Approved).

No alt text provided for this image

That's how we can add multiple number of actions on UI .



What should happen if user is selecting record that is already in A(Approved) state ?


It would be better if the button is disabled when the travel status is already approved .


In this scenario { features : instance} comes into picture that we have mentioned in behaviour defination while defining action.


Framework has already created method get_instance_features to implement such logic.


Let us write code in method get_instance_features to enable the button only if travel status is in O(Open) state .


To achieve this first we need to read data that user has selected from UI.


    READ ENTITIES OF zi_travel_m_may IN LOCAL MOD
    ENTITY travel
    ALL FIELDS WITH CORRESPONDING #( keys )
    RESULT DATA(lt_travel_instance).        

lt_travel_instance will hold the selected data of UI.


Now we will check if travel status is O then keep button enable otherwise disable and update the RESULT parameter.


%action-acceptTravel will hold value that enable/disable button (if_abap_behv=>fc-o-enabled / if_abap_behv=>fc-o-disabled )



    result = VALUE # (
             FOR wa_travel_instance IN lt_travel_instance
             LET statusinstance = COND #(
                       WHEN wa_travel_instance-overall_status = 'O'
                       THEN if_abap_behv=>fc-o-enabled
                       ELSE if_abap_behv=>fc-o-disabled )
                       IN ( %tky = wa_travel_instance-%tky
                            %action-acceptTravel = statusinstance )
                       ).        



No alt text provided for this image


Activate all including service binding and refresh the UI .


Travel ID 11 is having status A and button "Accept Travel " is disabled.
No alt text provided for this image


Whereas if status is O(Open) , button is enable.


No alt text provided for this image


That's how we can make use of { features : instance} .



#CHANGE_SET

We have implemented custom action button that can change travel status to Approved . Limitation is it can process only one travel request at a time.


What if user wants to select multiple travel request and approve all request at one hit.


In such scenarios where we need to process multiple line items at once , we go with invocationGrouping: #Change_set .


We need to add invocationGrouping: #Change_set in @UI.LineItem annotation .



? @UI: 
? ? ? lineItem: [{ position: 60,
? ? ? ? ? ? ? ? ? ?label: 'Accept Travel',
? ? ? ? ? ? ? ? ? ?type: #FOR_ACTION,
? ? ? ? ? ? ? ? ? ?dataAction: 'acceptTravel',
? ? ? ? ? ? ? ? ? ?invocationGrouping: #Change_set??
? ? ? ?}]        


In action method ,we need to keep the loop at UI data and make changes in desired fields . Framework will update all selected key field at once.



Since there is radio button available in RAP FIORI preview , we cant select multiple line items from UI.



This case is only possible when we create FIORI application through BAS .



In Fiori application , we can make multiple selection from UI by doing small change in manifest.json i.e. (making tableSettings??multiSelect?property is set to?true).




#ISOLATE

#CHANGE_SET works to achieve LUW (Logical unit of work ) i.e. either it will make changes in all selected key or none of them .



Lets say we are processing 10 records from UI and 4 records have error , in such case #CHANGE_SET will report the error and process 0 records.



If user wants to see error of 4 records and simultaneously expects execution of remaining 6 records . In such scenarios we use invocationGrouping: #ISOLATED



? @UI:
? ? ? lineItem: [{ position: 60,
? ? ? ? ? ? ? ? ? ?label: 'Accept Travel',
? ? ? ? ? ? ? ? ? ?type: #FOR_ACTION,
? ? ? ? ? ? ? ? ? ?dataAction: 'acceptTravel',
? ? ? ? ? ? ? ? ? ?invocationGrouping: #ISOLATE??
? ? ? ?}]         


Implementation would be remain same as #CHANGE_SET .






For more details on ABAP Restful programming model ,visit below link. https://help.sap.com/doc/3750bcdf7b8045e18f1b759e6d2b000b/Cloud/en-US/ABAP_RESTful_Programming_Model_EN.pdf
Ravi Singh

S/4 HANA Technical Architect @ IBM | ABAP, ABAP-OO, RAP

3 个月

Great stuff.

回复
srinivas pandyan

Associate Director, PWC

5 个月

Hi Satyaprakash, I am facing as issue with Custom action with parameter. I have only Object page without any standard actions. i have added a custom action. Read entities is showing blank in custom action method. not sure what am i missing. Data is not being passed from UI to method. Thanks, Pandyan

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了