RAP Business Objects Part 1: Designing the BO — Root, Children and Boundaries
Design a RAP business object before writing code: what one BO is, how to choose the root, which data belongs in the composition tree, which data is only referenced, and how keys and naming follow from that.
What this complete series covers
Learn RAP Business Objects in a clear, practical sequence — from the basic idea to real project use, troubleshooting, and interview-ready understanding.
- Who it is for
- Best for SAP consultants, developers, and learners who want a practical understanding of RAP Business Objects.
- Prerequisites
- Basic ABAP and ADT in Eclipse are recommended. The series explains the RAP/CDS/OData concepts as they are introduced.
- Final outcome
- By the end, you should be able to explain RAP Business Objects clearly, follow the main end-to-end flow, apply it in a project scenario, and troubleshoot the most common issues.
- Part 1: RAP Business Objects Part 1: Designing the BO — Root, Children and Boundaries
Design a RAP business object from the transactional boundary outward: one root, owned composition children, reference associations, behavior, and a projection layer that becomes th
- Part 2: RAP Business Objects Part 2: Managed vs Unmanaged — A Decision Framework
Choose managed RAP when the framework can own standard persistence behavior, and unmanaged RAP when existing business logic or persistence requires you to implement the REST contract explicitly.
- Part 3: RAP Business Objects Part 3: Transactional Buffer, Save Sequence and the RAP LUW
Understand how RAP separates the interaction phase from persistence, keeps changes in a transactional buffer, runs save-time checks, and commits all involved business objects consi
- Part 4: RAP Business Objects Part 4: Locking, ETags and Concurrency Control
Combine pessimistic locking and optimistic ETag checks correctly so RAP protects in-progress edits while also preventing stale clients from silently overwriting newer committed data.
- Part 5: RAP Business Objects Part 5: Authorization, Feature Control and Messages
Separate security authorization, dynamic feature availability, and user-facing RAP messages so the backend contract remains secure, predictable, and understandable to Fiori and API consumers.
System and release assumptions: Examples target recent SAP S/4HANA / ABAP Cloud capabilities. RAP, CDS, OData, and Fiori Elements syntax and tooling can differ by ABAP platform release.
Explanation
📌 KEY POINTS
✅ A BO is one transactional boundary: locked, checked and saved together.
✅ Composition only for parts with no own lifecycle.
✅ Everything else (supplier, product) is referenced by association.
⚠️ Oversized trees cause lock conflicts and heavy drafts.
▶ WHAT THIS SERIES COVERS
This series gives you the map of a RAP business object (BO). The detailed build steps are in the Managed RAP and Unmanaged RAP series; here you learn the concepts that make those steps make sense.
- Part 1 — designing the BO: root, children, boundaries (this lesson)
- Part 2 — managed vs unmanaged: the decision
- Part 3 — the transactional buffer, the save sequence and the RAP LUW
- Part 4 — locking, ETags and concurrency
- Part 5 — authorization, feature control and messages
━━━━━━━━━━━━━━━━━━━━
▶ WHAT A RAP BUSINESS OBJECT IS
A business object is a real-world thing your application manages as one unit: a purchase request, a sales order, a travel booking. Technically it is a tree of CDS entities plus a behavior definition that says what may happen to the tree.
The most important property: a BO is a transactional boundary. Everything inside the tree is locked together, checked together and saved together — all or nothing.
━━━━━━━━━━━━━━━━━━━━
▶ THE TREE
- Root entity — the anchor ("define root view entity"). Its key identifies the whole BO instance. Locks, ETag master and authorization master usually sit here.
- Child entities — parts that belong to the root and cannot exist without it (items, schedule lines, notes). Declared with "composition" in the parent and "association to parent" in the child.
- Deeper levels are allowed: root → item → schedule line.
- Everything outside the tree is only referenced with a normal association: customer, material, currency, another BO.
━━━━━━━━━━━━━━━━━━━━
▶ HOW TO DECIDE WHAT BELONGS IN THE TREE
Ask for each candidate entity:
- Does it have its own lifecycle? If it can be created, changed or deleted independently (a customer, a product), it is a separate BO — reference it.
- Must it be consistent with the root in the same transaction? If an item change must be validated together with the header (totals, status), it belongs in the tree.
- Who edits it and when? If two different teams edit it at different times, putting it in the tree causes unnecessary locking of the whole BO.
- How big can it get? A tree with thousands of children per root makes every lock and draft heavy — consider a separate BO.
Rule of thumb: keep the tree as small as consistency requires.
KEYS
- Use a technical UUID key for every entity (generated by the framework in managed RAP).
- Children carry the parent's key as a foreign key field (e.g. RequestUUID in the item).
- Add a human-readable semantic number on the root (e.g. RequestID) for users (Managed RAP Part 2).
━━━━━━━━━━━━━━━━━━━━
▶ LAYERS AND NAMING
A consistent naming scheme makes every RAP project easier:
- Tables: ZPR_HEAD, ZPR_ITEM (plus draft tables later).
- BO base views: ZR_PurchReq (root), ZR_PurchReqItem (child) with a behavior definition ZR_PurchReq.
- Behavior pool: ZBP_R_PURCHREQ.
- Projections per consumer: ZC_ for UI, ZA_ (or similar) for APIs.
- Service definition ZUI_… / ZAPI_…, binding with _O4 suffix.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP — DESIGN BEFORE CODE
- Write down the business object in one sentence ("A purchase request with its items, approved as one unit").
- List candidate entities and apply the four questions.
- Draw the tree: root, children, references.
- Decide keys (UUID + semantic number).
- Decide the implementation type (Part 2).
- Only then create tables and CDS views (Managed RAP Part 1).
━━━━━━━━━━━━━━━━━━━━
▶ WHAT YOU HAVE AFTER PART 1
A method to draw a correct BO tree. The code example shows how such a design is expressed in CDS and in the first lines of a behavior definition.
Code example
// ===== Design: Purchase Request BO =====//// PurchaseRequest (root, ZR_PurchReq) <- locks, ETag, authorization here// └── Item (child, ZR_PurchReqItem) <- composition: lives and dies with the request//// References (NOT in the tree - own lifecycle):// Supplier -> association to I_Supplier// Currency -> association to I_Currency// Product -> association to I_Product // ===== Root view: composition + references =====define root view entity ZR_PurchReq as select from zpr_head composition [0..*] of ZR_PurchReqItem as _Item // owned association [0..1] to I_Supplier as _Supplier on $projection.Supplier = _Supplier.Supplier // referenced association [0..1] to I_Currency as _Currency on $projection.CurrencyCode = _Currency.Currency // referenced{ key request_uuid as RequestUUID, request_id as RequestID, supplier as Supplier, currency_code as CurrencyCode, _Item, _Supplier, _Currency} // ===== Child view: back-link to the parent =====define view entity ZR_PurchReqItem as select from zpr_item association to parent ZR_PurchReq as _Request on $projection.RequestUUID = _Request.RequestUUID{ key item_uuid as ItemUUID, parent_uuid as RequestUUID, item_no as ItemNo, _Request} // ===== The tree in the behavior definition =====managed implementation in class zbp_r_purchreq unique;strict ( 2 ); define behavior for ZR_PurchReq alias PurchaseRequestpersistent table zpr_headlock masterauthorization master ( global, instance )etag master LocalLastChangedAt{ create; update; delete; association _Item { create; } // children only via the parent} define behavior for ZR_PurchReqItem alias Itempersistent table zpr_itemlock dependent by _Request // locked with the rootauthorization dependent by _Request // checked on the rootetag master LocalLastChangedAt{ update; delete; association _Request;}// Full, compiling version: Managed RAP Part 1.Real project scenario
A team modeled "Project" as a RAP BO with WBS elements, tasks, time entries and documents all as compositions under the project root. It worked in the demo. In production, every time an employee booked a time entry, the whole project was locked, so project managers could not edit the project for hours, and draft sessions became very large.
In a redesign, time entries and documents became separate BOs with an association to the project, because they have their own lifecycle and editors. The project BO kept only WBS elements and tasks, which really must be consistent with the project header. Lock conflicts disappeared and response times improved.
Common mistakes
- Putting every related entity into the composition tree "because it belongs to it".
- Modeling a reference (customer, product) as a composition.
- Using a normal association where the child really has no life without the parent.
- Designing without a UUID key, then struggling with numbering and draft.
- Starting with tables and code before drawing the tree.
- Mixing naming conventions so nobody can tell base views from projections.
Best practices
- Treat the BO as a transactional boundary: lock, check and save together.
- Keep the tree as small as consistency requires; reference everything with its own lifecycle.
- UUID keys for all entities, a semantic number on the root.
- Agree a naming convention (ZR_, ZC_, ZBP_, ZUI_) at project start.
- Draw and review the tree with the functional expert before building.
Interview angle
Questions: "What is a RAP business object?", "How do you decide what belongs in the composition tree?", "What is the difference between composition and association?"
Strong answer: a BO is a tree of CDS entities with behavior, forming one transactional boundary; the root carries lock, ETag and authorization master, children depend on it. Include an entity in the tree only if it has no independent lifecycle and must be consistent with the root in one transaction; everything else is referenced via association. Mention the cost of oversized trees (locking, draft size) — a sign of design experience.
Practice this lesson
Quick check
1. Which entity should be modeled as a composition child of a Purchase Request root?
2. Time entries modeled as composition children of a Project BO cause constant lock conflicts for project managers. What is the best redesign?
3. An action calls a legacy function that ends with COMMIT WORK. Which problem does this cause?
Interview questions
1. What is a RAP business object, and how do you decide which entities belong in its composition tree?
Answer it in your own words first, then compare.
2. A 'Project' BO contains WBS elements, tasks, time entries and documents as compositions. Project managers constantly get lock errors. How would you redesign it?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.