RAP · RESTful ABAP

SAP RAP Interview Questions

RAP questions arrive in almost every modern ABAP interview now, and they expose a specific gap: candidates who have read about the RESTful Application Programming Model but cannot reason about why it is shaped the way it is. Interviewers are not checking whether you can recite the layers; they are checking whether you know which layer owns which decision.

The questions on this page come from ERPClimb's reviewed question bank and move from the model's building blocks — behaviour definitions, projections, service definitions and bindings — into the judgement calls: managed versus unmanaged implementation, when a legacy application should keep its own persistence, and how RAP relates to the CDS model underneath it.

Each answer is written to be said out loud in an interview: the decision first, the reason second, and the trade-off the interviewer is waiting for last. If you can explain why a greenfield object goes managed without hesitating, you are ahead of most of the field.

What interviewers actually probe

Managed versus unmanaged

The single most common RAP question. Expect to justify the choice from who owns persistence and who owns the transactional buffer — not from which one is newer.

What the behaviour definition actually controls

Interviewers probe whether you understand that the behaviour definition declares the business object's contract — operations, validations, determinations, locks — rather than containing the logic itself.

Projections and service exposure

A frequent practical line: how a single data model serves multiple apps through projection layers and service bindings, and what V4 exposure buys you over a hand-built service.

RAP versus what it replaces

Strong candidates can place RAP against SEGW services, classic reports and BOPF-era thinking, and say honestly when the older technique is still the right one.

22 questions with full answers

Ordered from foundational to advanced. No sign-in required.

mediumRAP Basics

1. What is a determination?

A determination is a behaviour that runs automatically at defined trigger points such as create, update or save to derive and populate fields without manual user input. The first thing to check is which trigger point is appropriate for the business rule and what data the determination depends on, because it should only run when the required context is available. It is used to keep values consistent, for example automatically filling the reviewer based on the department when a request is created. A strong candidate also adds that determinations should be deterministic, lightweight, and focused on deriving data rather than performing unrelated processing, so the saved business object is complete and consistent.
mediumRAP Basics

2. How do you expose a RAP service to Fiori?

First create the service definition and list only the RAP entities you want to expose, because that controls the service contract and avoids publishing unnecessary data. Then create a service binding of type OData V4 UI and publish the binding so the runtime can generate the service endpoint. After that, register or activate the binding in /IWFND/V4_ADMIN, which makes the service available for consumption. In a strong answer, add that Fiori Elements can then consume the service directly, typically as a list report or object page, provided the CDS/RAP model is designed for those UI patterns and the exposed entities support the required navigation and annotations.
mediumRAP Basics

3. What is the difference between action, determination and validation in RAP?

First, I would separate them by when they run and whether they are triggered by the consumer. An action is an explicit operation the user or consumer invokes, such as approve or submit, so it is used for business steps that are not simple field updates. A determination runs automatically during modify or save to derive or adjust values, so it is ideal for defaulting, recalculating, or keeping data consistent without user intervention. A validation also runs automatically, but its purpose is to check business rules and stop the save with errors if the data is not acceptable. A strong candidate adds that action changes are intentional, determination is corrective or derivative, and validation is purely control and quality enforcement.
hardRAP Basics

4. How would you design a RAP business object with header and items?

I would create a root entity for the header and child entity for items using composition. The child would have an association to parent. Behavior definition would be defined for the root and child depending on allowed operations. I would use determinations and validations for business rules, and expose projection/consumption entities through a service definition and binding.
mediumRAP Basics

5. In a travel app, the total price is calculated in a determination on save. Users entering bookings in the Fiori object page see a total of zero until they press Save and think the app is broken. What do you change?

The calculation must run during the interaction phase, not only at save. I change it to determination calculateTotal on modify with trigger fields — on the booking entity the relevant fields (BookingFee/FlightPrice, CurrencyCode) and create/delete of bookings, and on the travel the header fields that influence the total. The implementation reads the bookings with READ ENTITIES IN LOCAL MODE by association, sums (with currency conversion if needed) and updates TotalPrice with MODIFY ENTITIES IN LOCAL MODE. In the BDEF I add side effects, e.g. field BookingFee affects field TotalPrice (or entity _Travel for child changes), so Fiori reloads the total without a manual refresh. Triggers stay narrow so the determination does not run on every unrelated field change.
mediumRAP Basics

6. A batch program called MODIFY ENTITIES to create orders and immediately reported success, but nothing appeared in the database and some records were never explained. What is wrong?

