Custom Actions and InvocationGrouping (#CHANGE_SET AND #ISOLATED ) in ABAP Restful Application Programming.
Satya Prakash Tiwari
Certified SAP ABAP on HANA /ABAP/Fiori consultant at Deloitte | Ex-IBM | Ex-Accenture | Ex-Wiproite
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.
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.
Since its managed application ,framework is taking care of standard operations such as Create, Update and Delete hence button are provided for the actions.
@UI: { lineItem: [
{ type: #FOR_ACTION, dataAction: 'acceptTravel', label: 'Accept Travel' } ]}
]
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 ;
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 .
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.
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).
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)
Click "Accept Travel" Button.
Status changed to A(Approved).
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 )
).
Activate all including service binding and refresh the UI .
Travel ID 11 is having status A and button "Accept Travel " is disabled.
Whereas if status is O(Open) , button is enable.
That's how we can make use of { features : instance} .
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).
#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
S/4 HANA Technical Architect @ IBM | ABAP, ABAP-OO, RAP
3 个月Great stuff.
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