Draft Handling ermöglicht es Benutzern, Änderungen an Business Objects zwischenzuspeichern, ohne sie sofort in die Datenbank zu schreiben. Dies ist besonders wichtig für komplexe Eingabeformulare in Fiori-Anwendungen. Mit Draft Handling können Benutzer ihre Arbeit unterbrechen, zu einem späteren Zeitpunkt fortsetzen und erst dann die Änderungen aktivieren, wenn alle Eingaben vollständig und validiert sind.
In diesem Artikel lernen Sie, wie Draft Handling in RAP funktioniert, wie Sie draft-fähige CDS Views und Behavior Definitions erstellen, und welche Draft Actions für typische Workflows zur Verfügung stehen.
Das Draft-Konzept: Active vs. Draft Instanzen
Das zentrale Konzept beim Draft Handling ist die Unterscheidung zwischen aktiven Instanzen und Draft-Instanzen:
-
Aktive Instanzen (Active Entities): Die persistenten Daten in der Datenbanktabelle. Diese repräsentieren den aktuellen, gültigen Zustand des Business Objects und sind für alle Benutzer sichtbar.
-
Draft-Instanzen (Draft Entities): Temporäre Arbeitskopien, die in einer separaten Draft-Tabelle gespeichert werden. Ein Draft ist nur für den bearbeitenden Benutzer sichtbar und enthält noch nicht validierte oder unvollständige Änderungen.
Der Lebenszyklus eines Drafts sieht typischerweise so aus:
- Edit: Benutzer startet die Bearbeitung → System erstellt Draft-Kopie
- Modify: Benutzer ändert Daten → Änderungen werden automatisch im Draft gespeichert
- Prepare: System führt Validierungen aus → Fehler werden angezeigt, aber Draft bleibt erhalten
- Activate: Benutzer aktiviert → Draft wird zur aktiven Instanz, Draft-Eintrag wird gelöscht
Alternativ kann der Benutzer jederzeit Discard wählen, um den Draft zu verwerfen, ohne die aktive Instanz zu ändern.
Wann brauche ich Draft?
Draft Handling ist sinnvoll bei:
- Komplexen Eingabemasken mit vielen Feldern
- Mehrstufigen Workflows, bei denen Benutzer zwischenspeichern möchten
- Langlebigen Transaktionen, die nicht in einer Session abgeschlossen werden
- Validierungen, die erst bei Aktivierung ausgeführt werden sollen
Draft vs. Non-Draft Szenarien
| Aspekt | Draft | Non-Draft |
|---|---|---|
| Speicherung | Separate Draft-Tabelle | Direkt in Datenbanktabelle |
| Zwischenspeichern | Ja, automatisch | Nein |
| Validierung | Bei Prepare/Activate | Bei jedem Save |
| Komplexität | Höher | Niedriger |
| Fiori-UX | Verbessert (Auto-Save) | Standard |
| Use Case | Komplexe Formulare | Einfache CRUD-Apps |
Non-Draft Szenario (Standard)
managed implementation in class zbp_i_travel unique;strict ( 2 );
define behavior for ZI_Travel alias Travelpersistent table ztravellock masterauthorization master ( instance )etag master LastChangedAt{ create; update; delete;}Draft Szenario
managed implementation in class zbp_i_travel unique;strict ( 2 );with draft;
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance )etag master LastChangedAt{ create; update; delete;
draft action Edit; draft action Activate optimized; draft action Discard; draft action Resume; draft determine action Prepare;}Exclusive vs. Shared Locks
RAP unterstützt zwei Lock-Modi für Draft-Szenarien:
| Lock-Typ | Beschreibung | Anwendungsfall |
|---|---|---|
| Exclusive | Nur ein Benutzer kann das Objekt bearbeiten | Standard für kritische Daten |
| Shared | Mehrere Benutzer können Drafts erstellen | Kollaborative Szenarien |
Exclusive Lock (Standard)
Mit Exclusive Lock kann nur ein Benutzer gleichzeitig ein Business Object bearbeiten:
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance ){ // Exclusive Lock ist der Standard // Nur ein Draft pro Instanz erlaubt}Shared Lock
Mit Shared Lock können mehrere Benutzer unabhängige Drafts erstellen:
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance )late numbering{ // Shared Draft: Mehrere Benutzer können // verschiedene Versionen bearbeiten with unmanaged save;}Draft-fähige CDS Views erstellen
Um Draft Handling zu nutzen, müssen Ihre CDS Views bestimmte Voraussetzungen erfüllen. Die wichtigste Anforderung ist ein Total ETag Feld, das Änderungen an der gesamten Entität nachverfolgt.
Interface View mit Draft-Unterstützung
@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Travel - Interface View'define root view entity ZI_Travel as select from ztravel
association [0..*] to ZI_Booking as _Booking on $projection.TravelUUID = _Booking.TravelUUID{ key travel_uuid as TravelUUID, travel_id as TravelId, agency_id as AgencyId, customer_id as CustomerId, begin_date as BeginDate, end_date as EndDate, @Semantics.amount.currencyCode: 'CurrencyCode' total_price as TotalPrice, currency_code as CurrencyCode, description as Description, overall_status as OverallStatus,
// Administrative Felder @Semantics.user.createdBy: true created_by as CreatedBy, @Semantics.systemDateTime.createdAt: true created_at as CreatedAt, @Semantics.user.lastChangedBy: true last_changed_by as LastChangedBy, @Semantics.systemDateTime.lastChangedAt: true last_changed_at as LastChangedAt,
// Wichtig für Draft: Total ETag für Concurrency Control @Semantics.systemDateTime.localInstanceLastChangedAt: true local_last_changed_at as LocalLastChangedAt,
// Associations _Booking}Das Feld LocalLastChangedAt mit der Annotation @Semantics.systemDateTime.localInstanceLastChangedAt wird als Total ETag verwendet. Es ermöglicht dem RAP-Framework, Konflikte bei gleichzeitigen Zugriffen zu erkennen.
Projection View für Draft
Die Projection View muss die Draft-relevanten Felder exponieren:
@AccessControl.authorizationCheck: #NOT_REQUIRED@EndUserText.label: 'Travel - Projection View'@Metadata.allowExtensions: truedefine root view entity ZC_Travel provider contract transactional_query as projection on ZI_Travel{ key TravelUUID, TravelId, AgencyId, CustomerId, BeginDate, EndDate, TotalPrice, CurrencyCode, Description, OverallStatus, CreatedBy, CreatedAt, LastChangedBy, LastChangedAt, LocalLastChangedAt,
_Booking : redirected to composition child ZC_Booking}Draft Table Definition
Für jede Entität mit Draft-Unterstützung benötigen Sie eine separate Draft-Tabelle. Diese Tabelle speichert die temporären Arbeitskopien und muss die gleiche Struktur wie die Haupttabelle haben, ergänzt um Draft-spezifische Verwaltungsfelder:
@EndUserText.label : 'Travel Draft'@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE@AbapCatalog.tableCategory : #TRANSPARENTdefine table zdraft_travel { key client : abap.clnt not null; key travel_uuid : sysuuid_x16 not null; // Draft-UUID travel_id : abap.numc(8); agency_id : abap.numc(6); customer_id : abap.numc(6); begin_date : abap.dats; end_date : abap.dats; total_price : abap.curr(16,2); currency_code : abap.cuky; description : abap.string(256); status : abap.char(1);
// Draft-spezifische Felder (automatisch vom Framework genutzt) "%admin" : include sych_bdl_draft_admin_inc;}Draft-Admin Include
Das Include sych_bdl_draft_admin_inc enthält wichtige Verwaltungsfelder:
| Feld | Beschreibung |
|---|---|
draftentityuuid | Eindeutige Draft-ID |
draftentitycreationdatetime | Erstellungszeitpunkt |
draftentitylastchangedatetime | Letzte Änderung |
draftentitycreatedby | Erstellt von |
draftentitylastchangedby | Geändert von |
draftentityownershipstate | Draft-Besitz |
hasactiveentity | Hat aktive Version |
isactiveentity | Ist aktive Version |
Draft Actions
RAP stellt automatisch Draft Actions bereit:
Edit Action
Startet den Bearbeitungsmodus und erstellt einen Draft:
" In der Behavior Definitiondraft action Edit;
" EML-AufrufMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Edit FROM VALUE #( ( TravelId = '00000001' ) ) MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported).Activate Action
Aktiviert den Draft und schreibt die Änderungen in die Datenbank:
" In der Behavior Definitiondraft action Activate optimized;
" EML-AufrufMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Activate FROM VALUE #( ( %key-TravelId = '00000001' ) ) MAPPED mapped FAILED failed REPORTED reported.
COMMIT ENTITIES.Der Zusatz optimized sorgt dafür, dass nur geänderte Felder geschrieben werden.
Discard Action
Verwirft den Draft ohne Speicherung:
" In der Behavior Definitiondraft action Discard;
" EML-AufrufMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Discard FROM VALUE #( ( %key-TravelId = '00000001' ) ) FAILED failed REPORTED reported.Resume Action
Setzt die Bearbeitung eines vorhandenen Drafts fort:
" In der Behavior Definitiondraft action Resume;
" EML-AufrufMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Resume FROM VALUE #( ( %key-TravelId = '00000001' ) ) RESULT DATA(result) FAILED failed REPORTED reported.Prepare Action
Führt Validierungen aus, ohne zu aktivieren:
" In der Behavior Definitiondraft determine action Prepare { validation validateDates; validation validateCustomer;}
" EML-Aufruf - prüft alle Draft-ValidierungenMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Prepare FROM VALUE #( ( %key-TravelId = '00000001' ) ) FAILED failed REPORTED reported.Vollständiges Draft-Beispiel
1. Behavior Definition
managed implementation in class zbp_i_travel unique;strict ( 2 );with draft;
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance )etag master LastChangedAt{ // Standard-Operationen create; update; delete;
// Feldmapping field ( readonly ) TravelId; field ( readonly ) CreatedBy, CreatedAt, LastChangedBy, LastChangedAt; field ( numbering : managed ) TravelId;
// Actions action ( features : instance ) acceptTravel result [1] $self; action ( features : instance ) rejectTravel result [1] $self;
// Validations - werden bei Prepare/Activate ausgeführt validation validateDates on save { field BeginDate, EndDate; } validation validateCustomer on save { field CustomerId; }
// Determinations determination setStatusNew on modify { create; }
// Draft Actions draft action Edit; draft action Activate optimized; draft action Discard; draft action Resume; draft determine action Prepare { validation validateDates; validation validateCustomer; }}2. Projection mit Draft
projection;strict ( 2 );use draft;
define behavior for ZC_Travel alias Travel{ use create; use update; use delete;
use action acceptTravel; use action rejectTravel;
use action Edit; use action Activate; use action Discard; use action Resume; use action Prepare;}3. Draft-Validierung implementieren
CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler. PRIVATE SECTION. METHODS validateDates FOR VALIDATE ON SAVE IMPORTING keys FOR Travel~validateDates.ENDCLASS.
CLASS lhc_travel IMPLEMENTATION. METHOD validateDates. " Draft-Daten lesen (nicht aktive Daten!) READ ENTITIES OF zi_travel IN LOCAL MODE ENTITY Travel FIELDS ( BeginDate EndDate ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_travel).
LOOP AT lt_travel INTO DATA(ls_travel). " Draft-Validierung: Warnung statt Fehler möglich IF ls_travel-EndDate < ls_travel-BeginDate. APPEND VALUE #( %tky = ls_travel-%tky %element-EndDate = if_abap_behv=>mk-on ) TO failed-travel.
APPEND VALUE #( %tky = ls_travel-%tky %state_area = 'VALIDATE_DATES' %element-EndDate = if_abap_behv=>mk-on %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = 'Enddatum muss nach Beginndatum liegen' ) ) TO reported-travel. ENDIF. ENDLOOP. ENDMETHOD.ENDCLASS.Draft in Fiori Elements
Wenn Draft aktiviert ist, zeigt Fiori Elements automatisch:
- Auto-Save: Änderungen werden automatisch gespeichert
- Draft Indicator: Zeigt an, dass ungespeicherte Änderungen existieren
- Discard-Button: Verwirft alle Änderungen
- Save-Button: Aktiviert den Draft (führt Validierungen aus)
Concurrent Access und Locking im Detail
Das RAP-Framework verwaltet Locks automatisch, um Datenkonsistenz sicherzustellen. Beim Draft Handling gibt es zwei kritische Szenarien:
Szenario 1: Zwei Benutzer bearbeiten dieselbe Instanz
Mit Exclusive Lock (Standard):
- Benutzer A startet Edit → Draft wird erstellt, Lock wird gesetzt
- Benutzer B versucht Edit → Fehlermeldung “Objekt wird von Benutzer A bearbeitet”
- Benutzer A aktiviert oder verwirft → Lock wird freigegeben
- Benutzer B kann nun bearbeiten
Szenario 2: Draft-Timeout
Wenn ein Benutzer einen Draft erstellt und die Session verlässt:
- Der Draft bleibt in der Draft-Tabelle
- Bei erneutem Zugriff kann mit Resume fortgesetzt werden
- Andere Benutzer sind weiterhin blockiert (bei Exclusive Lock)
Um verwaiste Drafts zu vermeiden, können Sie einen Background-Job einrichten, der alte Drafts automatisch löscht:
" Beispiel: Drafts älter als 7 Tage löschenDELETE FROM zdraft_travel WHERE draftentitylastchangedatetime < @lv_cutoff_timestamp.Best Practices
- Draft nur wenn nötig - Bei einfachen CRUD-Apps ohne komplexe Formulare ist Draft oft unnötig und erhöht die Komplexität
- Validierungen in Prepare - Ermöglicht frühe Rückmeldung ohne Aktivierung, verbessert die Benutzererfahrung
- Draft Table korrekt definieren - Immer das Admin-Include
sych_bdl_draft_admin_incverwenden - Optimized Activate - Der Zusatz
optimizedbei Activate verbessert die Performance, da nur geänderte Felder geschrieben werden - State Areas nutzen - Gruppieren Sie Validierungsmeldungen für bessere UX mit
%state_area - Draft Timeout einrichten - Konfigurieren Sie einen Background-Job zum automatischen Löschen alter Drafts
- Testing nicht vergessen - Testen Sie alle Draft-Szenarien: Edit, Activate, Discard, Resume und Concurrent Access
Zusammenfassung
Draft Handling ist ein mächtiges Feature des RESTful ABAP Programming Models, das die Benutzererfahrung bei komplexen Datenerfassungsszenarien erheblich verbessert. Die wichtigsten Punkte:
- Draft vs. Active: Drafts sind temporäre Arbeitskopien, die erst bei Aktivierung zu persistenten Daten werden
- Draft Table: Eine separate Tabelle speichert die Draft-Instanzen mit dem Admin-Include für Verwaltungsfelder
- Draft Actions: Edit, Activate, Discard, Resume und Prepare ermöglichen den kompletten Draft-Workflow
- Locking: Exclusive Lock verhindert gleichzeitige Bearbeitung, Shared Lock ermöglicht kollaborative Szenarien
- Validierungen: Mit Prepare können Validierungen ausgeführt werden, ohne den Draft zu aktivieren
Mit dem richtigen Einsatz von Draft Handling erstellen Sie professionelle Fiori-Anwendungen, die auch bei komplexen Eingabeszenarien eine optimale User Experience bieten.
Weiterführende Themen
- RAP Grundlagen - Einführung in das RESTful ABAP Programming Model
- RAP Actions und Functions - Geschäftslogik implementieren
- Feature Control & Side Effects - Dynamische UI-Steuerung
- RAP Determinations und Validations - Automatische Feldberechnungen und Prüfungen
- RAP Tutorial Teil 1 - Schritt-für-Schritt zur ersten RAP-Anwendung