Behavior Definitions
RAP / CDS / ODataintermediate

Behavior Definitions Part 4: Associations, Compositions and Draft Declarations

Key takeaway

Declare the relationships of a business object correctly in the BDEF: composition associations with create-by-association, read-by-association, dependent locking and authorization, and every declaration needed to enable draft.

Explanation

📌 KEY POINTS
✅ Children are created only via the parent association.

✅ The child declares association _Parent for dependent lock/authorization.

✅ Draft checklist: header, draft tables, total etag, actions, "with draft" on associations, projection.

⚠️ References to other BOs stay in CDS, not in the BDEF.

▶ WHERE WE ARE
Parts 2–3 covered one entity at a time. This part covers how entities of a BO tree are connected in the BDEF, and the exact set of declarations required for draft. (CDS Associations Part 4 explains composition vs association on the CDS side.)

━━━━━━━━━━━━━━━━━━━━
▶ 1. ASSOCIATIONS IN THE BDEF

Only associations that belong to the BO tree are declared in the BDEF body:

  • In the parent: "association _Item { create; }" — enables create-by-association (items are created through the request) and read-by-association (READ ENTITIES … BY \_Item).
  • In the child: "association _Request;" — enables read-by-association to the parent, needed for lock dependent and authorization dependent.
  • Without "create" in braces, the association is read-only; the child can then not be created at all unless via another path.
  • Options: "association _Item { create ( features : instance ); }" — adding items only allowed in certain states; "internal create" — only the BO itself may add children.

Associations to other BOs (supplier, product) stay in CDS only; they are not declared in the BDEF.

━━━━━━━━━━━━━━━━━━━━
▶ 2. WHY CHILDREN HAVE NO STANDALONE CREATE

A child without its parent is invalid. By omitting "create" in the child's body and offering create only via the parent's association, the BDEF makes it impossible to create an orphan — no code needed. EML uses CREATE BY \_Item with %cid_ref or the parent key.

