Draft Handling Part 2: Draft Lifecycle — Create, Edit, Resume, Activate, Discard
Follow the draft lifecycle step by step — new draft, Edit, Resume, Prepare, Activate and Discard — and see what happens in the data, the locks and the UI at each step.
Explanation
📌 KEY POINTS
✅ New object: starts as draft → Activate creates the active instance.
✅ Existing object: Edit creates a draft copy + exclusive lock → Activate writes it back.
✅ Prepare runs validations before activation; Discard throws the draft away.
💡 Resume re-acquires the lock when a user returns to an old draft.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 1 explained draft and active instances. This part walks through each lifecycle step, with what the user sees and what happens technically.
━━━━━━━━━━━━━━━━━━━━
▶ STEP A — CREATE A NEW OBJECT
- User clicks Create in the list report.
- Technically: CREATE with %is_draft = mk-on. Only a draft instance exists; no active data yet.
- Determinations on modify run (e.g. default status).
- The user sees an object page with "Draft" status.
━━━━━━━━━━━━━━━━━━━━
▶ STEP B — EDIT AN EXISTING OBJECT
- User clicks Edit on an active object.
- Technically: draft action Edit — copies the active instance (with children) into the draft tables and sets an exclusive lock on the active instance.
- Other users now see "Locked by <user>".
- If the user already has a draft for this object, Edit fails; the UI offers to continue the existing draft.
━━━━━━━━━━━━━━━━━━━━
▶ STEP C — CHANGE FIELDS
- Every field change is an UPDATE on the draft instance, saved immediately in the draft tables.
- Determinations on modify run; side effects tell the UI which fields to refresh.
- Nothing changes in the active data.
━━━━━━━━━━━━━━━━━━━━
▶ STEP D — RESUME
- The user leaves and comes back later. If the exclusive lock has expired, the draft still exists, but the lock must be re-acquired.
- Draft action Resume does that (and checks that the active data has not been changed in the meantime via the total ETag). If someone else changed the object in between, resuming or activating can fail.
━━━━━━━━━━━━━━━━━━━━
▶ STEP E — PREPARE
- When the user clicks Save, Fiori first calls Prepare.
- Prepare runs the validations (and determinations) listed in "draft determine action Prepare" on the draft.
- If validations fail, messages are shown and nothing is activated — the user can correct the draft.
━━━━━━━━━━━━━━━━━━━━
▶ STEP F — ACTIVATE
- Draft action Activate copies the draft into active data and runs the full save sequence (on-save determinations, validations, save).
- The draft is deleted and the lock released.
- "Activate optimized" (current releases) avoids unnecessary reprocessing of unchanged data — use it for new BOs.
━━━━━━━━━━━━━━━━━━━━
▶ STEP G — DISCARD
- User clicks Discard (or Cancel).
- Draft action Discard deletes the draft and releases the lock. The active data stays unchanged.
━━━━━━━━━━━━━━━━━━━━
▶ AUTOMATIC CLEANUP
Old, abandoned drafts are removed automatically by the framework after a configurable lifetime, so orphan drafts do not accumulate forever.
⚠️ WATCH OUT: Activate is not "just a save" — it runs validations and on-save determinations. A draft that passed Prepare can still fail at Activate if on-save logic finds a problem.
✅ CHECKPOINT: you can explain every button of a draft-enabled Fiori app in technical terms. The code example does the same lifecycle with EML.
Code example
" ===== Draft lifecycle with EML (e.g. in a console class or test) ===== " --- A: create a NEW object as draft ---MODIFY ENTITIES OF zr_purchreq ENTITY PurchaseRequest CREATE FIELDS ( Description CurrencyCode ) WITH VALUE #( ( %cid = 'N1' %is_draft = if_abap_behv=>mk-on Description = 'Monitors' CurrencyCode = 'EUR' ) ) MAPPED DATA(mapped). " --- E+F: prepare and activate the new draft ---MODIFY ENTITIES OF zr_purchreq ENTITY PurchaseRequest EXECUTE Prepare FROM VALUE #( ( %key = mapped-purchaserequest[ 1 ]-%key ) ) ENTITY PurchaseRequest EXECUTE Activate FROM VALUE #( ( %key = mapped-purchaserequest[ 1 ]-%key ) ) FAILED DATA(failed) REPORTED DATA(reported).COMMIT ENTITIES RESPONSE OF zr_purchreq FAILED DATA(c_failed) REPORTED DATA(c_reported). " --- B: EDIT an existing active object (creates draft + exclusive lock) ---MODIFY ENTITIES OF zr_purchreq ENTITY PurchaseRequest EXECUTE Edit FROM VALUE #( ( %key = existing_key %param-preserve_changes = abap_true ) ) RESULT DATA(edit_result) FAILED DATA(edit_failed)." preserve_changes = true: fail instead of overwriting an existing draft " --- C: change the DRAFT (active data untouched) ---MODIFY ENTITIES OF zr_purchreq ENTITY PurchaseRequest UPDATE FIELDS ( Description ) WITH VALUE #( ( RequestUUID = existing_key-RequestUUID %is_draft = if_abap_behv=>mk-on Description = 'Ergonomic monitors' ) ).COMMIT ENTITIES. " persists the DRAFT change only " --- G: DISCARD the draft (lock released, active unchanged) ---MODIFY ENTITIES OF zr_purchreq ENTITY PurchaseRequest EXECUTE Discard FROM VALUE #( ( %key = existing_key ) ).COMMIT ENTITIES. " ===== OData equivalents (V4) =====" POST .../PurchaseRequest(RequestUUID=..,IsActiveEntity=true)/com.sap.gateway.srvd.zui_purchreq.v0001.Edit" POST .../PurchaseRequest(RequestUUID=..,IsActiveEntity=false)/...Prepare" POST .../PurchaseRequest(RequestUUID=..,IsActiveEntity=false)/...Activate" DELETE .../PurchaseRequest(RequestUUID=..,IsActiveEntity=false) -> discardReal project scenario
Support received complaints that "Save does nothing" in a draft app. Analysis showed that Prepare returned validation errors, but the messages were not visible because the validations did not set %element or %state_area, and Fiori showed only a generic popup that users closed.
After adding field references and state areas to the validation messages, users saw the errors next to the fields during Prepare. The team also documented the lifecycle for key users — Edit, Prepare, Activate, Discard — which reduced confusion about "locked" objects and old drafts.
Common mistakes
- Treating Activate as a simple save without validations.
- Validations not listed in Prepare, so errors appear only at activation.
- Forgetting Resume in the BDEF/projection, so returning users get errors.
- Editing with preserve_changes = false and overwriting an existing draft.
- Using %tky of the active instance when changing the draft.
- Believing drafts disappear by themselves immediately.
Best practices
- Know the lifecycle: create/edit → change → resume → prepare → activate/discard.
- List all relevant validations in Prepare.
- Use Activate optimized for new BOs.
- Test the full lifecycle with EML, including edit conflicts.
- Explain draft behavior to key users.
Interview angle
Questions: "Explain the draft lifecycle", "What do Edit, Prepare, Activate, Resume and Discard do?", "When do validations run in draft?"
Strong answer: new objects start as draft; Edit copies active to draft with an exclusive lock; changes are saved to the draft; Resume re-acquires the lock; Prepare runs listed validations; Activate copies draft to active through the full save sequence and deletes the draft; Discard deletes the draft and releases the lock. Mention abandoned-draft cleanup and Activate optimized.
Practice this lesson
Quick check
1. Users say changing a supplier "did not save", but the draft contains the new value. What is most likely?
2. What occurs when a draft instance is successfully activated in a RAP-based business object?
3. Which standard draft action allows a user to start modifying an already saved (active) business object instance by creating a corresponding draft instance?
Interview questions
1. Walk through the draft lifecycle actions: Edit, Resume, Prepare, Activate and Discard.
Answer it in your own words first, then compare.
2. Users report 'Save does nothing' in a draft app. How do you investigate?
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.