Appearance
Lesson 17 — RAP Draft
Lesson 16 exposed the Reservation Business Object as an:
text
OData V4 UI serviceThe service already reuses:
text
managed CRUD
determinations
validations
messages
actions
feature control
authorization
DCLBut the editing model is still non-draft.
Today you add:
text
RAP DraftDraft changes the transactional user experience.
Instead of requiring one interaction to remain inside one short ABAP transaction, a draft can be persisted temporarily and resumed across requests and sessions.
The architecture becomes:
text
Fiori Elements
↓
OData V4 UI
↓
Draft-enabled Projection
↓
Draft-enabled RAP BO
┌───────────────┐
│ │
Active Table Draft Table
ZRESV_### ZDRESV_###
│ │
└──── Activate ─┘Lesson information
| Teacher-led time | About 3 hours |
| Self-practice time | About 3 hours |
| Environment | SAP BTP ABAP Trial |
| Prerequisite | Lesson 16 |
| Base BO | ZR_RESERVATION_### |
| Active table | ZRESV_### |
| Draft table | ZDRESV_### |
| Projection | ZC_RESERVATION_### |
| Service | Existing Lesson 16 OData V4 UI service |
| Draft type | Exclusive draft |
| Total ETag | LastChangedAt |
| Main outcome | Create, edit, validate, save, resume, and discard persistent drafts |
Replace:
text
###with your own student/group suffix.
Learning objectives
After the teacher-led part, you should be able to:
- explain why RAP Draft exists;
- distinguish business Status from RAP draft state;
- distinguish active data from draft data;
- explain new-draft vs edit-draft;
- explain why a draft table is required;
- generate a draft table with ADT Quick Fix;
- explain the draft administration include conceptually;
- enable exclusive draft with
with draft; - configure
draft table; - explain why a total ETag is mandatory for a draft BO;
- use
LastChangedAtas total ETag; - distinguish local ETag from total ETag;
- declare
Edit,Activate,Discard,Resume, andPrepare; - use
Activate optimized; - assign existing on-save validations to
Prepare; - explain how
Prepareprotects activation; - default
ResponsibleUserfor a new draft; - adapt global and instance authorization for draft actions;
- add
use draftto the projection BDEF; - reuse all draft actions in strict projection behavior;
- explain durable draft locks;
- inspect active and draft persistence separately;
- prove that an unsaved draft does not overwrite active persistence;
- prove that Discard removes draft changes;
- prove that invalid draft data cannot activate;
- explain the Fiori Elements Edit / Save / Cancel workflow;
- explain what activation does to the active and draft tables.
Draft Concept
1. Why normal transactions are not enough for UI editing
A normal RAP transaction is intentionally short.
Lesson 12 used:
text
MODIFY
READ
COMMITinside one ABAP consumer flow.
A human UI session is different.
A user may:
text
open an object
edit several fields
navigate away
return later
save after several requestsThe editing work needs durable intermediate storage.
That is what draft provides.
2. What is a RAP draft?
A draft is a persisted intermediate version of BO data.
It is stored separately from active business data.
text
Active instance
→ business data currently active
Draft instance
→ work in progressDraft handling lets an editing transaction span:
text
multiple HTTP requests
multiple ABAP sessions
human think time3. Draft is not a Status value
Do not confuse:
text
Status = Nwith:
text
draftN = New is business state.
Draft is framework-managed editing state.
A Reservation can be:
text
business Status = N
activeor:
text
business Status = N
draftThese are different dimensions.
4. Active and draft persistence
Before Lesson 17:
text
ZRESV_###
→ active business dataAfter Lesson 17:
text
ZRESV_###
→ active business data
ZDRESV_###
→ draft business data + draft runtime administrationDo not manually treat the draft table as an application table.
The RAP draft runtime owns it.
5. Two draft scenarios
New draft
There is:
text
draft instancebut no corresponding active instance yet.
Typical UI trigger:
text
CreateEdit draft
An active instance already exists.
RAP copies it into the draft table for editing.
Typical UI trigger:
text
EditTotal ETag
6. Local ETag vs total ETag
You already use:
text
LocalLastChangedAtas:
text
etag masterThat protects normal optimistic concurrency for the entity.
Draft also requires:
text
total ETagfor the whole lock-master BO.
7. Why total ETag exists
An edit draft can live longer than a normal lock lifetime.
RAP needs to know:
Has the active version changed since this draft was created?
The total ETag lets RAP detect an outdated draft.
8. Use LastChangedAt
Your root CDS already marks:
text
LastChangedAtwith:
abap
@Semantics.systemDateTime.lastChangedAt: trueThis is the correct existing field to use as:
text
total etagNo new timestamp is required.
Harden Ownership for Draft Creation
9. Why Lesson 15 ownership needs one refinement
Lesson 15 allowed the external create request to provide:
text
ResponsibleUserThat was useful for testing:
text
owned vs unassignedA Fiori draft create should not depend on the user manually entering their technical user ID before authorization becomes meaningful.
So Lesson 17 makes ownership system-derived.
10. Make ResponsibleUser read-only
Change:
abap
field ( readonly:update ) ResponsibleUser;to:
abap
field ( readonly ) ResponsibleUser;External consumers no longer assign ownership.
The BO determines it.
11. Add setResponsibleUser
Declare:
abap
determination setResponsibleUser on modify { create; }The rule:
text
new instance
→ ResponsibleUser = current technical userThis applies to:
text
new draft create
normal EML create12. Implement owner determination
Use:
abap
METHOD setResponsibleUser.
READ ENTITIES OF ZR_Reservation_### IN LOCAL MODE
ENTITY Reservation
FIELDS ( ResponsibleUser )
WITH CORRESPONDING #( keys )
RESULT DATA(reservations).
DATA updates TYPE TABLE FOR UPDATE ZR_Reservation_###.
DATA current_user TYPE abp_creation_user.
current_user = cl_abap_context_info=>get_user_technical_name( ).
LOOP AT reservations INTO DATA(reservation)
WHERE ResponsibleUser IS INITIAL.
APPEND VALUE #(
%tky = reservation-%tky
ResponsibleUser = current_user
) TO updates.
ENDLOOP.
IF updates IS NOT INITIAL.
MODIFY ENTITIES OF ZR_Reservation_### IN LOCAL MODE
ENTITY Reservation
UPDATE FIELDS ( ResponsibleUser )
WITH updates.
ENDIF.
ENDMETHOD.The provider may fill a read-only field through local-mode EML.
Enable Draft in the Base BDEF
13. Add with draft
Open the base Behavior Definition.
After:
abap
strict ( 2 );add:
abap
with draft;This draft-enables the whole BO.
14. Draft applies to the BO, not one random field
with draft is a BO-level capability.
It does not mean:
text
Status becomes draftor:
text
one field is draftedThe RAP BO participates in the draft lifecycle.
15. Add the draft table
After:
abap
persistent table zresv_###add:
abap
draft table zdresv_###At first, ZDRESV_### does not exist.
That is intentional.
16. Generate the draft table with Quick Fix
Place the cursor on:
text
zdresv_###Use:
text
Ctrl+1Choose the Quick Fix equivalent to:
text
Create draft table ZDRESV_### for entity ZR_RESERVATION_###Let ADT generate the table.
Do not manually guess the draft table structure.
17. Inspect the generated draft table
The generated draft table contains:
text
one storage field for relevant root view elements
+
technical draft-administration informationThe RAP runtime uses the technical draft fields to manage the draft lifecycle.
Activate the generated table.
18. Do not hand-maintain the draft table
The draft table is:
text
runtime persistencenot:
text
normal business-maintenance persistenceDo not:
text
INSERT
UPDATE
DELETEdraft rows manually.
Use RAP Draft.
19. Add total ETag
Change:
abap
lock masterto:
abap
lock master
total etag LastChangedAtThe total ETag must immediately follow the lock-master definition in the BDEF structure.
20. Keep the local ETag
Also keep:
abap
etag master LocalLastChangedAtNow the BO has:
text
LocalLastChangedAt
→ local/entity ETag
LastChangedAt
→ total ETag for draft concurrencyBoth have distinct roles.
Draft Actions
21. Draft actions are framework operations
Draft-enabled BOs have a standard draft lifecycle.
The important actions are:
text
Edit
Activate
Discard
Resume
PrepareThese are not your business actions:
text
confirm
cancelThey belong to the RAP draft framework.
22. Edit
Edit creates an edit draft from an active instance.
Flow:
text
active row
↓ Edit
active row stays
+
draft copy createdThe active row is not overwritten merely because editing started.
23. Activate
Activate transfers valid draft changes into active data.
For an edit draft:
text
draft
→ UPDATE active
→ draft removedFor a new draft:
text
draft
→ CREATE active
→ draft removed24. Use optimized Activate
Declare:
abap
draft action Activate optimized;The optimized variant can avoid unnecessary repeated determination/validation work when the BO modeling rules allow it.
25. Discard
Declare:
abap
draft action Discard;Discard:
text
deletes the draft instance
keeps the active instance unchangedFor a new draft, Discard means:
text
no active business object is created26. Resume
Declare:
abap
draft action Resume;Resume is used when work on an existing draft continues after the original exclusive lock period has expired.
It re-establishes the draft editing lock where permitted.
27. Prepare
Prepare is a:
text
draft determine actionIt runs selected existing:
text
validations
determinationsbefore activation.
In Fiori Elements, Save invokes Prepare before Activate.
Connect Existing Validations to Prepare
28. Why existing on-save validations need Prepare
You already have:
text
validateCustomer
validateDate
validateFeeFor draft activation, you want those business checks to run while the draft is being prepared for transition to active data.
Add them to:
text
Prepare29. Define Prepare
Use:
abap
draft determine action Prepare
{
validation validateCustomer;
validation validateDate;
validation validateFee;
}You are reusing the Lesson 13 validations.
You are not creating duplicate validation methods.
30. Why setInitialStatus is not listed in Prepare
setInitialStatus is:
text
on modify { create; }It runs when the new draft is created.
It does not need to be delayed until activation.
Same for:
text
setResponsibleUser31. Save flow with validation
Fiori Elements Save conceptually triggers:
text
Prepare
↓
validateCustomer
validateDate
validateFee
↓
valid?
┌─┴─┐
yes no
↓ ↓
Activate
draft remains
messages returnedInvalid draft data should not become active.
Complete Base BDEF Shape
32. Base BDEF reference
Your base BDEF should now be equivalent to:
abap
managed implementation in class zbp_r_resv_### unique;
strict ( 2 );
with draft;
define behavior for ZR_Reservation_### alias Reservation
persistent table zresv_###
draft table zdresv_###
lock master
total etag LastChangedAt
authorization master ( global, instance )
etag master LocalLastChangedAt
{
create;
update;
delete;
field ( numbering : managed, readonly ) Uuid;
field ( readonly )
Status,
ResponsibleUser,
LocalCreatedBy,
LocalCreatedAt,
LocalLastChangedBy,
LocalLastChangedAt,
LastChangedAt;
field ( mandatory:create, readonly:update ) ReservationNo;
field ( features : instance ) Fee, CurrencyCode;
determination setInitialStatus on modify { create; }
determination setResponsibleUser on modify { create; }
validation validateCustomer on save
{ create; field CustomerName; }
validation validateDate on save
{ create; field ReservationDate; }
validation validateFee on save
{ create; field Fee, CurrencyCode; }
action ( features : instance, authorization: update )
confirm result [1] $self;
action ( features : instance, authorization: update )
cancel result [1] $self;
draft action Edit;
draft action Activate optimized;
draft action Discard;
draft action Resume;
draft determine action Prepare
{
validation validateCustomer;
validation validateDate;
validation validateFee;
}
mapping for zresv_###
{
Uuid = uuid;
ReservationNo = reservation_no;
CustomerName = customer_name;
CustomerEmail = customer_email;
WorkshopCode = workshop_code;
ReservationDate = reservation_date;
Status = status;
ResponsibleUser = responsible_user;
Fee = fee;
CurrencyCode = currency_code;
Notes = notes;
LocalCreatedBy = local_created_by;
LocalCreatedAt = local_created_at;
LocalLastChangedBy = local_last_changed_by;
LocalLastChangedAt = local_last_changed_at;
LastChangedAt = last_changed_at;
}
}Draft-Aware Authorization
33. Why Lesson 15 authorization must be revisited
Draft introduces the authorization-controlled action:
text
EditIt must fit the existing update-style owner policy.
Prepare is a draft determine action, not an independently authorization-controlled action. Its components do not exist in the generated authorization structures, so do not check or populate authorization fields for it.
Do not assume the old Lesson 15 handler automatically knows about newly introduced draft requests.
34. Global authorization — treat Edit like update
Your global training policy already allows update.
Apply the same update-style policy to a request for:
text
%action-Editreceives the same allow decision.
Conceptually:
text
update requested
OR Edit requested
→ update-style authorization35. Global authorization pattern
Use a pattern equivalent to:
abap
METHOD get_global_authorizations.
IF requested_authorizations-%create = if_abap_behv=>mk-on.
result-%create = if_abap_behv=>auth-allowed.
ENDIF.
IF requested_authorizations-%update = if_abap_behv=>mk-on.
result-%update = if_abap_behv=>auth-allowed.
ENDIF.
IF requested_authorizations-%action-Edit = if_abap_behv=>mk-on.
result-%action-Edit = if_abap_behv=>auth-allowed.
ENDIF.
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
result-%delete = if_abap_behv=>auth-allowed.
ENDIF.
ENDMETHOD.This keeps the existing create/delete handling and fills only requested components. The global authorization result is a structure.
36. Instance authorization — owner rule remains
For an existing active Reservation:
text
ResponsibleUser = current user
→ update-style operations allowedThat should also protect:
text
Editwhen RAP requests its authorization result. Normal update/delete authorization continues through %update and %delete.
37. Instance authorization request detection
Treat either of these as requiring the same owner check:
text
%update
%action-EditThen fill the relevant requested result components with:
text
auth-allowed
or
auth-unauthorizedUnlike global authorization, get_instance_authorizations returns a result table. Append one row per instance with its %tky, then fill the requested components on that row.
Use:
abap
METHOD get_instance_authorizations.
READ ENTITIES OF ZR_Reservation_### IN LOCAL MODE
ENTITY Reservation
FIELDS ( ResponsibleUser )
WITH CORRESPONDING #( keys )
RESULT DATA(reservations)
FAILED failed.
DATA current_user TYPE abp_creation_user.
current_user = cl_abap_context_info=>get_user_technical_name( ).
LOOP AT reservations INTO DATA(reservation).
APPEND VALUE #(
%tky = reservation-%tky
) TO result ASSIGNING FIELD-SYMBOL(<authorization>).
IF requested_authorizations-%update = if_abap_behv=>mk-on.
<authorization>-%update =
COND #(
WHEN reservation-ResponsibleUser = current_user
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized
).
ENDIF.
IF requested_authorizations-%action-Edit = if_abap_behv=>mk-on.
<authorization>-%action-Edit =
COND #(
WHEN reservation-ResponsibleUser = current_user
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized
).
ENDIF.
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
<authorization>-%delete = if_abap_behv=>auth-allowed.
ENDIF.
ENDLOOP.
ENDMETHOD.The delete decision retains Lesson 15's classroom cleanup policy. Copy the full %tky from the read result so each authorization row retains the instance's active/draft identity.
38. Why Activate is different
Activation performs the underlying save:
text
CREATE active
or
UPDATE activeAuthorization for the modifying operation protects the transition.
Do not invent a separate custom authorization model for:
text
Activatein this lesson.
39. Why Discard is different
Discard removes:
text
draft dataThe draft framework controls that lifecycle action.
It is not a business delete of the active Reservation.
40. New drafts and ownership
Your new determination:
text
setResponsibleUserruns on create.
Therefore a new draft receives:
text
ResponsibleUser = current userautomatically.
This makes the existing owner-based DCL and instance authorization compatible with UI draft creation.
Draft-Enable the Projection
41. Open the projection BDEF
Open the Lesson 16 projection Behavior Definition for:
text
ZC_RESERVATION_###Current header:
abap
projection;
strict ( 2 );Add:
abap
use draft;42. Why use draft
The base BO is now draft-enabled.
The projection decides whether the service should expose that draft behavior.
For this UI service:
text
yesSo declare:
abap
use draft;43. Reuse draft actions explicitly
Strict projection behavior requires the draft actions to be listed.
Add:
abap
use action Edit;
use action Activate;
use action Discard;
use action Resume;
use action Prepare;44. Complete projection BDEF
Use:
abap
projection;
strict ( 2 );
use draft;
define behavior for ZC_Reservation_### alias Reservation
use etag
{
use create;
use update;
use delete;
use action Edit;
use action Activate;
use action Discard;
use action Resume;
use action Prepare;
use action confirm;
use action cancel;
}The projection does not repeat:
text
draft table
total etagThose are reused implementation details from the base BO.
Activate the Draft Stack
45. Activation order
A practical activation sequence is:
text
1. root CDS / persistence changes
2. draft table
3. base BDEF
4. Behavior Pool
5. projection BDEF
6. service artifacts if ADT reports dependenciesUse:
text
Ctrl+Shift+F3when related activation is helpful.
46. Service Definition does not change
Your Lesson 16 Service Definition already exposes:
text
ZC_RESERVATION_###The entity name did not change.
No new service entity is required just because the BO became draft-enabled.
47. Service Binding does not need a new name
Keep:
text
ZUI_RESV_###_O4The OData V4 UI binding is already the correct service type.
Activate changed artifacts and refresh/reopen the preview.
If the binding editor indicates publishing is required, publish the local service again.
Runtime Test 1 — New Draft
48. Open the Fiori Elements preview
Open:
text
ZUI_RESV_###_O4Launch:
text
Reservations
→ PreviewThe UI should now present a draft-aware transactional flow.
49. Start a new Reservation
Choose:
text
CreateIn an OData V4 draft UI, Create creates:
text
a new draftnot an active row immediately.
Enter valid values such as:
text
ReservationNo = 99100001
CustomerName = Draft Student
CustomerEmail = draft@example.com
WorkshopCode = RAP401
ReservationDate = today
Fee = 300.00
CurrencyCode = EUR
Notes = New draft testDo not enter:
text
Status
ResponsibleUser
Uuid
admin fieldsThe BO owns those values.
50. Observe automatic fields
The create determinations should produce:
text
Status = N
ResponsibleUser = current userThe BO remains the source of those defaults.
51. Do not save yet
Leave the new object in draft state.
At this point:
text
draft exists
active instance does not yet existThis is the best moment to inspect persistence.
52. Inspect the active table
Open:
text
ZRESV_###Use:
text
Alt+F8Filter:
text
99100001Expected:
text
no active row yet53. Inspect the draft table
Open:
text
ZDRESV_###Use Table Data Preview.
Find the draft corresponding to:
text
99100001Expected:
text
draft row existsAlso inspect the generated technical draft administration fields.
Do not modify them.
54. Save the new draft
Return to the Fiori preview.
Choose:
text
SaveConceptually:
text
Prepare
↓
validations
↓
Activate
↓
CREATE active instance
↓
remove draft55. Verify after activation
Active table:
text
ZRESV_###
→ 99100001 existsDraft table:
text
ZDRESV_###
→ draft for 99100001 removedProtected projection:
text
ZC_RESERVATION_###
→ active row visibleRuntime Test 2 — Edit Draft and Discard
56. Open active 99100001
From the Fiori Elements preview, open the active Reservation.
Choose:
text
EditRAP creates an:
text
edit draftfrom the active instance.
57. Change Notes only
Change:
text
Notesto:
text
This change will be discardedDo not save.
58. Inspect active persistence while editing
Open:
text
ZRESV_###Expected:
text
active Notes still contain the old saved valueEditing has not overwritten active persistence.
59. Inspect draft persistence
Open:
text
ZDRESV_###Expected:
text
draft row contains the unsaved Notes changeNow you can see the two versions simultaneously.
60. Discard the edit draft
Return to the UI.
Choose the UI operation equivalent to:
text
Cancel / DiscardExpected:
text
draft row removed
active row unchanged61. Verify discard
Active:
text
Notes = original saved valueDraft:
text
no edit draft for 99100001This proves Discard is not Delete.
Runtime Test 3 — Validation During Draft Save
62. Edit the active Reservation again
Choose:
text
EditSet:
text
ReservationDate = yesterdayThis violates the Lesson 13 rule.
63. Attempt Save
Choose:
text
SaveThe draft lifecycle invokes:
text
Prepareand therefore:
text
validateDateExpected:
text
activation fails
validation message appears
draft remains available for correction
active row remains unchanged64. Why the draft remains
The invalid data is allowed to exist as:
text
work in progressbut it is not allowed to become:
text
active business dataThis is one of the main benefits of draft.
65. Correct the date
Change:
text
ReservationDateback to:
text
today or futureChoose:
text
SaveExpected:
text
Prepare succeeds
Activate succeeds
active row updated
draft removedRuntime Test 4 — Resume Concept
66. What Resume solves
Draft editing can outlive an ordinary database lock.
If the exclusive lock expires while the durable draft still exists:
text
Resumere-establishes the editing lock when permitted.
You do not need to wait for a real lock timeout during class.
Understand the lifecycle role.
67. Durable draft vs short transaction
Normal Lesson 12 buffer:
text
short-lived transactional stateDraft:
text
persisted intermediate state
survives across requests/sessionsThis distinction is certification-relevant.
Active vs Draft Identity
68. Same business object, two versions
For an edit draft:
text
active version
+
draft versionrefer to the same logical BO instance.
The draft runtime tracks the relationship.
Do not design a second business key for the draft.
69. Managed UUID still matters
The same UUID-based identity model continues to support the BO.
Draft does not mean:
text
generate unrelated UUID for active copyThe runtime manages active/draft identity correctly.
Draft Actions vs Business Actions
70. Framework draft actions
text
Edit
Activate
Discard
Resume
Preparemanage editing lifecycle.
71. Business actions
text
confirm
cancelexpress Reservation business transitions.
These remain separate concepts.
Do not rename:
text
confirmto:
text
ActivateThey solve unrelated problems.
72. Example
A Reservation can be:
text
active
Status = NThen:
text
Edit
→ create draft for editingLater:
text
Activate
→ save draft changesThen business action:
text
confirm
→ Status N → CDraft lifecycle and business lifecycle are independent.
Total ETag and Concurrency
73. Outdated draft scenario
Imagine:
text
User starts edit draftThen somehow the active instance changes independently.
When the user later tries to continue/activate the old draft:
text
total ETag comparisonhelps RAP detect that the draft is based on stale active data.
74. Why LastChangedAt is appropriate
The total ETag needs an active timestamp that changes whenever active data changes.
Your existing:
text
LastChangedAthas the semantic role required for this purpose.
Authorization with Draft
75. DCL remains read protection
The existing DCL still protects the service's read surface.
Draft does not remove:
text
ResponsibleUser = current userread authorization.
76. Instance authorization remains write protection
Owner-based authorization still protects changes to active business objects and the edit lifecycle.
The authorization handler checks %action-Edit when requested, alongside %update and %delete. Prepare remains part of validation/determination processing and has no independent authorization component.
77. New-draft create authorization
Creating a new draft uses the create authorization path.
Our Trial global create policy allows it.
The new determination then assigns:
text
ResponsibleUser = current user78. Edit-draft authorization
Editing an existing active instance must respect the existing owner policy.
That is why:
text
Editis handled like update in the authorization implementation.
Common Mistakes
79. Mistake — use Status D as Draft
Wrong:
text
Status D means RAP draftCorrect:
text
business Status
and
RAP draft state
are separate80. Mistake — manually create the draft table
Prefer:
text
Ctrl+1
Generate draft tableThe generated table requires RAP draft administration structure.
Do not guess it manually.
81. Mistake — forget total ETag
A draft-enabled BO requires a total ETag on the lock master.
For this BO:
text
LastChangedAtis the intended field.
82. Mistake — replace local ETag with total ETag
Keep both:
text
etag master LocalLastChangedAt
total etag LastChangedAtThey serve different concurrency purposes.
83. Mistake — declare draft actions but no Prepare validations
If Prepare contains no relevant validations, the draft UI may reach activation without the intended pre-activation validation flow.
Reuse your existing business validations.
84. Mistake — duplicate validation implementations
Do not write:
text
validateCustomerForDraftwhen the same rule already exists.
Assign:
text
validateCustomerto Prepare.
85. Mistake — forget use draft in projection
Base draft capability does not automatically mean every projection exposes draft behavior.
Add:
abap
use draft;to the projection BDEF.
86. Mistake — omit draft actions from strict projection BDEF
With strict projection behavior, explicitly reuse:
text
Edit
Activate
Discard
Resume
Prepare87. Mistake — create a second Service Binding
The existing:
text
OData V4 UIbinding is already the right consumption layer.
Draft-enable the BO/projection rather than creating a duplicate service merely for draft.
88. Mistake — use direct SQL on draft table
Never use normal business logic to:
text
INSERT draft row
UPDATE draft row
DELETE draft rowRAP owns draft persistence.
89. Mistake — authorization ignores draft actions
After enabling Draft, revisit:
text
get_global_authorizations
get_instance_authorizationsHandle the generated %action-Edit component using the update-style policy. Do not add authorization components for the draft determine action Prepare.
Keep the result shapes distinct: global authorization fills a structure; instance authorization appends table rows keyed by %tky.
90. Mistake — let the user type owner identity
Lesson 17 hardens:
text
ResponsibleUseras system-derived.
New draft creation should not depend on typing a technical user ID.
Certification Alignment
91. Practical draft tasks
A system-based RAP task can ask you to:
text
add with draft
define a draft table
generate draft persistence
add total etag
declare draft actions
wire validations into Prepare
draft-enable a projection
repair missing use action statements
test Fiori draft behaviorYou should recognize which artifact owns each part.
92. Draft repair map
If:
text
draft table missing
→ base BDEF + Quick Fix
outdated draft/concurrency error
→ total ETag / timestamp model
Save allows invalid data
→ Prepare assignments / validation
UI has no Edit/Save draft flow
→ base draft + projection use draft + service metadata
Edit unauthorized unexpectedly
→ authorization handler draft requests
active data changes before Save
→ draft architecture is wrong / bypassed
Discard deletes active row
→ severe modeling/runtime misunderstandingKnowledge Check
93. Questions
1. Why does RAP Draft need separate persistence?
2. What is the difference between a new draft and an edit draft?
3. Why is Status N not the same as Draft?
4. What does with draft do?
5. Why should ADT generate the draft table?
6. What is the difference between local ETag and total ETag?
7. Why is total ETag mandatory for draft?
8. What does Edit do?
9. What does Activate do?
10. What does Discard do?
11. What does Resume do?
12. What does Prepare do?
13. Why are Lesson 13 validations assigned to Prepare?
14. Why does ResponsibleUser become system-derived?
15. Why must authorization handlers be revisited after draft enablement?
16. What does use draft do in the projection BDEF?
17. Why are draft actions listed explicitly in strict projection behavior?
18. Does the Service Definition need a second Reservation entity for draft?
19. Does an unsaved edit draft overwrite active persistence?
20. What happens to the draft row after successful activation?
Teacher-Led Completion Checklist
94. Checklist
End-of-Day Mental Model
95. Final model
text
Fiori Elements
↓
OData V4
↓
Draft-enabled Projection
↓
Draft-enabled RAP BO
↓
┌──────────┴──────────┐
↓ ↓
Active Persistence Draft Persistence
ZRESV_### ZDRESV_###
↑ │
└──── Activate ───────┘Draft lifecycle:
text
Active
↓ Edit
Edit Draft
├─ Discard → Active unchanged
└─ Prepare → Validate
↓
Activate
↓
Active updatedNew-object lifecycle:
text
Create
↓
New Draft
├─ Discard → nothing active
└─ Prepare → Validate
↓
Activate
↓
Active createdLesson 18 will extend this from a single-node BO to:
text
Compositions
→ parent/child business objects
→ draft-aware composition trees