Draft Handling permite a los usuarios guardar cambios en Business Objects de forma intermedia, sin escribirlos inmediatamente en la base de datos. Esto es especialmente importante para formularios de entrada complejos en aplicaciones Fiori. Con Draft Handling, los usuarios pueden interrumpir su trabajo, continuar en un momento posterior y solo entonces activar los cambios cuando todas las entradas estén completas y validadas.
En este articulo aprenderas como funciona Draft Handling en RAP, como crear CDS Views y Behavior Definitions habilitadas para draft, y que Draft Actions estan disponibles para workflows tipicos.
El Concepto Draft: Instancias Active vs. Draft
El concepto central en Draft Handling es la distincion entre instancias activas e instancias draft:
-
Instancias Activas (Active Entities): Los datos persistentes en la tabla de base de datos. Representan el estado actual y valido del Business Object y son visibles para todos los usuarios.
-
Instancias Draft (Draft Entities): Copias de trabajo temporales que se almacenan en una tabla Draft separada. Un Draft solo es visible para el usuario que lo edita y contiene cambios aun no validados o incompletos.
El ciclo de vida de un Draft tipicamente se ve asi:
- Edit: El usuario inicia la edicion -> El sistema crea una copia Draft
- Modify: El usuario cambia datos -> Los cambios se guardan automaticamente en el Draft
- Prepare: El sistema ejecuta validaciones -> Los errores se muestran, pero el Draft permanece
- Activate: El usuario activa -> El Draft se convierte en instancia activa, la entrada Draft se elimina
Alternativamente, el usuario puede elegir Discard en cualquier momento para descartar el Draft sin modificar la instancia activa.
¿Cuando necesito Draft?
Draft Handling es util para:
- Formularios de entrada complejos con muchos campos
- Workflows de multiples pasos, donde los usuarios quieren guardar de forma intermedia
- Transacciones de larga duracion, que no se completan en una sesion
- Validaciones, que solo deben ejecutarse en la activacion
Draft vs. Non-Draft Escenarios
| Aspecto | Draft | Non-Draft |
|---|---|---|
| Almacenamiento | Tabla Draft separada | Directamente en tabla de base de datos |
| Guardar intermedio | Si, automaticamente | No |
| Validacion | En Prepare/Activate | En cada Save |
| Complejidad | Mayor | Menor |
| Fiori-UX | Mejorada (Auto-Save) | Estandar |
| Caso de uso | Formularios complejos | Apps CRUD simples |
Escenario Non-Draft (Estandar)
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;}Escenario 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 soporta dos modos de Lock para escenarios Draft:
| Tipo de Lock | Descripcion | Caso de uso |
|---|---|---|
| Exclusive | Solo un usuario puede editar el objeto | Estandar para datos criticos |
| Shared | Multiples usuarios pueden crear Drafts | Escenarios colaborativos |
Exclusive Lock (Estandar)
Con Exclusive Lock solo un usuario puede editar un Business Object simultaneamente:
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
Con Shared Lock multiples usuarios pueden crear Drafts independientes:
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;}Crear CDS Views habilitadas para Draft
Para usar Draft Handling, sus CDS Views deben cumplir ciertos requisitos. El requisito mas importante es un campo Total ETag que rastrea los cambios en toda la entidad.
Interface View con soporte 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,
// 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}El campo LocalLastChangedAt con la anotacion @Semantics.systemDateTime.localInstanceLastChangedAt se usa como Total ETag. Permite al framework RAP detectar conflictos en accesos concurrentes.
Projection View para Draft
La Projection View debe exponer los campos relevantes para 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}Definicion de Draft Table
Para cada entidad con soporte Draft necesita una tabla Draft separada. Esta tabla almacena las copias de trabajo temporales y debe tener la misma estructura que la tabla principal, complementada con campos de administracion especificos de 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);
// Draft-spezifische Felder (automatisch vom Framework genutzt) "%admin" : include sych_bdl_draft_admin_inc;}Draft-Admin Include
El Include sych_bdl_draft_admin_inc contiene campos de administracion importantes:
| Campo | Descripcion |
|---|---|
draftentityuuid | ID Draft unico |
draftentitycreationdatetime | Momento de creacion |
draftentitylastchangedatetime | Ultimo cambio |
draftentitycreatedby | Creado por |
draftentitylastchangedby | Cambiado por |
draftentityownershipstate | Propiedad del Draft |
hasactiveentity | Tiene version activa |
isactiveentity | Es version activa |
Draft Actions
RAP proporciona Draft Actions automaticamente:
Edit Action
Inicia el modo de edicion y crea un 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
Activa el Draft y escribe los cambios en la base de datos:
" 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.El sufijo optimized asegura que solo se escriban los campos modificados.
Discard Action
Descarta el Draft sin guardar:
" 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
Continua la edicion de un Draft existente:
" 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
Ejecuta validaciones sin activar:
" 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.Ejemplo Completo de Draft
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 con 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. Implementar Draft-Validation
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 en Fiori Elements
Cuando Draft esta activado, Fiori Elements muestra automaticamente:
- Auto-Save: Los cambios se guardan automaticamente
- Draft Indicator: Indica que existen cambios sin guardar
- Boton Discard: Descarta todos los cambios
- Boton Save: Activa el Draft (ejecuta validaciones)
Concurrent Access y Locking en Detalle
El framework RAP gestiona Locks automaticamente para asegurar la consistencia de datos. En Draft Handling hay dos escenarios criticos:
Escenario 1: Dos usuarios editan la misma instancia
Con Exclusive Lock (Estandar):
- Usuario A inicia Edit -> Se crea Draft, se establece Lock
- Usuario B intenta Edit -> Mensaje de error “El objeto esta siendo editado por Usuario A”
- Usuario A activa o descarta -> Se libera Lock
- Usuario B ahora puede editar
Escenario 2: Draft-Timeout
Cuando un usuario crea un Draft y abandona la sesion:
- El Draft permanece en la tabla Draft
- Al acceder de nuevo puede continuar con Resume
- Otros usuarios siguen bloqueados (con Exclusive Lock)
Para evitar Drafts huerfanos, puede configurar un Background-Job que elimine automaticamente Drafts antiguos:
" Beispiel: Drafts älter als 7 Tage löschenDELETE FROM zdraft_travel WHERE draftentitylastchangedatetime < @lv_cutoff_timestamp.Mejores Practicas
- Draft solo cuando sea necesario - Para apps CRUD simples sin formularios complejos, Draft a menudo es innecesario y aumenta la complejidad
- Validaciones en Prepare - Permite retroalimentacion temprana sin activacion, mejora la experiencia del usuario
- Definir Draft Table correctamente - Usar siempre el Admin-Include
sych_bdl_draft_admin_inc - Optimized Activate - El sufijo
optimizeden Activate mejora el rendimiento, ya que solo se escriben los campos modificados - Usar State Areas - Agrupe mensajes de validacion para mejor UX con
%state_area - Configurar Draft Timeout - Configure un Background-Job para eliminar automaticamente Drafts antiguos
- No olvidar Testing - Pruebe todos los escenarios Draft: Edit, Activate, Discard, Resume y Concurrent Access
Resumen
Draft Handling es una caracteristica potente del RESTful ABAP Programming Model que mejora significativamente la experiencia del usuario en escenarios complejos de captura de datos. Los puntos mas importantes:
- Draft vs. Active: Los Drafts son copias de trabajo temporales que solo se convierten en datos persistentes en la activacion
- Draft Table: Una tabla separada almacena las instancias Draft con el Admin-Include para campos de administracion
- Draft Actions: Edit, Activate, Discard, Resume y Prepare permiten el workflow Draft completo
- Locking: Exclusive Lock previene la edicion simultanea, Shared Lock permite escenarios colaborativos
- Validaciones: Con Prepare se pueden ejecutar validaciones sin activar el Draft
Con el uso correcto de Draft Handling crea aplicaciones Fiori profesionales que ofrecen una experiencia de usuario optima incluso en escenarios de entrada complejos.
Temas Relacionados
- Fundamentos de RAP - Introduccion al RESTful ABAP Programming Model
- RAP Actions y Functions - Implementar logica de negocio
- Feature Control & Side Effects - Control dinamico de UI
- RAP Determinations y Validations - Calculos automaticos de campos y validaciones
- RAP Tutorial Parte 1 - Paso a paso hacia su primera aplicacion RAP