MODIFY ENTITIES only changes the transactional buffer. Outside the BO the program must call COMMIT ENTITIES to run the save sequence (finalize, check_before_save with validations, save) and write to the database. It must also check the responses: failed and reported after MODIFY (interaction phase errors) and COMMIT ENTITIES RESPONSE OF … FAILED … REPORTED … plus sy-subrc after the commit (save-phase errors, e.g. validations). On error it calls ROLLBACK ENTITIES and logs the messages with the business key — using %cid derived from the source key makes this traceable; mapped returns the created keys. For mass loads I process in packages (e.g. 500 per MODIFY/COMMIT) instead of one commit per record or one huge commit.
mediumRAP Basics

7. An expense app put defaulting, validation and status transitions all into one big determination on save. Users get no immediate feedback, and wrong amounts are silently corrected. How would you restructure the logic?

I would split the logic by type. Defaults (currency, initial status 'Open') become a determination on modify { create; } so they appear immediately. Recalculated values (total amount) become a determination on modify with trigger fields Amount and Currency plus a side effect so Fiori refreshes the total. Checks (amount within policy, dates valid) become validations on save, which reject with failed/reported and messages on the field instead of silently correcting data; they are also listed in draft determine action Prepare so users see errors before activation. Status transitions triggered by users (submit, approve, reject) become actions with result $self and feature control. Only truly final values, like drawing the claim number, stay in a determination on save.
mediumRAP Basics

8. A new approval app on custom tables needs standard CRUD, draft, and in addition must write change documents and an application log entry whenever an approval request is saved. Which RAP implementation type do you choose and where does the extra logic go?

I would choose managed with additional save. The data lives in our own tables, so the framework can handle the transactional buffer, CRUD, numbering, locking and draft — no reason for unmanaged. The additional save option (managed with additional save in the BDEF header or with additional save on the entity) gives a saver class where I redefine save_modified. There I receive create, update and delete tables and write change documents and the application log in the same LUW as the framework's save. No COMMIT WORK in that method — the framework commits. Determinations are not the place for this, because they run during the interaction phase and may run several times before save.
mediumRAP Basics

9. Your team designed a draft-enabled RAP BO for trade promotions with the promotion number (from a number range) as the table key, drawn in early numbering. Auditors now complain about large gaps in promotion numbers. What went wrong and how would you redesign the keys?

The gaps come from drawing numbers when the instance is created — with draft, a number is consumed as soon as the user clicks Create, and every abandoned or discarded draft burns one. I would redesign with a technical UUID key (sysuuid_x16) and field ( readonly, numbering : managed ), so the framework fills the key without any number range. The promotion number stays as a normal readonly field and is filled by a determination on save (or late numbering), which only runs when the promotion is actually activated/saved. Users see the readable number, never the UUID. Existing data can be migrated by generating UUIDs for existing rows. This is the standard RAP pattern: UUID key plus semantic ID drawn on save.
mediumRAP Basics

10. A Fiori app hid the Approve button for approved or foreign-region requests, but an integration partner using the OData API was still able to approve such requests. Where should this rule have been implemented?

In the BO, not in the UI. Two different rules are mixed here. "Approved requests cannot be approved again" is state-dependent operation control: action ( features : instance ) approve in the BDEF, implemented in get_instance_features returning disabled when status is approved. "Users of another region may not approve" is authorization: authorization master ( instance ) with get_instance_authorizations doing AUTHORITY-CHECK on a custom object with the region field. Both are enforced by the RAP runtime for every consumer — Fiori, Web API, EML — and Fiori Elements reads them to hide/disable the button automatically. The UI extension becomes unnecessary. I would also add a test with EML and with a restricted user.
mediumRAP Basics

11. Two Fiori apps must work on the same RAP business object: a planner app with full editing and an approver app that may only approve or reject. A colleague proposes copying the BO. What do you propose instead?

I would keep one interface BO (ZI_* views, one BDEF, one behavior pool) and build two projections on top of it. ZC_PromoPlanner exposes the needed fields and a projection BDEF with use create, use update, use delete and all actions; ZC_PromoApprover exposes a smaller field set and only use action approve and use action reject. Each projection has its own metadata extension for UI annotations and its own service definition and binding. Business logic — validations, determinations, feature control, authorization — stays once in the interface BO, so rule changes happen in one place. Copying the BO would duplicate logic, which drifts apart and doubles testing and maintenance.
mediumRAP Basics

12. A managed RAP BO on custom tables went live quickly, but users report that two people editing the same record overwrite each other's changes, and the "Changed by" column is always empty. Which part of the data model is missing?

