Behavior Definitions Part 2: CRUD, Field Control, Numbering, Locking and Authorization
Master the syntax options for standard operations, field characteristics, numbering, locking and authorization — including internal operations, prechecks, readonly:update, mandatory:create and authorization:none.
Explanation
📌 KEY POINTS
✅ readonly, readonly : update, mandatory, mandatory : create, features : instance.
✅ precheck rejects input before it enters the buffer.
✅ internal operations are callable only inside the BO.
⚠️ authorization : none must be deliberate and documented.
▶ WHERE WE ARE
Part 1 showed the structure. This part is the reference for the most frequently used options. For each one: what it means and when to use it.
━━━━━━━━━━━━━━━━━━━━
▶ 1. STANDARD OPERATIONS AND THEIR OPTIONS
- create; update; delete; — available to all consumers.
- internal create/update/delete — only callable from inside the BO (IN LOCAL MODE), e.g. a child that is only created by an action.
- ( features : instance ) — enabled or disabled per instance via get_instance_features.
- ( precheck ) — a precheck method runs before the operation reaches the buffer; use it to reject obviously invalid input early (e.g. before draft data is written).
- ( authorization : none ) — no authorization check for this operation (use deliberately and document why).
- ( authorization : update ) — for an action or operation: check it with the same instance authorization as update.
━━━━━━━━━━━━━━━━━━━━
▶ 2. FIELD CHARACTERISTICS
Syntax: field ( <characteristic> ) Field1, Field2;
- readonly — consumers can never set it; the BO sets it (status, totals, admin fields).
- readonly : update — can be set on create, not changed later (e.g. an external document number).
- mandatory — must be filled; Fiori marks it, RAP reports missing values.
- mandatory : create — mandatory only on create.
- features : instance — read-only/mandatory decided at runtime in get_instance_features.
- numbering : managed — framework assigns a UUID key (combined with readonly).
- suppress — field hidden from the BO interface (available on newer releases).
Declare as much as possible here instead of checking in code.
━━━━━━━━━━━━━━━━━━━━
▶ 3. NUMBERING
- field ( readonly, numbering : managed ) Key; — managed UUID key.
- early numbering (entity header) — your earlynumbering_create method assigns keys at create.
- late numbering (entity header) — your saver's adjust_numbers assigns final keys at save; temporary %pid until then.
- No numbering declaration + key not readonly — external numbering: the consumer supplies the key.
━━━━━━━━━━━━━━━━━━━━
▶ 4. LOCKING
- lock master — this entity is locked (normally the root).
- lock dependent by _Parent — lock via the parent association.
- lock master unmanaged — in managed BOs, implement the lock yourself (e.g. to reuse a legacy lock object).
In unmanaged BOs, lock master means you implement the lock method.
━━━━━━━━━━━━━━━━━━━━
▶ 5. AUTHORIZATION
- authorization master ( global ) — only global checks (create, static actions).
- authorization master ( instance ) — only instance checks.
- authorization master ( global, instance ) — both; the common choice.
- authorization dependent by _Parent — children use the root's result.
Strict mode requires authorization to be declared, which prevents forgotten checks.\n\n━━━━━━━━━━━━━━━━━━━━\n▶ 6. ETAG\n• etag master Field — the field used for stale-data checks of this entity.
- etag dependent by _Parent — use the parent's ETag.
- total etag Field — root only, for draft activation.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- For each field of your BO, decide: readonly, readonly:update, mandatory, mandatory:create, dynamic, or unrestricted.
- For each operation, decide: public, internal, feature-controlled, prechecked.
- Write the declarations; activate; generate methods with Ctrl+1.
- Test with EML: try to set a readonly field — RAP rejects it without any code.
━━━━━━━━━━━━━━━━━━━━
▶ WHAT YOU HAVE AFTER PART 2
A reference for the declarative part of the BDEF. Part 3 covers business logic declarations.
Code example
define behavior for ZR_PurchReq alias PurchaseRequestpersistent table zpr_headlock masterauthorization master ( global, instance )etag master LocalLastChangedAt{ // ---- operations with options ---- create ( precheck ); // reject bad input before buffering update ( features : instance, precheck ); // state-dependent + precheck delete ( features : instance ); internal action recalcTotal; // callable only inside the BO (IN LOCAL MODE) // ---- field characteristics ---- field ( readonly, numbering : managed ) RequestUUID; // managed UUID field ( readonly ) Status, TotalAmount, RequestID, CreatedBy, CreatedAt, LastChangedBy, LocalLastChangedAt; field ( readonly : update ) ExternalReference; // set once at create field ( mandatory ) Description; field ( mandatory : create ) CurrencyCode; // required when creating field ( features : instance ) Supplier; // decided at runtime association _Item { create ( features : instance ); } // add items only in some states // ---- actions with authorization options ---- action ( features : instance, authorization : update ) submit result [1] $self; static action ( authorization : none ) refreshCatalog;} // Alternatives in the ENTITY HEADER:// early numbering -> method earlynumbering_create// late numbering -> saver method adjust_numbers// lock master unmanaged -> your own lock method in a managed BO// authorization master ( global ) -> only global checks// etag dependent by _Request -> (child) use parent's ETag " Generated method for create ( precheck ):" METHODS precheck_create FOR PRECHECK" IMPORTING entities FOR CREATE PurchaseRequest." -> append to FAILED / REPORTED to reject before the data enters the bufferReal project scenario
A requisition BO had about 400 lines of code in its update handler logic (validations and a precheck-like routine) whose only purpose was to reject changes to system fields and to the external reference after creation. Reviewing the BDEF, the team replaced this code with three lines: field ( readonly ) for the system fields, field ( readonly : update ) ExternalReference, and field ( mandatory : create ) CurrencyCode.
RAP now rejected invalid requests before any code ran, Fiori showed the fields correctly as read-only, and the associated unit tests went from 25 to 6 because there was far less logic to test.
Common mistakes
- Checking read-only fields in code instead of declaring them.
- Using mandatory when the field is only required at create (use mandatory : create).
- Setting authorization : none without a documented reason.
- Declaring early numbering but not implementing earlynumbering_create.
- Using lock dependent without a working association to the parent.
- Forgetting that instance feature control needs an implementation for every declared feature.
Best practices
- Classify every field once and express it in field characteristics.
- Use precheck for cheap input checks that must happen before buffering or drafting.
- Use internal operations for things only the BO itself may do.
- Keep authorization declarations explicit; strict mode helps.
- Verify with EML tests that declared restrictions are enforced without code.
Interview angle
Questions: "What field characteristics exist in RAP?", "What is the difference between readonly and readonly : update?", "What is a precheck?", "What does lock master unmanaged mean?"
Strong answer: list readonly, readonly:update, mandatory, mandatory:create, features:instance and numbering:managed with use cases; precheck rejects input before it enters the buffer or draft; internal operations are callable only within the BO; lock master unmanaged lets a managed BO use its own lock implementation. Emphasize that declarative rules are enforced by RAP before code runs.
Practice this lesson
Quick check
1. An external reference may be set when a request is created but never changed afterwards. Which field characteristic expresses this?
2. Document numbers must be gap-free and assigned only when the save is certain. Which BDEF numbering option fits?
3. A field in a behavior definition is declared with the static field characteristic 'readonly'. If the field should sometimes be editable depending on business logic (e.g., only before an order is confirmed), what must the developer do?
Interview questions
1. Explain field characteristics in a BDEF: readonly, readonly : update, mandatory, mandatory : create and features : instance. When would you use each?
Answer it in your own words first, then compare.
2. What do 'precheck', 'internal' and 'authorization : none' mean on BDEF operations, and what risks come with them?
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.
More lessons in this topic
- Behavior Definitions Part 1: Reading a BDEF as the BO Contract
- Behavior Definitions Part 3: Actions, Functions, Determinations and Validations
- Behavior Definitions Part 4: Associations, Compositions and Draft Declarations
- Behavior Definitions Part 5: Projection Behavior, Strict Mode and Stable Contracts