Sap rap comprehensive
23 SAP development skills for Claude Code — ABAP, RAP, CAP, Fiori, BTP, HANA, S/4HANA, Integration Suite and more. Agent Skills Specification compatible.
npx -y skills add efeumutaslan/SAP-SKILLS --skill sap-rap-comprehensiveAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
SAP RAP (RESTful Application Programming Model) comprehensive development skill. Use when creating RAP business objects, writing BDEF/CDS view entities, implementing validations/ determinations/actions, handling drafts, writing EML, or extending standard RAP BOs. If the user mentions RAP, BDEF, behavior definition, CDS view entity, EML, managed/unmanaged BO, or service binding, use this skill. Covers BTP, S/4HANA Cloud, and On-Premise.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
14.5 KB, as published. Nobody here has run it
SAP RAP — RESTful Application Programming Model
Related Skills
sap-s4hana-extensibility— Extending standard SAP RAP BOssap-security-authorization— RAP authorization patternssap-testing-quality— RAP test doubles in depth
Quick Start
RAP BO in 5 artifacts:
1. Database Table → ZTAB_TRAVEL
2. CDS View Entity → ZI_Travel (interface, root)
3. Behavior Definition → ZI_Travel (managed, draft)
4. Behavior Impl. → ZBP_I_Travel (handler + saver)
5. Service Definition → ZSD_Travel → Service Binding (V4)
Minimum BDEF (managed with draft):
managed implementation in class zbp_i_travel unique;
strict ( 2 );
with draft;
define behavior for ZI_Travel alias Travel
persistent table ztab_travel
draft table zdraft_travel
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master ( global, instance )
{
field ( readonly ) TravelUUID;
field ( mandatory ) AgencyID, CustomerID;
create; update; delete;
determination SetStatusNew on modify { create; }
validation ValidateDates on save { field BeginDate, EndDate; }
action ( features : instance ) AcceptTravel result [1] $self;
draft action Resume;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft determine action Prepare;
mapping for ztab_travel corresponding;
}
Core Concepts
RAP Architecture Layers
┌─ Service Layer ──────────────────────────────┐
│ Service Definition → Service Binding (V2/V4) │
├─ BO Projection Layer ────────────────────────┤
│ CDS Projection View (C_*) + Projection BDEF │
├─ BO Interface Layer ─────────────────────────┤
│ CDS View Entity (I_*) + Behavior Definition │
│ + Behavior Implementation (Handler/Saver) │
├─ Data Layer ─────────────────────────────────┤
│ Database Tables / CDS Abstract Entities │
└──────────────────────────────────────────────┘
Implementation Types
| Type | When to Use | Key Difference |
|---|---|---|
| Managed | New greenfield development | Framework handles CRUD + persistence |
| Unmanaged | Wrapping legacy (BAPIs, FMs) | Developer handles all persistence |
| Managed + Unmanaged Save | Managed CRUD but custom save | Framework CRUD, you handle DB write |
| Managed + Additional Save | Managed save + extra side-effects | Framework saves, you do extra work |
CDS View Entity — Root with Child
@AccessControl.authorizationCheck: #CHECK
define root view entity ZI_Travel
as select from ztab_travel
composition [0..*] of ZI_Booking as _Booking
{
key travel_uuid as TravelUUID,
travel_id as TravelID,
agency_id as AgencyID,
customer_id as CustomerID,
begin_date as BeginDate,
end_date as EndDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
total_price as TotalPrice,
currency_code as CurrencyCode,
overall_status as OverallStatus,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.lastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt,
_Booking
}
Common Patterns
Pattern 1: Validation (on save)
METHOD validateDates.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( BeginDate EndDate )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travels).
LOOP AT lt_travels INTO DATA(ls_travel).
IF ls_travel-BeginDate > ls_travel-EndDate.
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 = 'Begin date must be before end date' )
%element-BeginDate = if_abap_behv=>mk-on
%element-EndDate = if_abap_behv=>mk-on
) TO reported-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
Pattern 2: Determination (on modify)
METHOD setStatusNew.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( OverallStatus )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travels).
MODIFY ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( OverallStatus )
WITH VALUE #( FOR travel IN lt_travels
WHERE ( OverallStatus IS INITIAL )
( %tky = travel-%tky OverallStatus = 'O' ) ). " Open
ENDMETHOD.
Pattern 3: Action with Result
METHOD acceptTravel.
MODIFY ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
UPDATE FIELDS ( OverallStatus )
WITH VALUE #( FOR key IN keys
( %tky = key-%tky OverallStatus = 'A' ) ). " Accepted
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travels).
result = VALUE #( FOR travel IN lt_travels
( %tky = travel-%tky %param = travel ) ).
ENDMETHOD.
Pattern 4: Instance Feature Control
METHOD get_instance_features.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( OverallStatus )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_travels).
result = VALUE #( FOR travel IN lt_travels
( %tky = travel-%tky
%action-AcceptTravel = COND #(
WHEN travel-OverallStatus = 'A'
THEN if_abap_behv=>fc-o-disabled " Already accepted
ELSE if_abap_behv=>fc-o-enabled )
%action-RejectTravel = COND #(
WHEN travel-OverallStatus = 'X'
THEN if_abap_behv=>fc-o-disabled " Already rejected
ELSE if_abap_behv=>fc-o-enabled )
) ).
ENDMETHOD.
Pattern 5: Authorization (Global + Instance)
" Global authorization: Can user create at all?
METHOD get_global_authorizations.
IF requested_authorizations-%create = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'Z_TRAVEL' ID 'ACTVT' FIELD '01'.
result-%create = COND #(
WHEN sy-subrc = 0 THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
ENDIF.
ENDMETHOD.
" Instance authorization: Can user update THIS travel?
METHOD get_instance_authorizations.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel FIELDS ( AgencyID ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_travels).
LOOP AT lt_travels INTO DATA(ls_travel).
AUTHORITY-CHECK OBJECT 'Z_TRAVEL'
ID 'ACTVT' FIELD '02'
ID 'Z_AGNCY' FIELD ls_travel-AgencyID.
DATA(lv_update) = COND #(
WHEN sy-subrc = 0 THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
APPEND VALUE #( %tky = ls_travel-%tky
%update = lv_update
%action-AcceptTravel = lv_update
) TO result.
ENDLOOP.
ENDMETHOD.
Pattern 6: EML (Entity Manipulation Language)
" Create
MODIFY ENTITIES OF zi_travel
ENTITY Travel
CREATE FIELDS ( AgencyID CustomerID BeginDate EndDate )
WITH VALUE #( (
%cid = 'CID_1'
AgencyID = '70001'
CustomerID = '100000'
BeginDate = cl_abap_context_info=>get_system_date( )
EndDate = cl_abap_context_info=>get_system_date( ) + 14
) )
MAPPED DATA(ls_mapped)
FAILED DATA(ls_failed)
REPORTED DATA(ls_reported).
" Read
READ ENTITIES OF zi_travel
ENTITY Travel
ALL FIELDS
WITH VALUE #( ( TravelUUID = lv_uuid ) )
RESULT DATA(lt_result).
" Commit
COMMIT ENTITIES
RESPONSE OF zi_travel
FAILED DATA(ls_commit_failed)
REPORTED DATA(ls_commit_reported).
Pattern 7: Draft Handling Flow
[New]
→ Edit → [Draft created in draft table]
→ Modify fields (auto-saved to draft table)
→ Prepare (runs validations on draft)
→ Activate (moves draft → active table, runs on-save validations)
[Existing Active]
→ Edit → [Copy to draft table, lock active]
→ Modify → Prepare → Activate
[Discard] → Delete draft, unlock active
[Resume] → Continue editing existing draft
Draft table structure: Same as active table + admin fields (%is_draft, draftentityoperationcode, etc.)
Error Catalog
| Error | Cause | Fix |
|---|---|---|
| "Entity not modifiable" | Missing update in BDEF | Add update; to behavior definition |
| "Draft table does not exist" | Draft table not created | Create DDIC table matching draft table name in BDEF |
| CDS activation "composition invalid" | Child not defined as root or composition mismatch | Child must NOT be root; check composition [0..*] of syntax |
| "Determination not triggered" | Wrong trigger event (on modify vs on save) | Verify trigger: on modify { create; } vs on save { field X; } |
| "Authorization check failed" | Missing AUTHORITY-CHECK or wrong object | Implement get_global_authorizations / get_instance_authorizations |
| BDEF activation "strict mode" | Using deprecated syntax in strict ( 2 ) | Use current syntax; check ADT error message for guidance |
| "%cid not found in mapped" | Create-by-association without matching %cid_ref | Ensure parent %cid matches child %cid_ref in EML |
| "Lock conflict" on edit | Another user has active draft | Check draft table for existing draft; use Resume if same user |
| "Feature control not working" | Method signature mismatch | Use exact parameter types from handler class interface |
| "etag mismatch" | Stale data (concurrent modification) | Reload data and retry; check etag field definition |
Performance Tips
- Use
IN LOCAL MODEin handler methods to skip authorization re-checks - Read only needed fields:
FIELDS ( Field1 Field2 )notALL FIELDS - Avoid N+1 queries: batch-read entities, don't loop-and-read
- Use
%controlto detect which fields were actually sent by the client - Keep validations focused: one validation per business rule
- Use
on modifydeterminations for immediate feedback,on savefor expensive checks
BTP vs S/4HANA Differences
| Aspect | BTP ABAP Environment | S/4HANA Cloud/On-Prem |
|---|---|---|
| strict mode | strict ( 2 ) required | strict ( 1 ) or none |
| Available APIs | Only released (C1/C2) | All (on-prem), released (cloud) |
| ABAP version | ABAP Cloud only | Cloud or Classic |
| Service binding | OData V4 default | V2 and V4 available |
| Draft | Standard | Standard |
| Extend SAP BO | Via released extension points | Full access (on-prem) |
Bundled Resources
| File | When to Read |
|---|---|
references/rap-complete-guide.md | Full RAP reference with all patterns |
references/bdef-syntax-reference.md | Complete BDEF syntax reference |
references/eml-cheatsheet.md | EML statement quick reference |
templates/managed-bo.cds | Complete managed RAP BO template |
templates/handler-class.abap | Handler class implementation template |
templates/test-class.abap | RAP unit test template with CL_BOTD |
Gotchas
- Managed vs. Unmanaged save: Managed RAP handles INSERT/UPDATE/DELETE automatically; if you need custom save logic, use
managed with additional saveormanaged with unmanaged save— don't fight the framework - Draft and non-draft mismatch: If root entity has draft, ALL compositions in the BO must also have draft — partial draft is not allowed
- EML in non-RAP context: EML (
MODIFY ENTITIES OF ...) can only be used inside RAP behavior implementations or withIN LOCAL MODE/PRIVILEGED ACCESS— not in arbitrary ABAP programs - Late numbering gotcha: With late numbering,
%pid(preliminary ID) is only valid within the same LUW — never persist it; map to final key inadjust_numbers - Authorization timing: Global authorization is checked FIRST, then instance authorization — if global auth fails, instance auth never runs
- CDS view vs. view entity: RAP requires CDS view ENTITIES (
define root view entity), not classic CDS views (define view) — migration needed for legacy CDS - Determination on modify vs. on save:
on modifyruns immediately and can set fields visible to user;on saveruns during finalize — choose based on UX needs - Strict mode levels:
strict(2)is recommended for new BOs; it enforces additional validations and will be required in future releases
Validation Workflow
After creating or modifying a RAP BO, validate completeness:
bash scripts/validate-rap-bo.sh ./src
RAP BO checklist:
- Root view entity defined with
define root view entity - BDEF has authorization control (master/dependent)
- ETag field defined for concurrency control
- Draft table defined (if draft enabled)
- Service definition and binding created
- At least one unit test class exists
MCP Server Integration
{
"mcpServers": {
"vibing-steampunk": {
"command": "npx", "args": ["-y", "vibing-steampunk"],
"env": { "SAP_HOST": "https://your-system.abap.hana.ondemand.com",
"SAP_USER": "YOUR_USER", "SAP_PASSWORD": "YOUR_PASSWORD" }
}
}
}
- Vibing Steampunk: Read/write BDEF, CDS, handler classes directly on SAP system via ADT