Le Draft Handling permet aux utilisateurs de sauvegarder les modifications sur les Business Objects de maniere intermediaire, sans les ecrire immediatement dans la base de donnees. C’est particulierement important pour les formulaires de saisie complexes dans les applications Fiori. Avec le Draft Handling, les utilisateurs peuvent interrompre leur travail, le reprendre plus tard et activer les modifications seulement lorsque toutes les saisies sont completes et validees.
Dans cet article, vous apprendrez comment fonctionne le Draft Handling dans RAP, comment creer des CDS Views et Behavior Definitions compatibles Draft, et quelles Draft Actions sont disponibles pour les workflows typiques.
Le concept Draft : Instances Actives vs. Draft
Le concept central du Draft Handling est la distinction entre les instances actives et les instances Draft :
-
Instances actives (Active Entities) : Les donnees persistantes dans la table de base de donnees. Elles representent l’etat actuel et valide du Business Object et sont visibles par tous les utilisateurs.
-
Instances Draft (Draft Entities) : Copies de travail temporaires, stockees dans une table Draft separee. Un Draft est visible uniquement par l’utilisateur qui l’edite et contient des modifications non encore validees ou incompletes.
Le cycle de vie d’un Draft ressemble typiquement a ceci :
- Edit : L’utilisateur commence l’edition → Le systeme cree une copie Draft
- Modify : L’utilisateur modifie les donnees → Les modifications sont automatiquement sauvegardees dans le Draft
- Prepare : Le systeme execute les validations → Les erreurs sont affichees, mais le Draft est conserve
- Activate : L’utilisateur active → Le Draft devient l’instance active, l’entree Draft est supprimee
Alternativement, l’utilisateur peut a tout moment choisir Discard pour rejeter le Draft sans modifier l’instance active.
Quand ai-je besoin du Draft ?
Le Draft Handling est judicieux pour :
- Masques de saisie complexes avec de nombreux champs
- Workflows multi-etapes ou les utilisateurs souhaitent sauvegarder de maniere intermediaire
- Transactions de longue duree qui ne sont pas terminees en une seule session
- Validations qui ne doivent etre executees qu’a l’activation
Scenarios Draft vs. Non-Draft
| Aspect | Draft | Non-Draft |
|---|---|---|
| Stockage | Table Draft separee | Directement dans la table de base de donnees |
| Sauvegarde intermediaire | Oui, automatique | Non |
| Validation | Lors de Prepare/Activate | A chaque Save |
| Complexite | Plus elevee | Plus faible |
| UX Fiori | Amelioree (Auto-Save) | Standard |
| Cas d’usage | Formulaires complexes | Applications CRUD simples |
Scenario Non-Draft (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;}Scenario Draft
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 supporte deux modes de verrou pour les scenarios Draft :
| Type de Lock | Description | Cas d’usage |
|---|---|---|
| Exclusive | Un seul utilisateur peut editer l’objet | Standard pour les donnees critiques |
| Shared | Plusieurs utilisateurs peuvent creer des Drafts | Scenarios collaboratifs |
Exclusive Lock (Standard)
Avec Exclusive Lock, un seul utilisateur peut editer un Business Object a la fois :
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance ){ // Exclusive Lock est la valeur par defaut // Un seul Draft par instance autorise}Shared Lock
Avec Shared Lock, plusieurs utilisateurs peuvent creer des Drafts independants :
define behavior for ZI_Travel alias Travelpersistent table ztraveldraft table zdraft_travellock master total etag LastChangedAtauthorization master ( instance )late numbering{ // Shared Draft : Plusieurs utilisateurs peuvent // editer differentes versions with unmanaged save;}Creer des CDS Views compatibles Draft
Pour utiliser le Draft Handling, vos CDS Views doivent remplir certaines conditions. L’exigence la plus importante est un champ Total ETag qui suit les modifications sur l’entite entiere.
Interface View avec support Draft
@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,
// Champs administratifs @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,
// Important pour Draft : Total ETag pour le controle de concurrence @Semantics.systemDateTime.localInstanceLastChangedAt: true local_last_changed_at as LocalLastChangedAt,
// Associations _Booking}Le champ LocalLastChangedAt avec l’annotation @Semantics.systemDateTime.localInstanceLastChangedAt est utilise comme Total ETag. Il permet au framework RAP de detecter les conflits lors d’acces simultanees.
Projection View pour Draft
La Projection View doit exposer les champs pertinents pour le Draft :
@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}Definition de la Draft Table
Pour chaque entite avec support Draft, vous avez besoin d’une table Draft separee. Cette table stocke les copies de travail temporaires et doit avoir la meme structure que la table principale, completee par des champs d’administration specifiques au Draft :
@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);
// Champs specifiques au Draft (utilises automatiquement par le framework) "%admin" : include sych_bdl_draft_admin_inc;}Draft-Admin Include
L’include sych_bdl_draft_admin_inc contient des champs d’administration importants :
| Champ | Description |
|---|---|
draftentityuuid | ID Draft unique |
draftentitycreationdatetime | Moment de creation |
draftentitylastchangedatetime | Derniere modification |
draftentitycreatedby | Cree par |
draftentitylastchangedby | Modifie par |
draftentityownershipstate | Propriete du Draft |
hasactiveentity | A une version active |
isactiveentity | Est une version active |
Draft Actions
RAP fournit automatiquement des Draft Actions :
Action Edit
Demarre le mode edition et cree un Draft :
" Dans la Behavior Definitiondraft action Edit;
" Appel EMLMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Edit FROM VALUE #( ( TravelId = '00000001' ) ) MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported).Action Activate
Active le Draft et ecrit les modifications dans la base de donnees :
" Dans la Behavior Definitiondraft action Activate optimized;
" Appel EMLMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Activate FROM VALUE #( ( %key-TravelId = '00000001' ) ) MAPPED mapped FAILED failed REPORTED reported.
COMMIT ENTITIES.L’ajout optimized fait en sorte que seuls les champs modifies soient ecrits.
Action Discard
Rejette le Draft sans sauvegarde :
" Dans la Behavior Definitiondraft action Discard;
" Appel EMLMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Discard FROM VALUE #( ( %key-TravelId = '00000001' ) ) FAILED failed REPORTED reported.Action Resume
Reprend l’edition d’un Draft existant :
" Dans la Behavior Definitiondraft action Resume;
" Appel EMLMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Resume FROM VALUE #( ( %key-TravelId = '00000001' ) ) RESULT DATA(result) FAILED failed REPORTED reported.Action Prepare
Execute les validations sans activer :
" Dans la Behavior Definitiondraft determine action Prepare { validation validateDates; validation validateCustomer;}
" Appel EML - verifie toutes les validations DraftMODIFY ENTITIES OF zi_travel ENTITY Travel EXECUTE Prepare FROM VALUE #( ( %key-TravelId = '00000001' ) ) FAILED failed REPORTED reported.Exemple Draft complet
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{ // Operations standard create; update; delete;
// Mapping des champs 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 - executees lors de Prepare/Activate 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 avec 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. Implementer la validation Draft
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. " Lire les donnees Draft (pas les donnees actives!) 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). " Validation Draft : Warning au lieu d'erreur possible 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 = 'La date de fin doit etre apres la date de debut" ) ) TO reported-travel. ENDIF. ENDLOOP. ENDMETHOD.ENDCLASS.Draft dans Fiori Elements
Lorsque le Draft est active, Fiori Elements affiche automatiquement :
- Auto-Save : Les modifications sont sauvegardees automatiquement
- Draft Indicator : Indique qu’il existe des modifications non sauvegardees
- Bouton Discard : Rejette toutes les modifications
- Bouton Save : Active le Draft (execute les validations)
Acces concurrent et Locking en detail
Le framework RAP gere automatiquement les verrous pour assurer la coherence des donnees. Avec le Draft Handling, il y a deux scenarios critiques :
Scenario 1 : Deux utilisateurs editent la meme instance
Avec Exclusive Lock (par defaut) :
- L’utilisateur A demarre l’edition → Le Draft est cree, le verrou est pose
- L’utilisateur B essaie d’editer → Message d’erreur “L’objet est en cours d’edition par l’utilisateur A”
- L’utilisateur A active ou rejette → Le verrou est libere
- L’utilisateur B peut maintenant editer
Scenario 2 : Timeout du Draft
Lorsqu’un utilisateur cree un Draft et quitte la session :
- Le Draft reste dans la table Draft
- Lors d’un nouvel acces, il peut reprendre avec Resume
- Les autres utilisateurs restent bloques (avec Exclusive Lock)
Pour eviter les Drafts orphelins, vous pouvez mettre en place un job en arriere-plan qui supprime automatiquement les anciens Drafts :
" Exemple : Supprimer les Drafts de plus de 7 joursDELETE FROM zdraft_travel WHERE draftentitylastchangedatetime < @lv_cutoff_timestamp.Bonnes pratiques
- Draft seulement si necessaire - Pour les applications CRUD simples sans formulaires complexes, le Draft est souvent inutile et augmente la complexite
- Validations dans Prepare - Permet un retour precoce sans activation, ameliore l’experience utilisateur
- Definir correctement la Draft Table - Toujours utiliser l’include Admin
sych_bdl_draft_admin_inc - Activate optimized - L’ajout
optimizedlors de Activate ameliore la performance car seuls les champs modifies sont ecrits - Utiliser les State Areas - Groupez les messages de validation pour une meilleure UX avec
%state_area - Configurer le Draft Timeout - Configurez un job en arriere-plan pour la suppression automatique des anciens Drafts
- Ne pas oublier les tests - Testez tous les scenarios Draft : Edit, Activate, Discard, Resume et Acces concurrent
Resume
Le Draft Handling est une fonctionnalite puissante du RESTful ABAP Programming Model qui ameliore considerablement l’experience utilisateur dans les scenarios de saisie de donnees complexes. Les points cles :
- Draft vs. Active : Les Drafts sont des copies de travail temporaires qui ne deviennent des donnees persistantes qu’a l’activation
- Draft Table : Une table separee stocke les instances Draft avec l’include Admin pour les champs d’administration
- Draft Actions : Edit, Activate, Discard, Resume et Prepare permettent le workflow Draft complet
- Locking : Exclusive Lock empeche l’edition simultanee, Shared Lock permet les scenarios collaboratifs
- Validations : Avec Prepare, les validations peuvent etre executees sans activer le Draft
Avec la bonne utilisation du Draft Handling, vous creez des applications Fiori professionnelles qui offrent une experience utilisateur optimale meme dans les scenarios de saisie complexes.
Sujets connexes
- Fondamentaux RAP - Introduction au RESTful ABAP Programming Model
- RAP Actions et Functions - Implementer la logique metier
- Feature Control & Side Effects - Controle dynamique de l’UI
- RAP Determinations et Validations - Calculs automatiques et verifications
- Tutoriel RAP Partie 1 - Etape par etape vers votre premiere application RAP