RAP pitfalls
What you'll learn
An ETag pinned to a field that never changes silently switches off optimistic locking — anchor it to a LocalLastChangedAt that a determination bumps.
- An ETag on a non-changing field silently disables optimistic locking — use a LocalLastChangedAt updated by a determination.
- READ/MODIFY ENTITIES IN LOCAL MODE skips DCL — fine inside the BO, a leak if surfaced without re-checking auth.
- UPDATE FIELDS ( ... ) is an allow-list — a field you forget to list is silently not updated, no error.
The RAP pitfall that quietly corrupts data integrity is a mis-wired ETag. Optimistic locking compares the ETag the client read against the current value on save; if they differ, the save is rejected. But if you bind the ETag to a field that never changes, the comparison always passes and concurrent edits silently overwrite each other — locking is effectively disabled with no error anywhere. The correct pattern is an ETag master on a LocalLastChangedAt field that a determination updates on every save, so the token genuinely moves.
Two more traps come from the LOCAL MODE keyword. READ/MODIFY ENTITIES ... IN LOCAL MODE deliberately skips DCL authorization — which is correct *inside* the behaviour pool where you have already passed the entry-point check, but a defect if you hand that result to a UI or external consumer without re-checking. And MODIFY ENTITIES ... UPDATE FIELDS ( ... ) updates *only* the fields you list: forget one in the parenthesised list and that field is silently left unchanged, with no error. The FIELDS list is an allow-list, not a hint.
The last is ordering with late numbering. ADJUST_NUMBERS assigns the real key once per save, *after* the determination phase. So a DETERMINE ON SAVE that runs before numbering cannot read the final key — it sees the temporary one. If downstream logic depends on the assigned number, it must run in or after the numbering step, not before it.
Key points
- An ETag on a non-changing field silently disables optimistic locking — use a LocalLastChangedAt updated by a determination.
- READ/MODIFY ENTITIES IN LOCAL MODE skips DCL — fine inside the BO, a leak if surfaced without re-checking auth.
- UPDATE FIELDS ( ... ) is an allow-list — a field you forget to list is silently not updated, no error.
- Late numbering (ADJUST_NUMBERS) runs after determinations — you cannot read the assigned key before it.
Examples
OrderId never changes, so the ETag comparison always matches — concurrent saves silently clobber each other.
ABAPmanaged implementation in class zbp_i_order unique;
define behavior for zi_order alias order
persistent table zorder_hdr
etag master order_id { }A determination updates local_last_changed_at on every save, so the ETag actually moves and stale writes are rejected.
ABAPmanaged implementation in class zbp_i_order unique;
define behavior for zi_order alias order
persistent table zorder_hdr
etag master local_last_changed_at { }Source notes: clean-core-curriculum §10.3
Ask Claude
Build a prompt from this lesson + your question and open a fresh Claude chat with it pre-filled — handy for adapting a before/after pattern to your own object.