Skip to content

Lesson 17 Companion — RAP Draft ​

This companion supports:

text
Lesson 17 — RAP Draft

The core change is:

text
short-lived RAP transaction
→ persisted draft editing lifecycle

1. Draft architecture ​

text
ZRESV_###
Active Persistence
     ↑
     │ Activate
     │
ZDRESV_###
Draft Persistence
     ↑
     │
Draft-enabled RAP Runtime
     ↑
OData V4 / Fiori Elements

2. Exclusive draft ​

Lesson 17 uses:

abap
with draft;

This is exclusive draft.

One draft owner has exclusive modify access to the draft.

Collaborative Draft is a separate RAP capability and is not required here.


3. Draft persistence ​

Each draft-enabled entity requires:

text
active persistence
draft persistence

For this single-node BO:

text
ZRESV_###
ZDRESV_###

Use ADT Quick Fix to generate the draft table.


4. Generated draft table ​

SAP's draft-table generator derives storage from the CDS entity and adds technical draft administration.

Do not manually design:

text
draft admin fields

and do not directly write to the table.


5. Total ETag ​

Draft BOs require:

text
total etag

on the lock master.

Reference:

abap
lock master
total etag LastChangedAt

6. Local ETag vs total ETag ​

text
LocalLastChangedAt
→ etag master
→ normal entity concurrency

LastChangedAt
→ total etag
→ draft/active concurrency across draft lifetime

Keep both.


7. Owner determination reference ​

BDEF:

abap
field ( readonly ) ResponsibleUser;

determination setResponsibleUser on modify { create; }

Implementation:

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.

8. Why automatic owner matters ​

The Lesson 15 DCL is:

text
ResponsibleUser = aspect user

New drafts should acquire ownership automatically.

Otherwise UI create could depend on users knowing and typing technical identities.


9. Base BDEF reference ​

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;
  }
}

10. Draft actions ​

Edit ​

text
active → edit draft

Active persistence remains.

Activate ​

text
new draft → CREATE active
edit draft → UPDATE active
successful activation → draft removed

Discard ​

text
delete draft only

Resume ​

text
continue a durable draft after lock expiration

Prepare ​

text
execute assigned validations/determinations before activation

11. Activate optimized ​

Use:

abap
draft action Activate optimized;

The optimized variant can skip unnecessary repeated Prepare work when RAP knows the required validations/determinations have already executed and remain valid.


12. Prepare reference ​

abap
draft determine action Prepare
{
  validation validateCustomer;
  validation validateDate;
  validation validateFee;
}

Only already-defined BO validations/determinations can be assigned.


13. Prepare and Fiori Save ​

For a draft instance, Fiori Elements Save invokes Prepare before Activate.

Conceptual flow:

text
Save
 ↓
Prepare
 ↓
validations
 ↓
Activate

If validation fails:

text
Activate does not complete
draft remains

14. Draft authorization impact ​

Draft enablement adds framework actions.

Existing authorization implementations must handle requests for:

text
Edit

Apply the Lesson 15 update-style policy to Edit.

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.


15. Global authorization pattern ​

Training model:

text
create = allowed
delete = allowed
update-style requests = allowed

Update-style requests now include:

text
%update
%action-Edit

Reference:

abap
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.

The global authorization result is a structure. Fill only requested components and retain the existing %create and %delete handling.


16. Instance authorization pattern ​

Treat:

text
%update
%action-Edit

with the same owner check:

text
ResponsibleUser = current user

The instance authorization result is a table. Append one row per instance with its full %tky, then fill the requested components on that row. Retain Lesson 15's classroom cleanup policy for %delete.

Reference:

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.

Copying the full %tky preserves each instance's active/draft identity. Direct assignments such as result-%update belong to global authorization; in the instance handler, assign to the appended row.

Do not confuse:

text
draft Edit

with:

text
business confirm/cancel

17. Activate authorization ​

Activate itself is not modeled as an unrelated business privilege in this lesson.

The active create/update performed by activation is still subject to the BO's modifying authorization.


18. Discard authorization ​

Discard manages the user's draft persistence.

It is not the same as:

text
delete active Reservation

Do not reuse active delete business semantics blindly.


19. Projection BDEF reference ​

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;
}

20. Why projection needs use draft ​

A base BO can be draft-enabled while a particular projection is not.

Draft exposure is a projection choice.

The Lesson 16 UI projection should be draft-enabled.


21. Why projection does not repeat draft table ​

The draft table is an implementation detail of the base behavior.

Projection reuses it automatically.

Do not write:

text
draft table ...
total etag ...

in the projection BDEF.


22. Existing service artifacts ​

No new:

text
Service Definition
Service Binding

is required.

The existing:

text
OData V4 UI

service can expose the newly draft-enabled projection.


23. New draft lifecycle ​

Fiori Create:

text
CREATE request with draft state
↓
new draft table row
↓
determinations on modify
↓
user edits
↓
Save
↓
Prepare
↓
Activate
↓
active row created
↓
draft row removed

24. Edit draft lifecycle ​

text
active row
↓ Edit
copy to draft table
↓
user edits draft
├─ Discard → draft removed, active unchanged
└─ Save → Prepare → Activate → active updated

25. Draft table inspection ​

During training, Table Data Preview is useful for proving:

text
draft persistence really exists

But do not make business logic depend on draft-table SQL.

The draft table is a runtime artifact.


26. Active table inspection ​

While an edit draft exists:

text
active table
→ old saved values

draft table
→ work-in-progress values