━━━━━━━━━━━━━━━━━━━━
▶ 3. DEPENDENT LOCKING, AUTHORIZATION AND ETAG

  • lock dependent by _Request — the child is locked by locking its root.
  • authorization dependent by _Request — the child uses the root's authorization result.
  • etag master (own) or etag dependent by _Request (parent's ETag).

These work only if the association to the parent is declared in the child's body.

━━━━━━━━━━━━━━━━━━━━
▶ 4. DEEPER TREES

For root → item → schedule line: the schedule line declares "lock dependent by _Request" pointing to the root via its association (declare an association from the schedule line to the root in CDS, or chain through the item — in both cases the root must be reachable). Keep trees shallow when possible.

━━━━━━━━━━━━━━━━━━━━
▶ 5. THE DRAFT CHECKLIST

To enable draft, all of the following are required:

  1. Header: "with draft;".
  2. Each entity: "draft table <table>" — generate it with the ADT quick fix; regenerate after adding CDS fields.
  3. Root: "total etag <field>" (usually LastChangedAt).
  4. Root: draft actions — Edit, Activate (optimized on current releases), Discard, Resume, and "draft determine action Prepare { … }" listing validations.
  5. Every association: "with draft" — "association _Item { create; with draft; }" and "association _Request { with draft; }".
  6. Projection BDEF: "use draft;" and "use action Edit; …" for all draft actions, plus "with draft" on associations.
  7. Handler code: use %tky (contains %is_draft), never only the key.

Missing any item leads to activation errors or runtime failures that are hard to trace.

━━━━━━━━━━━━━━━━━━━━
▶ 6. DRAFT AND CHILD OPERATIONS

With draft, adding an item in Fiori creates a draft item under the draft root. "with draft" on the association tells RAP to route the operation to draft or active instances depending on %is_draft of the parent.

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP

  1. Check each child: association to parent in CDS and in BDEF body; no standalone create.
  2. Check each parent: association with create for its children.
  3. Run through the draft checklist item by item before activating.
  4. Test: create a request with items in Fiori, leave, resume, activate.

━━━━━━━━━━━━━━━━━━━━
▶ WHAT YOU HAVE AFTER PART 4

Correct relationship and draft declarations. Part 5 covers projection and interface BDEFs and how to keep contracts stable.

Code example

ABAP Code
managed implementation in class zbp_r_purchreq unique;strict ( 2 );with draft;                                         // (1) define behavior for ZR_PurchReq alias PurchaseRequestpersistent table zpr_headdraft table zpr_head_d                              // (2)lock mastertotal etag LastChangedAt                            // (3)authorization master ( global, instance )etag master LocalLastChangedAt{  create; update; delete;   association _Item { create ( features : instance ); with draft; }   // (5) + state-dependent add   draft action Edit;                                // (4)  draft action Activate optimized;  draft action Discard;  draft action Resume;  draft determine action Prepare  {    validation validateDescription;    validation Item~validateQuantity;               // child validation too  }} define behavior for ZR_PurchReqItem alias Itempersistent table zpr_itemdraft table zpr_item_d                              // (2)lock dependent by _Request                          // needs "association _Request" belowauthorization dependent by _Requestetag master LocalLastChangedAt{  update;  delete;                                           // NO create: only via PurchaseRequest\_Item  association _Request { with draft; }              // (5)} // ===== Projection BDEF (6) =====projection;strict ( 2 );use draft; define behavior for ZC_PurchReq alias PurchaseRequest{  use create; use update; use delete;  use action Edit; use action Activate; use action Discard;  use action Resume; use action Prepare;  use association _Item { create; with draft; }}define behavior for ZC_PurchReqItem alias Item{  use update; use delete;  use association _Request { with draft; }} " (7) Handler code: always %tky" READ ENTITIES OF zr_purchreq IN LOCAL MODE"   ENTITY PurchaseRequest BY \_Item ALL FIELDS WITH CORRESPONDING #( keys )  " keys carry %is_draft"   RESULT DATA(items).

Real project scenario

After a developer enabled draft on a requisition BO, the Fiori app could create drafts, but adding an item failed with a generic error. The BDEF had "with draft" in the header and draft tables for both entities, but the association declarations lacked "with draft", and the projection BDEF did not use the Resume and Prepare actions.
Going through a written draft checklist (header, draft tables, total etag, draft actions, associations with draft, projection, %tky in code) found three gaps in ten minutes. The team kept the checklist in their wiki and later used it for four more BOs without a single draft-related defect.

Common mistakes

  • Offering create on the child entity itself instead of via the parent association.
  • Declaring lock dependent without declaring the association to the parent in the BDEF body.
  • Declaring associations to other BOs (references) in the BDEF.
  • Enabling draft but missing "with draft" on associations, the total etag or some draft actions.
  • Forgetting to update the projection BDEF with use draft and the draft actions.
  • Not regenerating draft tables after adding fields.

Best practices

  • Children are created only by association; declare the back-association in every child.
  • Keep BO trees shallow; reference other BOs from CDS only.
  • Use a written draft checklist and apply it to base and projection BDEFs.
  • Use features on association create to control when children may be added.
  • Use %tky everywhere so the same code works for draft and active data.

Interview angle

Questions: "How do you create child entities in RAP?", "Why does a child entity usually have no create operation?", "What is needed to enable draft?"
Strong answer: children are created via create-by-association declared in the parent ("association _Item { create; }"), which prevents orphans; the child declares its association to the parent for dependent locking and authorization. For draft list the complete checklist: with draft, draft tables, total etag, draft actions including Prepare, with draft on associations, projection use draft, %tky in code.

Practice this lesson

Quick check

1. How should a BDEF prevent request items from being created without a parent request?

2. In a composition hierarchy where a root entity is declared with 'lock master' and a dependent child entity is declared with 'lock dependent by _Association', what does this configuration achieve?

3. When a RAP business object's behavior definition includes the statement 'with draft;', which of the following is required and automatically enabled?

Interview questions

1. After enabling draft, adding an item in the Fiori app fails. The header has 'with draft' and draft tables exist. What do you check?

Answer it in your own words first, then compare.

2. Why do child entities in a RAP BDEF usually have no create operation of their own, and what must the child declare?

Answer it in your own words first, then compare.

Practice more with Interview AI →

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.

More lessons in this topic

Interview questions on this topic

Related SAP topics