ABAP RAP Tutorial - Part 1
ABAP RAP Tutorial - Part 1
Objective: The aim of this document is to show you how to create ABAP RAP UI
applications using Managed scenario. The document provides working ABAP Code as
reference for implementing a fully functional application with navigation to object
page, child entities, CUD functionalities, Behavior implementation for Actions,
Determinations and Validations, CDS Search Helps, Virtual Elements and handling
attachments.
1
Page
Contents:
1. Database Tables … 3
2. ABAP console program to maintain test data … 4
3. CDS Data Definitions … 6
4. CDS Value Helps … 9
5. Metadata extension with UI annotations … 10
6. Behavior Definition … 12
7. Implementation of Behavior Definition … 13
8. Service Definition … 15
9. Service Binding … 16
10. Handling CUD operations for Child Entities … 20
11. Demo on Advanced Feature Control …
12. Virtual Elements … 23
13. Demo on Upload Attachments … 32
14. Reference … 39
15. About the author … 40
2
Page
Step 1: Code to create custom tables (The data element details have not been
provided, these can be created in system as required) *
}
3
Page
Step 2: Code to maintain data in the custom tables created above for initial setup.
PUBLIC SECTION.
METHOD if_oo_adt_classrun~main.
DATA: lt_classes TYPE STANDARD TABLE OF zpsb_classes WITH DEFAULT KEY,
lw_classes TYPE zpsb_classes,
lt_admission_stat TYPE STANDARD TABLE OF zpsb_adm_stat WITH DEFAULT KEY,
lt_studentmaster TYPE STANDARD TABLE OF zpsb_stud_master,
4
DO 12 TIMES.
lw_classes-class = lw_classes-class + 1.
APPEND lw_classes TO lt_classes.
ENDDO.
INSERT zpsb_classes FROM TABLE @lt_classes.
IF sy-subrc = 0.
COMMIT WORK AND WAIT.
out->write( 'Data saved for Classes.' ).
ENDIF.
( aadhar = '2003110752000001'
admissionstatus = 'Rejected'
dob = '19930318'
dtofadmission =
cl_abap_context_info=>get_system_date( )
fname = 'Sampat'
mname = 'Singh'
lname = 'Bist'
class = '12'
contact = '9163512445'
plofbirth = 'Dehradun' ) ).
parenttype = 'F'
contact = '9163554321'
fname = 'Shilpi'
lname = 'Bist'
occupation = 'Housewife'
qualification = 'Graduate' )
( studentaadhar = '2003110752000000'
parenttype = 'M'
contact = '9163554320'
fname = 'Sampat'
lname = 'Bist'
occupation = 'IFS'
qualification = 'Post Graduate' ) ).
ENDMETHOD.
ENDCLASS.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Student Master'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@Search.searchable: true
define view entity ZPSB_I_STUD_MASTER
as select from zpsb_stud_master
{
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.9
key aadhar as Aadhar,
fname as FirstName,
mname as MiddleName,
lname as LastName,
dob as DateofBirth,
plofbirth as PlaceofBirth,
6
class as Class,
Page
contact as Contact,
email as Email,
dtofadmission as DateofAdmission,
admissionstatus as AdmissionStatus
}
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Student Parent Relation'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@Search.searchable: true
define view entity ZPSB_I_STUD_PARENT
as select from zpsb_stud_parent
{
@Search.defaultSearchElement: true
key studentaadhar as Studentaadhar,
key parenttype as Parenttype,
fname as FirstName,
mname as MiddleName,
lname as LastName,
qualification as Qualification,
occupation as Occupation,
contact as Contact,
email as Email,
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Student Master Root View'
@Metadata.allowExtensions: true
@Metadata.ignorePropagatedAnnotations: true
define root view entity ZPSB_UI_STUDENT_MASTER
as select from ZPSB_I_STUD_MASTER
composition[0..*] of ZPSB_UI_STUD_PARENT as _tostudentparent
{
key Aadhar,
FirstName,
MiddleName,
LastName,
DateofBirth,
PlaceofBirth,
Class,
7
Contact,
Page
Email,
DateofAdmission,
AdmissionStatus,
_tostudentparent
}
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Student Parent Root View'
@Metadata:{ allowExtensions: true, ignorePropagatedAnnotations: true}
define view entity ZPSB_UI_STUD_PARENT
as select from ZPSB_I_STUD_PARENT
association to parent ZPSB_UI_STUDENT_MASTER as _tomaster on
$projection.Studentaadhar = _tomaster.Aadhar
{
key Studentaadhar,
key Parenttype,
FirstName,
MiddleName,
LastName,
Qualification,
Occupation,
Contact,
Email,
Salary,
Currency,
_tomaster
}
@AccessControl.authorizationCheck: #NOT_REQUIRED
Page
as projection on ZPSB_UI_STUD_PARENT
{
key Studentaadhar,
key Parenttype,
FirstName,
MiddleName,
LastName,
Qualification,
Occupation,
Contact,
Email,
Salary,
Currency,
_tomaster : redirected to parent ZPSB_UIP_STUDENT_MASTER
}
Step 4: Create CDS DDL for some search helps required in the demo.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Search Help on admission status'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@Search.searchable: true
define view entity ZPSB_I_SHLPAD_M_STAT as select from zpsb_adm_stat
{
@Search.fuzzinessThreshold: 0.8
@Search.defaultSearchElement: true
key status as Status
}
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Search Help on Class'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
@Search:{searchable: true}
define view entity ZPSB_I_SHLP_CLASS
as select from zpsb_classes
{
@UI.hidden: false
9
@EndUserText:{ label: 'Class', quickInfo: 'Class the student has enrolled for' }
Page
@Search.defaultSearchElement: true
@Search.fuzzinessThreshold: 0.8
key class as Class
Step 5: Create the UI metadata extensions for the Root View and the View Entity
created in Step 3.
@Metadata.layer: #CORE
@UI.headerInfo.typeName: 'Student'
@UI.headerInfo.typeNamePlural: 'Students'
annotate view ZPSB_UI_STUDENT_MASTER with
{
@UI.facet: [{ id:'Student', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, Commented [BP2]: When the object page has to show
label: 'Student Details',position: 10 }, additional fields of the current entity
{ id:'Parent', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label:
'Parent Details', position: 20, targetElement: '_tostudentparent'}] Commented [BP3]: When the object page has to show
details from an association.
@UI:{ selectionField: [{ position: 10 }], Commented [BP4]: Free search
lineItem: [{ position: 10, label: 'Aadhar UID Number' },
{ type: #FOR_ACTION, dataAction: 'Action_AcceptStudent', label: Commented [BP5]: To show an action button on the Fiori
'Accept Admission' }], UI
identification: [{ position: 10, label: 'Aadhar UID Number' }] }
Aadhar; Commented [BP6]: To show the fields in the Object Page
@UI.selectionField: [{ position: 60 }]
@UI.identification: [{ position: 70, label: 'Class' }]
Page
@Metadata.layer: #CORE
@UI.headerInfo.typeName: 'Parent'
@UI.headerInfo.typeNamePlural: 'Parents'
annotate view ZPSB_UI_STUD_PARENT with
{
FirstName;
Class,
DateofBirth,
Contact,
FirstName,
LastName,
AdmissionStatus;
create;
update;
delete;
projection;
strict ( 2 );
CLASS lhc_ZPSB_UI_STUDENT_MASTER DEFINITION INHERITING FROM cl_abap_behavior_handler. Commented [BP10]: 1.The behavior definitions are
PRIVATE SECTION. implemented in a local class inside the behavior
13
implementation class.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION 2.RAP uses EML for data manipulation
Page
IMPORTING keys REQUEST requested_authorizations FOR StudentMaster RESULT 3.Do not write COMMIT as the framework will take care of
result. all commits.
ENDCLASS.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD Validate_Class.
READ ENTITIES OF zpsb_ui_student_master IN LOCAL MODE
ENTITY StudentMaster
FIELDS ( Class ) WITH CORRESPONDING #( Keys )
RESULT DATA(lt_studentmaster).
METHOD Determine_DOA.
DATA(lv_current_date) = cl_abap_context_info=>get_system_date( ) .
ENDLOOP.
ENDMETHOD.
METHOD Action_AcceptStudent.
MODIFY ENTITIES OF zpsb_ui_student_master IN LOCAL MODE
ENTITY StudentMaster
UPDATE
FIELDS ( AdmissionStatus ) WITH VALUE #( FOR key IN keys ( %tky = key-%tky
AdmissionStatus = 'Accepted' ) ).
METHOD get_instance_features.
READ ENTITIES OF zpsb_ui_student_master IN LOCAL MODE
ENTITY StudentMaster
FIELDS ( AdmissionStatus ) WITH CORRESPONDING #( keys )
RESULT data(lt_studentmaster)
FAILED data(lt_failed).
THEN if_abap_behv=>fc-o-enabled
ELSE if_abap_behv=>fc-o-disabled )
IN ( %tky = lw_studentmaster-%tky
%action-Feature_SendLetter = statusval ) ).
ENDMETHOD.
METHOD Feature_SendLetter.
ENDMETHOD.
ENDCLASS.
Step 8: Create a service definition using the behavior projection and expose the
entities.
Screenshot-01
Screenshot-02
Page
Screenshot-03
In the screenshot above as the Admission Status is Accepted you are allowed to send the welcome
letter.
Screenshot-04
In the screenshot above as the Admission Status is Rejected and you are not allowed to send the
welcome letter, the UI greys out the button.
Select the record with Admission Status as Rejected and click on Accept Admission and the status will
change to Accepted and the Send Welcome Letter will be active.
17
Page
Screenshot-05
18
Screenshot-06
Page
Try to Edit the Student Details and enter Class as 13, the validation will kick in and show the error-
Screenshot-07
We also had a determination so, let’s create a new entry via the UI now.
Screenshot-08
Press Create.
19
Page
Screenshot-09
The Date of Admission is auto-populated as per the code for the determination in the behavior pool
class.
Additional Features:
1. To enable the CUD for the composition child, we must enhance the behavior definition and the
behavior projection as follows. The code highlighted in yellow is the new code added to the
existing code we wrote for the basic application.
managed ;
strict ( 2 );
DateofBirth,
Contact,
FirstName,
LastName,
AdmissionStatus;
create;
update;
delete;
association _tomaster;
update;
delete;
Studentaadhar = studentaadhar;
Parenttype = parenttype;
Page
FirstName = fname;
MiddleName = mname;
LastName = lname;
Contact = contact;
Email = email;
Occupation = occupation;
Qualification = qualification;
Salary = salary;
Currency = currency;
}
}
projection;
strict ( 2 );
We can see that the CUD options are now available for the UI Facet Parent Details
implemented by the composition child ZPSB_UI_STUD_PARENT (See the screenshot below).
So, the new changes are working as expected.
22
Page
Screenshot-10
2. Now let’s have some more control on the create feature on the composition
child, if the age of the student is equal to or over 18 years then we do not
need the parent details and the create feature should be disabled. This
basically means we are controlling the features of the child entities now.
3. Add a virtual element in the Student Header that shows the current academic
performance of the student as Good, Mediocre or Poor.
The points to note are that the Virtual Element is not part of the persistent
layer and only defined in the selection list of the projection root view
entity. The value for the Virtual Element is calculated by an ABAP Class that
implements the interface - if_sadl_exit_calc_element_read.
So, in our demo let’s call that virtual element as AcademicPerformance, and
let’s add it to the projection view entity of StudentMaster.
23
Page
So, let’s implement the class – ZCL_PSB_ACADEMICS. This class will implement
the interface- IF_SADL_EXIT_CALC_ELEMENT_READ and this has 2 important
methods.
▪ calculate: This method is called after the data retrieval. It uses the values
of the relevant elements to calculate the value for the virtual element.
In our example, we will read the academic details available for the latest
enrolled class of the student and calculate the % to label it as Good,
Mediocre or Poor. If the % is >= 70 it’s Good, % < 70 and % >= 50 then
Mediocre and if the % < 50 then it would be called Poor.
24
Page
METHOD if_sadl_exit_calc_element_read~calculate.
DATA: lt_original_data TYPE STANDARD TABLE OF zpsb_uip_student_master
WITH DEFAULT KEY,
lv_total TYPE p LENGTH 5 DECIMALS 2,
lv_percentage TYPE p LENGTH 5 DECIMALS 2,
lv_performance TYPE c LENGTH 10.
lv_performance = 'Poor'.
ELSEIF lv_percentage < 70 AND lv_percentage >= 50.
lv_performance = 'Mediocre'.
ENDIF.
CATCH cx_sy_itab_line_not_found.
ENDTRY.
ENDMETHOD.
ENDCLASS.
Now, we must create a metadata extension for the Projected Root View Entity.
This is because of the Virtual Element that exists in the Projected Root View
Entity and not the Root View Entity
26
Page
Now how about adding some criticality to add more visual impact.
So, let’s add the criticality based on the admission status. If Accepted then
Green else if Rejected then Red and for exceptions it is Grey (Neutral).
28
Page
Now enhance the metadata extension created for the Projection Root View
Entity- ZPSB_UIP_STUDENT_MASTER. The UI annotation for AdmissionStatus- Line
Item now adds a new component called criticality that refers to the field –
AdmissionStatusCriticality.
30
Page
Activate all the artifacts, refresh the service binding, and execute the
preview to check the output.
Select the student and press the action Accept Admission and then we have-
31
Page
4. Upload attachment (picture of the student) in the parent entity for the
student master record.
In most real-world cases, people would like to add attachments. In the past the RAP
model did not support it but now it does. And the steps to add an attachment in our
Student Header- Parent entity would be a few simple steps described below.
32
Page
4.1 Add the 3 new fields highlighted in the screenshot in the ZPSB_STUD_MASTER
table. The 3 fields are Attachment, File name and the Mime Type.
33
Page
4.2 Add the 3 new fields added in the database table to the interface view
ZPSB_I_STUD_MASTER. Note the annotations used @semantics.largeObject and
@semantics.mimeType. Commented [BP13]: Large Objects (LOB) allows the
handling of attachment in the ABAP RAP Framework
34
Page
4.3 Add the fields in the View Entity and the Projection of the View Entity.
35
Page
36
Page
4.4 Update the metadata extension of the Parent Entity with the new fields.
37
Page
4.5 Update the field-mapping of the root entity in the behavior definition.
38
Page
Reference(s):
1. https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/2
89477a81eec4d4e84c0302fb6835035.html
2. https://open.sap.com/courses/cp13
3. https://developers.sap.com/tutorials/abap-environment-behavior.html
4. https://help.sap.com/docs/abap-cloud/abap-rap/working-with-large-
objects?version=sap_btp
5. https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/d
f0ef4aac2d34fdd948b8a8883df3a1f.html?q=virtual%20
39
Page
Prasenjit Singh Bist is an SAP Certified ABAP Developer, with almost 16 years of
experience in SAP custom development with strong expertise in latest technologies.
He has worked in multiple SAP ECC and S/4HANA implementation projects. He has strong
expertise in ABAP Objects, Design patterns, ABAP CDS, ABAP RESTful Application
Programming, ABAP on HANA, BOPF, IDOC and ODATA services.
40
Page