This is the clearest demonstration of draft isolation.


27. Invalid draft ​

A draft may temporarily contain business-invalid values.

That is acceptable while the user is editing.

Activation must still enforce business validity.

This is why Prepare + validation is central.


28. Invalid active data is still forbidden ​

Draft does not weaken:

text
validateCustomer
validateDate
validateFee

It changes when/how the UI gets a chance to correct invalid work-in-progress data.


29. Draft locks ​

Exclusive draft establishes durable draft ownership/locking behavior beyond the short database transaction.

The lock is associated with the draft lifecycle rather than one ABAP request.


30. Resume ​

Resume matters after the original exclusive lock has expired while the draft still exists.

It recreates the edit lock if the runtime permits the user to continue.

No classroom timeout simulation is required.


31. Total ETag invalidation ​

If active data changes after an edit draft is created:

text
draft based on old active version

The total ETag lets RAP recognize the stale relationship.


32. Business status remains independent ​

Examples:

text
active + Status N
draft + Status N
active + Status C
draft based on Status C

Never encode draft lifecycle in the business Status domain.


33. Managed draft runtime ​

Even for unmanaged RAP BOs, draft handling itself is framework-managed.

For our current managed BO:

text
managed persistence
+
managed draft runtime

fit naturally.

This course uses managed RAP for the hands-on application.


34. Quick Fix is preferred ​

For draft table creation:

text
cursor on draft table name
Ctrl+1
Create draft table

This is safer and more certification-relevant than memorizing generated technical columns.


35. If root CDS changes later ​

If view elements change, ADT can offer a Quick Fix to adjust the draft table.

Draft persistence must stay compatible with the entity shape.


36. Fiori Create vs direct EML ​

Fiori draft Create creates a draft.

EML can explicitly distinguish draft and active operations.

Lesson 17 focuses on the Fiori/OData V4 lifecycle because that is where persistent draft editing becomes most visible.


37. Fiori Edit ​

Edit:

text
copies active data to draft

The active version remains the published business version until activation.


38. Fiori Save ​

Save:

text
Prepare
+
Activate

conceptually.

The exact requests are handled by the RAP/Fiori integration.


39. Fiori Cancel ​

The UI operation may be shown as:

text
Cancel
Discard

depending on context/version.

Conceptually it executes the draft discard lifecycle and leaves active data unchanged.


40. Action availability ​

Existing business actions:

text
confirm
cancel

still use feature control.

Draft capability does not replace business feature control.


41. Read authorization ​

Projection DCL from Lesson 16 remains required.

Draft enablement does not make DCL unnecessary.


42. Write authorization ​

Owner-based RAP authorization remains required.

Draft enablement adds authorization runtime paths rather than replacing them.


43. Common activation error — missing draft table ​

Symptom:

text
with draft
draft table name declared
table does not exist

Fix:

text
Ctrl+1 on draft table name
generate table
activate table

44. Common activation error — missing total ETag ​

Draft BO:

text
with draft

but no:

text
total etag

Fix the lock-master line.


45. Common strict-mode error — missing draft action ​

Explicitly declare:

text
Edit
Activate
Discard
Resume
Prepare

in base behavior.


46. Common strict projection error ​

If projection has:

text
use draft

also explicitly expose all required draft actions in strict mode.


47. Common runtime error — Edit denied ​

Check:

text
ResponsibleUser
current user
global authorization handler
instance authorization handler
%action-Edit authorization result

48. Common syntax errors — authorization components and result shape ​

If authorization code references a component for Prepare, remove that reference. Prepare is a draft determine action and has no independent authorization component.

Handle %action-Edit with the update-style policy, and retain normal %update and %delete handling.

If instance authorization code treats result as a structure, append a table row with %tky and fill the requested components on that row instead. See section 16.


49. Common runtime error — new draft hidden ​

Check:

text
setResponsibleUser determination
projection DCL
current user
draft create authorization

New draft ownership should be assigned automatically.


50. Common runtime error — invalid data activates ​

Check:

text
validation exists?
validation still on save?
validation listed in Prepare?
projection uses draft?

51. Common misunderstanding — draft row after Save ​

A successfully activated draft is normally removed.

The active table contains the new saved version.

Do not expect both to remain indefinitely.


52. Common misunderstanding — Discard is active delete ​

Discard removes draft persistence.

It does not mean:

text
delete active business object

53. Certification object map ​

text
Base BDEF
→ with draft
→ draft table
→ total etag
→ draft actions
→ Prepare

Draft table
→ persistent work-in-progress storage

Behavior Pool
→ existing rules + draft-aware auth changes

Projection BDEF
→ use draft + use draft actions

OData V4 UI
→ draft-aware consumer

54. Instructor demo sequence ​

Recommended:

text
1. Show non-draft service
2. Add owner determination
3. Add with draft
4. declare draft table
5. Quick Fix generate table
6. add total ETag
7. add draft actions
8. add validations to Prepare
9. adapt authorization
10. add use draft to projection
11. activate
12. Preview → Create
13. inspect draft table before Save
14. Save → inspect active/draft tables
15. Edit → change Notes
16. compare active vs draft
17. Discard
18. Edit → invalid date
19. Save → validation message
20. correct → Save

55. Ready-for-Lesson-18 test ​

Students are ready when they can explain:

text
active vs draft
new draft vs edit draft
draft table
total ETag
Edit
Activate
Discard
Resume
Prepare
validation before activation
draft-aware authorization
use draft in projection

without confusing any of those concepts with business Status.