The administrative fields and their @Semantics annotations are missing or incomplete. For concurrency, the table needs local_last_changed_at (instance ETag, referenced by etag master in the BDEF) and, for draft, last_changed_at as total ETag (lock master total etag). Without an ETag the OData If-Match check cannot detect that the record changed since it was read, so the last writer wins. For "Changed by", the interface view needs @Semantics.user.localInstanceLastChangedBy and the other annotations (createdBy, createdAt, localInstanceLastChangedAt, lastChangedAt) so the managed runtime fills them automatically. I would add the five standard ABP admin fields to the table, annotate them in ZI_*, declare etag master LocalLastChangedAt, and retest with two users.
mediumRAP Basics

13. In a claim application, developers made claim items a separate root BO so items could be created on their own. Now items exist without a claim header and item changes are not locked with the claim. How should the model look?

Items are existentially dependent on the claim, so they should be a composition child of the claim root, not a separate root. The claim view has composition [0..*] of ZI_ClaimItem as _Item; the item view has association to parent ZI_Claim as _Claim. In the BDEF the claim is lock master, authorization master and etag master; the item is lock dependent by _Claim and authorization dependent by _Claim, with its own etag. Items are created only through the parent: association _Item { create; } on the claim (create by association, with draft if draft-enabled) — no create on the item entity itself. Deleting a claim then deletes its items, and editing an item locks the whole claim. Existing orphan items must be cleaned up before the change.
mediumRAP Basics

14. A team exposed an interface CDS view entity (ZI_*) directly in the service definition. External consumers now depend on internal technical fields, and every data-model change breaks them. How should the layers have been set up?

The interface layer is the internal data model of the BO and should not be exposed directly. Exposure should go through the projection layer: a projection view (as projection on ZI_*) with provider contract transactional_query for UI or transactional_interface for APIs, listing only the fields the consumer needs with stable names, redirected compositions, value helps and texts. The service definition exposes the projection, not the interface view. Then the interface can evolve (new fields, renamed internals) while the projection stays stable. For external consumers I would create a dedicated API projection with its own service definition and Web API binding and treat it as a versioned contract.
mediumRAP Basics

15. An acceptTravel action works in development but in quality approvers get an error that the status field cannot be changed or that they are not authorized — even though they are allowed to approve. The action updates OverallStatus with MODIFY ENTITIES. What is the likely cause?

The MODIFY ENTITIES (and probably READ ENTITIES) inside the behavior pool is missing IN LOCAL MODE. Without it, the BO's own logic is treated like an external consumer: field control (OverallStatus is readonly for consumers), feature control and authorization checks for update are applied to the internal update. The developer had broad authorizations, so it worked in development. Inside handler methods all EML on the own BO must use IN LOCAL MODE, which bypasses consumer-level feature control and authorization — the action itself is already authorized through its own feature/authorization definition. I would add IN LOCAL MODE, return result $self, and retest with a restricted approver user.
mediumRAP Basics

16. A RAP UI service (OData V4 – UI binding) was given to a logistics partner for integration. After a UI enhancement renamed fields in the projection, the partner interface failed. How do you set up exposure correctly?

UI and integration consumers need separate contracts. The UI service (ZUI_* service definition on ZC_* projections, OData V4 – UI binding) may change with UI needs. For the partner I create an API projection (e.g. ZA_Travel, provider contract transactional_interface) with stable field names, a separate service definition ZAPI_TRAVEL and an OData V4 – Web API binding, published in each system (/IWFND/V4_ADMIN on-premise, communication arrangement on BTP). This API is documented and versioned: compatible additions are allowed, incompatible changes go into a new service version while the old one stays until partners migrate. Both projections sit on the same interface BO, so business logic is shared.
mediumRAP Basics

17. When would you choose managed RAP and when would you choose unmanaged RAP?

I would choose managed RAP when the business object uses standard persistence and the framework can handle CRUD and save behavior. I would choose unmanaged RAP when save logic must be controlled manually, such as when calling BAPIs, legacy function modules, existing APIs or complex custom update logic.
hardRAP Basics

18. How does RAP fit S/4HANA Clean Core?

First, I would say RAP fits S/4HANA Clean Core by moving custom development into released, upgrade-safe extension points. It relies on released CDS views for the data model and BDEF for transactional behaviour, so business logic sits in the extension layer rather than in core modifications. That makes it fully cloud-eligible and aligned to the Clean Core principle of keeping the standard stable. Compared with classic SEGW and modification-based approaches, RAP is the preferred way to add transactional apps and logic without changing the SAP core. A strong candidate also highlights that RAP supports maintainability, clearer separation of custom code, and safer upgrades because the custom build uses released artefacts only.
hardRAP Basics

19. An approve action for expense claims reads each selected claim with a separate SELECT SINGLE in a loop and raises a message when one fails, but the other claims still get approved without any explanation for the failed one. How do you improve the implementation?

