C2 - Restricted
use
Advanced-level notes for the SAP RAP (RESTful Application
Programming Model), we must look beyond simple CRUD and dive into the
orchestration of the Big Three: the Data Model, the Behavior, and the
Service.
This is a deep-dive technical guide designed for architects and senior
developers.
🚀 Advanced Technical Guide: SAP ABAP RAP
The RAP model is the "Evolutionary Successor" to BOPF and SEGW. It is
designed for Cloud-centric development, enforcing a strict separation
between the data state and the business logic.
1. Deep Dive: The Data Modeling Layer (CDS)
In RAP, the CDS (Core Data Services) is not just a view; it is the Data
Definition Language (DDL) that defines the entire entity tree.
Root Entities: Every RAP business object must have exactly one Root
Entity. This acts as the entry point for the "Composition Tree."
Compositions vs. Associations:
o Composition: Defines a parent-child relationship where the child
cannot exist without the parent (e.g., Header $\rightarrow$ Item).
o Association: A loose relationship with other data (e.g., Item $\
rightarrow$ Product Master).
Virtual Elements: Use the annotation
@[Link]: 'ABAP:CL_CALC_LOGIC' to
define fields that don't exist in the DB but are calculated at runtime via
an ABAP class.
2. The Behavior Definition (BDEF) – The "Brain"
The BDEF is a specialized object where you define the transactional
capabilities of your BO.
A. The Managed Scenario (Standard)
Best For: New tables ("Greenfield").
C2 - Restricted
use
Buffer Management: SAP handles the transactional buffer. You only
write "determinations" or "validations."
Strict Mode: Always use strict(2); in the BDEF header. This enforces
the latest cloud-compliant syntax and best practices.
B. The Unmanaged Scenario (Legacy)
Best For: Wrapping existing BAPIs or Function Modules ("Brownfield").
Responsibility: You must manually implement the FOR MODIFY and
FOR READ methods. You are responsible for the COMMIT logic (though
it must still occur during the RAP save sequence).
3. Transactional Life Cycle: The Interaction Phase
Understanding when code executes is critical for debugging.
I. Interaction Phase (Before Save)
Determinations: Triggered by field changes. Used to auto-fill data
(e.g., calculating a total price when an item is added).
o Trigger Time: on modify or on save.
Validations: Check data integrity. If a validation fails, it returns a
"failed" key and a "reported" message, stopping the save.
Actions: Custom logic (e.g., "Approve Travel Request"). These can be
factory actions (create new instances) or instance actions.
II. Save Sequence (The ACID Phase)
1. Finalize: Last chance to change data.
2. Check Before Save: Final validation.
3. Adjust Numbers: For late numbering (generating IDs).
4. Save: The data is pushed to the database.
4. State Management: Draft Handling
Draft is the most powerful feature of RAP. It allows a user to "pause" their
work.
C2 - Restricted
use
Draft Tables: SAP automatically creates _D tables.
Total ETag: A field (usually a timestamp) used to prevent multiple
users from overwriting the same record.
Transitions:
o Edit: Active Data $\rightarrow$ Draft Data.
o Activate: Draft Data $\rightarrow$ Active Data (Validations run here).
o Discard: Draft Data is deleted.
5. Advanced Implementation: The Business Object Provider (ABP)
When you implement the logic in the Behavior Pool (BP), you use EML
(Entity Manipulation Language).
Master EML Syntax:
ABAP
" Example of updating a record via EML
MODIFY ENTITIES OF ZI_Travel_Root
ENTITY Travel
UPDATE FIELDS ( Description )
WITH VALUE #( ( TravelID = '123' Description = 'Updated' ) )
REPORTED DATA(lt_reported)
FAILED DATA(lt_failed).
FAILED: Contains the keys of records that didn't process.
REPORTED: Contains the T100 messages to be displayed on the Fiori
UI.
MAPPED: Contains the mapping of temporary IDs to final IDs.
6. Service Exposure (The API Layer)
C2 - Restricted
use
1. Service Definition (SRVD): You select which entities to expose. You
usually alias them for the UI (e.g., expose ZI_TRAVEL_M as Travel;).
2. Service Binding:
o OData V2 UI: Higher compatibility with older Fiori tools.
o OData V4 UI: Modern, faster, uses less bandwidth (Batch processing
is superior).
o Web API: For system-to-system integration (no Fiori UI annotations
needed).
7. Performance Optimization Strategies
Bypass Buffer: When using EML, use FROM READ to get data from the
buffer instead of the DB to save hits.
Select Only What You Need: Use the FIELDS addition in EML to
avoid fetching large BLOBs or unnecessary columns.
Internal Tables: Always use SORTED or HASHED tables when
processing MAPPED, FAILED, or REPORTED data in high-volume
scenarios.
📝 Downloadable Summary Table
Compone Object Type Responsibility
nt
Data CDS View Entity Joins, Associations, Aggregations
Model
Behavior BDEF Defining Actions, Validations,
Determinations
Logic ABAP Class (BP) EML Code, BAPI Calls, Business Rules
C2 - Restricted
use
UI Metadata Field labels, Positioning, Hide/Show
Control Extensions
Security DCL Row-level authorization
This advanced technical blueprint covers the end-to-end architecture of the
SAP RAP (RESTful Application Programming) Model, focusing on the
"Managed" scenario with Draft capabilities, as this is the industry standard
for S/4HANA development.
Advanced Technical Architecture: SAP RAP Deep Dive
The RAP model is a "Top-Down" development approach. Unlike the classical
"Bottom-Up" (SE11 $\rightarrow$ SE37 $\rightarrow$ SEGW), RAP starts with
the Data Model and uses Annotations to drive the UI and Framework
behavior.
1. The Data Layer: CDS View Entities
In modern ABAP, we use DEFINE VIEW ENTITY instead of the older DEFINE
VIEW. View entities are faster and do not create a redundant SQL view in the
DDIC.
Key Advanced Annotations:
@[Link]: true: Decouples UI logic from the
data model.
@[Link]: Defines performance expectations (e.g.,
#DATA_CLASS: #TRANSACTIONAL).
@[Link]: true: Enables the fuzzy search bar in Fiori.
Composition Tree:
A business object is a tree. The Root Entity holds the header, and
Compositions define the children.
ABAP
define root view entity ZI_Header_TP
C2 - Restricted
use
composition [0..*] of ZI_Items_TP as _Items
key HeaderUUID,
OrderNumber,
_Items // Targeted association
2. The Behavior Definition (BDEF)
This is the "Contract" of your Business Object. It is written in a domain-
specific language (DSL).
Essential Components:
persistent table <TABLE_NAME>: Where data is saved.
draft table <D_TABLE_NAME>: Where "in-progress" data is stored.
lock master: Handles concurrency (pessimistic locking).
etag master <LocalLastChangedAt>: Handles optimistic locking to
prevent "lost updates."
Internal vs. External Actions:
Internal Actions: Can only be called by the BO itself (e.g., status
updates).
External Actions: Visible as buttons on the Fiori UI (e.g., "Post
Invoice").
3. The Behavior Pool (ABAP Class)
The logic is implemented in Local Types within a Global Class. The global
class is usually empty; the heavy lifting happens in LHC_<ENTITY_NAME>.
A. Determinations (The "Auto-Fill")
Triggered automatically. Use these for calculating totals or defaulting the
"Created By" user.
C2 - Restricted
use
Best Practice: Use on modify for immediate UI feedback; use on save
for performance-heavy calculations.
B. Validations (The "Gatekeeper")
Validations check the state of the BO. If the check fails:
1. Populate the FAILED table with the key.
2. Populate the REPORTED table with a message (using
new_message_with_text).
4. Entity Manipulation Language (EML)
EML is the language used to talk to RAP Business Objects. It replaces MODIFY
FROM or CALL FUNCTION.
Deep Update Example:
ABAP
MODIFY ENTITIES OF ZI_Header_TP
ENTITY Header
UPDATE FIELDS ( Status )
WITH VALUE #( ( %tky = ls_key Status = 'A' ) )
ENTITY Header EXECUTE SetToDelivered
FROM VALUE #( ( %tky = ls_key ) )
FAILED DATA(lt_failed)
REPORTED DATA(lt_reported).
%tky (Transactional Key): Crucial for Draft handling. It automatically
points to either the Draft or Active table depending on the context.
5. Draft & The State Area
Draft handling allows Stateful behavior on a Stateless OData protocol.
C2 - Restricted
use
Exclusive Lock: When a user edits a Draft, an exclusive lock is placed
on the Active record.
Field Control: You can define fields as ( readonly ), ( mandatory ), or (
features: instance ) to dynamically hide/show fields based on status.
6. Service Exposure & Consumption
Service Definition (SRVD)
Exposes the required entities. Keep this "clean"—only expose what the UI
needs.
ABAP
@[Link]: 'Service for Sales'
define service ZUI_SALES_V4 {
expose ZI_Header_TP as SalesOrder;
expose ZI_Items_TP as Items;
Service Binding
OData V4: Use this for all new development. It supports "Collapse"
and "Expand" more efficiently and has better performance for large
data sets.
7. Advanced Debugging & Troubleshooting
1. ADT Debugger: Use the "ABAP Cross Trace" to see exactly which EML
calls are failing.
2. SQL Trace (ST05): Since RAP is highly optimized, it generates
complex SQL. Use ST05 to ensure your CDS views aren't causing
"Sequential Reads."
3. Check View Browser: Use the SAP Fiori app "View Browser" to verify
the annotation propagation across your CDS hierarchy.
C2 - Restricted
use
📥 Summary Checklist for Advanced RAP
1. Strict Mode: Ensure strict(2); is in your BDEF.
2. Concurrency: Use Total ETag for draft-enabled scenarios.
3. Side Effects: Define them in the Metadata Extension to refresh the UI
when an Action or Determination changes data.
4. Virtual Elements: Implement IF_SADL_EXIT_CALC_ELEMENT_READ for
on-the-fly logic.
This real-world scenario will focus on a Travel Management System. We
will build a "Managed" Business Object with Draft capabilities, featuring a
validation to check dates and an action to "Approve" the travel.
✈️Real-World Scenario: Travel Approval System
In this scenario, we have a Parent (Travel) and a Child (Booking). We will
implement strict business rules using the RAP framework.
1. The Data Model (CDS View Entities)
First, we define the hierarchy. The Root entity manages the lifecycle and
locking.
Root Entity: ZR_Travel_TP
ABAP
@[Link]: #NOT_REQUIRED
@[Link]: 'Travel Root Entity'
define root view entity ZR_Travel_TP
as select from ztravel_table
composition [0..*] of ZR_Booking_TP as _Booking
key travel_uuid as TravelUUID,
travel_id as TravelID,
agency_id as AgencyID,
customer_id as CustomerID,
C2 - Restricted
use
begin_date as BeginDate,
end_date as EndDate,
@[Link]: 'CurrencyCode'
total_price as TotalPrice,
currency_code as CurrencyCode,
overall_status as OverallStatus,
local_last_changed_at as LocalLastChangedAt, -- For ETag
last_changed_at as LastChangedAt -- For Total ETag
/* Associations */
_Booking
2. The Behavior Definition (BDEF)
This is where we define the "Capabilities" of our system, including Draft and
Actions.
ABAP
managed implementation in class zbp_r_travel_tp unique;
strict ( 2 );
with draft;
define behavior for ZR_Travel_TP alias Travel
persistent table ztravel_table
draft table ztravel_d // Automatically generated draft table
lock master total etag LastChangedAt
etag master LocalLastChangedAt
C2 - Restricted
use
create;
update;
delete;
// Actions
action ( features : instance ) acceptTravel result [1] $self;
// Validations
validation validateDates on save { field BeginDate, EndDate; }
// Determinations
determination calculateTotalPrice on modify { create; field TotalPrice; }
draft action Edit;
draft action Activate;
draft action Discard;
draft action Resume;
association _Booking { create; with draft; }
mapping for ztravel_table {
TravelUUID = travel_uuid;
AgencyID = agency_id;
// ... other fields
}
C2 - Restricted
use
3. Deep Dive: The Logic (Behavior Pool)
We implement the logic in the Local Types tab of the global class
ZBP_R_TRAVEL_TP.
A. Implementing the Action (Accept Travel)
This method updates the status of the travel record.
ABAP
METHOD acceptTravel.
" Modify the entity status to 'Accepted' (A)
MODIFY ENTITIES OF ZR_Travel_TP IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( OverallStatus )
WITH VALUE #( FOR key IN keys ( %tky = key-%tky OverallStatus =
'A' ) )
FAILED failed
REPORTED reported.
" Read the updated data to return it to the UI
READ ENTITIES OF ZR_Travel_TP IN LOCAL MODE
ENTITY Travel
ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel).
result = VALUE #( FOR travel IN lt_travel ( %tky = travel-%tky %param =
travel ) ).
ENDMETHOD.
C2 - Restricted
use
B. Implementing the Validation (Date Check)
If the end date is before the start date, we must stop the save.
ABAP
METHOD validateDates.
READ ENTITIES OF ZR_Travel_TP IN LOCAL MODE
ENTITY Travel
FIELDS ( BeginDate EndDate ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel).
LOOP AT lt_travel INTO DATA(ls_travel).
IF ls_travel-EndDate < ls_travel-BeginDate.
APPEND VALUE #( %tky = ls_travel-%tky ) TO failed-travel.
APPEND VALUE #( %tky = ls_travel-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'End Date cannot be before Begin Date!' )
%element-EndDate = if_abap_behv=>mk-on ) TO reported-
travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
4. Interaction Phase: Side Effects
In advanced Fiori apps, when you click "Accept Travel," you want the status
color to change immediately without a manual refresh. You define this in the
Metadata Extension (MEXT) or via the BDEF.
ABAP
C2 - Restricted
use
// In the BDEF or a dedicated Side Effects side-car
side effects {
action acceptTravel affects field OverallStatus;
5. Summary of Advanced Key-Value Pairs
IN LOCAL MODE: This keyword is vital. It allows the behavior pool to
modify its own fields without triggering a permission check or a
recursive loop.
%tky: This stands for Transactional Key. In a draft-enabled BO, %tky
automatically includes the %is_draft flag. It ensures your logic works
whether the user is in "Edit Mode" or has already "Saved."
reported: This is a deep structure. Use %element-fieldname =
if_abap_behv=>mk-on to highlight the specific input field on the UI
that has the error.
📝 Final Checklist for your RAP Object
1. Database Tables: Created with UUIDs as keys for best RAP
compatibility.
2. Draft Tables: Generated via the "Quick Fix" (Ctrl+1) in Eclipse.
3. Service Binding: Published as OData V4 - UI.
4. Authorization: Ensure you have a DCL (Data Control Language) file if
you need row-level security (e.g., users can only see their own travels).
In a professional production environment, data security is non-negotiable.
While the Behavior Definition (BDEF) handles what a user can do
(Actions/CRUD), the Data Control Language (DCL) handles which specific
rows of data a user is allowed to see.
This is the final "Deep Level" layer of the RAP model.
C2 - Restricted
use
🔐 Advanced Security: Data Control Language (DCL) in RAP
In RAP, security is "implicit." Once you define a DCL for a CDS entity, the SAP
database interface automatically injects WHERE clauses into every OpenSQL
and EML statement. The developer does not need to manually check
permissions in the ABAP code.
1. Defining the Access Control
To restrict our Travel App so that agents can only see travels belonging to
their specific Agency ID, we create an Access Control object in ADT.
Syntax:
ABAP
@[Link]: 'Access Control for Travel'
@MappingRole: true
define role ZI_Travel_Auth {
grant
select
on ZR_Travel_TP
where
( AgencyID ) = aspect pfcg_auth( ZAGENCY_O, ZAGENCYID,
ACTVT = '03' );
Breakdown of the Code:
aspect pfcg_auth: This bridges the gap between the CDS view and
the classical SAP Authorization Object (ZAGENCY_O).
ZAGENCYID: The field in the Authorization Object that holds the
allowed values.
ACTVT = '03': This ensures the restriction only applies to "Display"
activity.
C2 - Restricted
use
2. Advanced Dynamic Instance Authorization
Sometimes, simple row-level filtering isn't enough. You might need logic like:
"A manager can delete a travel request only if the status is 'New', but not if
it is 'Approved'."
This is handled via Instance Authorization in the BDEF.
Step 1: Update BDEF
ABAP
define behavior for ZR_Travel_TP alias Travel
...
authorization master ( instance )
update;
delete;
action acceptTravel;
Step 2: Implement Logic in the Behavior Pool
The framework will call the method get_instance_authorizations.
ABAP
METHOD get_instance_authorizations.
READ ENTITIES OF ZR_Travel_TP IN LOCAL MODE
ENTITY Travel
FIELDS ( OverallStatus ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_travel).
LOOP AT lt_travel INTO DATA(ls_travel).
" If travel is already approved (A), disable the delete and update actions
C2 - Restricted
use
IF ls_travel-OverallStatus = 'A'.
APPEND VALUE #( %tky = ls_travel-%tky
%update = if_abap_behv=>auth-exclusive
%delete = if_abap_behv=>auth-exclusive ) TO result.
ENDIF.
ENDLOOP.
ENDMETHOD.
3. Integration: The Full Technical Flow
To master RAP, you must visualize how a single click on a Fiori App travels
through these layers:
1. Fiori Elements UI: User clicks "Delete."
2. OData Gateway: Receives the request and identifies the Business
Object.
3. DCL Layer: Checks if the user is even allowed to see that row.
4. Instance Authorization: Runs the ABAP logic in
get_instance_authorizations to see if "Delete" is valid for the current
status.
5. BDEF Validations: Runs validateDates to ensure data integrity.
6. Database: If all pass, the row is deleted from the persistent table.
4. Summary Table: Authorization Types
Type Object Purpose
Static / Row DCL Filters data based on Org Units (Company
Level Code, Agency).
Global Auth BDEF / Checks if a user has the "Role" to create a
C2 - Restricted
use
Class record at all.
Instance BDEF / Checks if a specific record can be changed
Auth Class based on its state.
🎓 Professional Certification Tip
If you are preparing for the C_ABAPD (ABAP Cloud Certification),
remember that Managed RAP objects are preferred over Unmanaged, and
OData V4 is the standard for S/4HANA Public Cloud.
This concludes the deep-dive technical notes. Would you like a Final
Comprehensive Quiz with 10 high-level technical questions to test your
knowledge of these notes?