This is a test message to test the length of the message box.
Created by Software-Heroes

RAP - Draft


In this article you will learn more about draft handling within a business object and how to implement it on an existing object.

What actually happens when a user stops working on the app and calls up the app again on another device? That's right, nothing of his current working status is available anymore. Today we want to show you how you can change this situation and give the user the opportunity to continue working on their second device without losing their entries.



What is draft handling? This is a technique to save the current status in the backend in a kind of shadow table for the user after each step. The data is not initially in the table with the real data, it is a working status of the changes. To do this, you have to create the shadow table and expand the RAP business object in a few places.



However, before we can get started with the change in the RAP, we need to create a prerequisite. A unique time stamp is required that describes the status of the last change, the so-called ETAG field. This must be present in every data table so that the system knows whether a data record has changed in the meantime. To do this, we add a new field to the partner table ZBS_DMO_PARTNER:

@EndUserText.label : 'Partner Data'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zbs_dmo_partner {
  key client       : abap.clnt not null;
  key partner      : abap.char(10) not null;
  name             : abap.char(60);
  street           : abap.char(80);
  city             : abap.char(60);
  country          : land1;
  payment_currency : abap.cuky;
  last_changed_at  : timestampl;


At the end we add a new field "last_changed_at" with type "timestampl". This field will contain the information of the last change. After activating the table, we still have to extend the view stack of the RAP object and accept the field. The interface view now looks like this:

define root view entity ZBS_I_RAPPartner
  as select from zbs_dmo_partner

  key partner          as PartnerNumber,
      name             as PartnerName,
      street           as Street,
      city             as City,
      country          as Country,
      payment_currency as PaymentCurrency,
      last_changed_at  as LastChangedAt


First of all, we don't transfer it to the Consumption View because we don't want to output it, we only need the information for processing.


Behavior definition

In the next step, we can now tackle the actual expansion of the business object. To do this, we add the addition "with draft" to the behavior definition to activate draft handling. The further steps are now explained in the subsections.

with draft;


Draft table

Next, the draft table must be specified under the table of data. The system will issue a corresponding error message since the table does not yet exist. You can then use CTRL + 1 to create the table automatically.


The table has now been defined by the system as follows:

@EndUserText.label : 'Draft table for entity ZBS_I_RAPPARTNER'
@AbapCatalog.enhancement.category : #EXTENSIBLE_ANY
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zbs_dmo_dpartner {
  key mandt         : mandt not null;
  key partnernumber : abap.char(10) not null;
  key draftuuid     : sdraft_uuid not null;
  partnername       : abap.char(60);
  street            : abap.char(80);
  city              : abap.char(60);
  country           : land1;
  paymentcurrency   : abap.cuky;
  lastchangedat     : timestampl;
  "%admin"          : include sych_bdl_draft_admin_inc;


The names of the fields correspond to the fields of the interface view. An additional element is added to the key and some administrative data is defined at the end of the table. The names of the fields should not be changed and should always correspond to the CDS views.


ETAG field

The new field must now be included in the mapping at the end of the behavior definition, and the "lock master" must be supplemented with the field, and a general ETAG must be defined as "master".

lock master total etag LastChangedAt
authorization master ( instance )
late numbering
etag master LastChangedAt



Another requirement is the implementation of the various draft actions provided by the framework. Validations that we have defined and that are executed before a draft is transferred to the productive table can be stored in the "Prepare" function.

draft action Resume;
draft action Edit;
draft action Activate;
draft action Discard;

draft determine action Prepare
  validation validateKeyIsFilled;
  validation validateCoreData;


New behavior definition

After all the adjustments, the new behavior definition now looks like this:

managed implementation in class zbp_bs_demo_rappartner unique;
with draft;

define behavior for ZBS_I_RAPPartner alias Partner
persistent table zbs_dmo_partner
draft table zbs_dmo_dpartner
lock master total etag LastChangedAt
authorization master ( instance )
late numbering
etag master LastChangedAt
  delete ( features : global );

  field ( readonly ) PartnerNumber;

  draft action Resume;
  draft action Edit;
  draft action Activate;
  draft action Discard;

  draft determine action Prepare
    validation validateKeyIsFilled;
    validation validateCoreData;

  validation validateKeyIsFilled on save { create; }
  validation validateCoreData on save { create; field Country, PaymentCurrency; }

  determination fillCurrency on modify { create; update; }

  static action withPopup parameter ZBS_I_PopupEntity;
  action ( features : instance ) fillEmptyStreets result [1] $self;
  static action clearAllEmptyStreets;
  factory action copyLine [1];

  mapping for zbs_dmo_partner
    PartnerNumber = partner;
    PartnerName = name;
    Street = street;
    City = city;
    Country = country;
    PaymentCurrency = payment_currency;
    LastChangedAt = last_changed_at;



So that the draft is also available via the app, it must also be given to the outside in the projection of the behavior definition. In addition, it is announced that Darft is used and the various actions are released. After adjustment, the projection now looks like this:

use draft;

define behavior for ZBS_C_RAPPartner alias Partner
  use create;
  use update;
  use delete;

  use action fillEmptyStreets;
  use action clearAllEmptyStreets;
  use action copyLine;
  use action withPopup;

  use action Edit;
  use action Activate;
  use action Discard;
  use action Prepare;
  use action Resume;



What has actually changed in the app and what is the point? As soon as we open the app, we notice that another option has been added to the filter bar:


This allows the different drafts to be selected or you can only filter the "real" data sets. This filter is automatically gifted to you with draft handling. In the next step we take a look at the detail screen of a data set:


It is noticeable that there are now a few more buttons that provide us with some additional functions:

  • Display Saved Version - Display of the original version of the dataset if changes have already been made.
  • Discard Draft - The draft is removed from the draft table and the original record is the leading and only record.


As soon as you make a change to a field and switch focus to another field, a draft is created in the database and the information is saved:


When you click on the "Save" button, the data record from the draft table will be adopted as the new active version. However, if you just want to go back, you'll be asked what you want to do now:


If we set the point "Keep Draft" then the intermediate status will continue to be saved and we will end up back on the overview screen. If we now set the filter accordingly to our own entries, then our changed data set will be displayed:



You now know how to activate and use the draft in the business object. Furthermore, you know which requirements a table must meet so that Draft can also be activated. The function is available in many standard apps and completes the user experience in the Fiori context.

Included topics:
RAPBTPDraftDraft Handling
Comments (0)

And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.

RAP - Deep Action in OData v4

Category - ABAP

In this article we will look at actions with deep structures, how we can create them and pass data to an API endpoint.


BTP - Connect On-Premise (Consumption Model v2)

Category - ABAP

In this article we want to provide another update on the connection of on-premise systems and how this is done with a communication arrangement.


RAP - Show app count (Tile)

Category - ABAP

This example is about displaying a counter on the tile of a Fiori Elements application and how such a thing can be implemented.


RAP - Generator (Fiori)

Category - ABAP

In this article we will look at the more complex RAP generator as a Fiori Elements application and what advantages you have with it.


RAP - Generator (ADT)

Category - ABAP

Today, let's take a look at the RAP Generator, which is already integrated into ABAP Development Tools, and how you can use it to easily build new RAP apps.