Two issues: performance and response handling. Keys arrive as a table, so I read all needed data once — READ ENTITIES IN LOCAL MODE for the claim fields and one SELECT with FOR ALL ENTRIES (or a join) for the reference data — instead of one SELECT per claim. For each claim that fails the check I append its %tky to failed-claim and a message to reported-claim (%tky, %msg, %element for the field), and exclude it from the MODIFY; only the valid claims are updated with one MODIFY ENTITIES IN LOCAL MODE. The result is filled for the successful ones. The Fiori user then sees exactly which claim failed and why, while the others are approved. Raising a classic message (MESSAGE … TYPE 'E') inside RAP is wrong — messages go through reported.
hardRAP Basics

20. You must bring an existing SAP GUI transaction for customer returns onto a Fiori app on S/4HANA 2022. The legacy code uses BAPIs and a custom update function module. How do you approach the migration to RAP?

First I check whether SAP delivers a released RAP BO or API for the object (API Business Hub, released objects in ADT) — for customer returns there is a released BO that can be consumed with EML, which is the clean-core option and avoids wrapping BAPIs. Only for parts without a released BO I design a custom BO: if the data is in custom tables written only by legacy update logic, managed with unmanaged save keeps buffer, draft and locking from the framework while save_modified calls the legacy update function; if the whole process including checks lives in BAPIs, an unmanaged BO wraps them with my own buffer class and saver. Then projection, service definition and an OData V4 UI binding, and a Fiori Elements app instead of rebuilding the GUI screens one-to-one. Business rules are re-mapped to validations and determinations where possible.
hardRAP Basics

21. After go-live of a draft-enabled RAP app, users complain that changes "disappear" when two planners work on the same promotion on the same day. How do you analyse and fix it?

I check the concurrency setup in the BDEF. Typical cause: an instance ETag exists but no total ETag, so when planner A's draft is activated it overwrites the active version planner B changed in between. The fix is lock master total etag LastChangedAt on the root (with the last_changed_at admin field annotated @Semantics.systemDateTime.lastChangedAt), plus etag master LocalLastChangedAt per entity. Then Resume/Activate detects the change and shows "data changed by another user" instead of overwriting. I also verify lock master/lock dependent is in place and that no custom code writes directly to the tables bypassing the BO. Test with two users editing the same promotion.
hardRAP Basics

22. A procurement request app must let users save incomplete requests and continue days later, while nobody else changes the same request in between. How do you design this in RAP?

I would enable draft: with draft; in the BDEF header, draft table generated via quick fix for each entity, draft actions Edit, Activate optimized, Discard, Resume and draft determine action Prepare listing the validations, and with draft on create-by-association for children. Draft stores the incomplete work server-side, so mandatory checks run only at Prepare/Activate. For concurrency: lock master on the root (children lock dependent) — with draft the exclusive lock is held while the draft is being edited — plus etag master LocalLastChangedAt and lock master total etag LastChangedAt, so if the active request changed while a draft existed, Resume/Activate detects it. I would also agree on draft lifetime/expiry with the business and test with two users.

Practise by experience level

Fresher1-3 years4-7 years8-12 yearsArchitect

The questions above are tagged by the experience levels they are normally asked at, so the same page works for a first interview and for a lead-developer round.

SAP RAP Interview Questions FAQ

When would you choose a managed over an unmanaged RAP implementation?

Managed when the object is new and the framework can own persistence and the transactional buffer — that is the greenfield default on S/4HANA. Unmanaged when existing code already owns the database tables and the save sequence, because RAP then delegates those phases to your implementation instead of replacing working logic.

What is a behaviour definition in RAP?

It is the declared contract of a business object: which operations exist, which fields are read-only, where validations and determinations run, and how locking works. The implementation lives in the behaviour pool class; the definition is what consumers and the framework rely on.

How does a CDS model become an OData service in RAP?

Through three thin layers: the CDS views model the data, a projection view adapts it for a specific app, and a service definition plus binding exposes it as OData — V4 with RAP. The point interviewers look for is that no hand-written DPC class is involved.

What is the difference between a validation and a determination?

A validation checks consistency and can reject the save; a determination derives or fills values during the transactional phase. The expected answer includes when each runs — determinations modify, validations guard — and that both are declared in the behaviour definition and triggered by the framework, not called directly.

Is RAP only for S/4HANA cloud?

No — RAP is available on S/4HANA on-premise and in the ABAP environment on BTP as well. What changes with the cloud is which release of the model and which language version restrictions apply, which is itself a question interviewers ask to test whether you have actually built with it.

Next practice step

Related SAP interview topics

ERP Climb is an independent educational platform and is not affiliated with SAP SE.