Introduction
In SAP ABAP RESTful Application Programming Model (RAP), the concepts of Create and Create by Association are fundamental for managing data persistence in business objects.
Implementing numbering mechanisms during these operations is essential to ensure unique identifiers for newly created entities.
This blog explores strategies and best practices for numbering during the Create operation and Create by Association, highlighting how RAP supports these processes in both managed and unmanaged scenarios.
Basic Information About Numbering
Numbering in RAP refers to the process of assigning unique values to the key fields of business entities during Create operations.
Types of Numbering
Early Numbering:Primary key values are assigned immediately when a creation operation is initiated. This mechanism is triggered during the interaction phase. Types: Managed Early Numbering: The RAP framework automatically assigns a UUID (Universal Unique Identifier) to the key field during the create request. Applicable for key fields of type RAW (16) in managed scenarios. Unmanaged Early Numbering: Developers implement custom logic to assign key values during the creation operation. Use Cases: Suitable for scenarios requiring immediate key assignment, such as generating unique identifiers for new records upon clicking “Create.” Late Numbering:Primary key values are assigned just before the data is saved to the database. Triggered during the save sequence phase.
Implementation:
Developers implement the ADJUST_NUMBERS method to handle late numbering. This method is invoked during the save sequence to assign key values.
Scenario Example
In this example, we have designed a scenario with two views:
Hospital View (Root entity) Patient View (Child entity, dependent on Hospital View)
The Hospital View is the root entity, and the Patient View is related to it via a composition relationship. The patient data cannot exist independently of the hospital data.
Below are the CDS view definitions and behavior implementations for the scenario:
Hospital View
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Hospital interface view’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity zismo_i_hospital
as select from zismo_dt_hosp
composition [1..*] of zismo_i_patient as _patient
{
@UI.facet: [{
label: ‘Hospital information’,
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
position: 10
},
{ label : ‘Patient information’,
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
position: 20,
targetElement: ‘_patient’ } ]
@UI.lineItem: [{ position: 10, label: ‘Hospital Id’ }]
@UI.identification: [{ position: 10, label: ‘Hospital Id’ }]
key hospital_id as HospitalId,
@UI.lineItem: [{ position: 20, label: ‘Hospital name’ }]
@UI.identification: [{ position: 20, label: ‘Hospital name’ }]
hospital_name as HospitalName,
@UI.lineItem: [{ position: 30, label: ‘Hospital location’ }]
@UI.identification: [{ position: 30, label: ‘Hospital location’ }]
hospital_location as HospitalLocation,
@UI.lineItem: [{ position: 40, label: ‘No of doctors’ }]
@UI.identification: [{ position: 40, label: ‘No of doctors’ }]
no_of_doctors as NoOfDoctors,
@UI.lineItem: [{ position: 50, label: ‘No of rooms’ }]
@UI.identification: [{ position: 50, label: ‘No of rooms’ }]
no_of_rooms as NoOfRooms,
_patient
}
Patient View
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Patient interface view’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity zismo_i_patient
as select from zismo_dt_patient
association to parent zismo_i_hospital as _hospital on $projection.HospitalId = _hospital.HospitalId
{
@UI.facet: [{
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
position: 10
}]
@UI.lineItem: [{ position: 10, label: ‘Hospital Id’ }]
@UI.identification: [{ position: 10, label: ‘Hospital Id’ }]
key hospital_id as HospitalId,
@UI.lineItem: [{ position: 20, label: ‘Patient Id’ }]
@UI.identification: [{ position: 20, label: ‘Patient Id’ }]
key patient_id as PatientId,
@UI.lineItem: [{ position: 30, label: ‘Patient name’ }]
@UI.identification: [{ position: 30, label: ‘Patient name’ }]
patient_name as PatientName,
@UI.lineItem: [{ position: 40, label: ‘Medical cause’ }]
@UI.identification: [{ position: 40, label: ‘Medical cause’ }]
medical_cause as MedicalCause,
@UI.lineItem: [{ position: 50, label: ‘Doctor assigned’ }]
@UI.identification: [{ position: 50, label: ‘Doctor assigned’ }]
doctor_assigned as DoctorAssigned,
@UI.lineItem: [{ position: 60, label: ‘Room no’ }]
@UI.identification: [{ position: 60, label: ‘Room no’ }]
room_no as RoomNo,
@UI.lineItem: [{ position: 70, label: ‘Payment status’ }]
@UI.identification: [{ position: 70, label: ‘Payment status’ }]
payment_status as PaymentStatus,
_hospital
}
To manage the functionality of the scenario, I have created a behavior definition for the root view (Hospital View).
This behavior definition defines the operations and interactions that can be performed on the hospital entity and its associated patient entities.
managed implementation in class zbp_ismo_i_hospital unique;
strict ( 2 );
define behavior for zismo_i_hospital alias hospital
persistent table zismo_dt_hosp
lock master
authorization master ( instance )
{
create;
update;
delete;
field ( readonly : update ) HospitalId;
association _patient { create; }
mapping for zismo_dt_hosp
{
HospitalId = hospital_id;
HospitalName = hospital_name;
HospitalLocation = hospital_location;
NoOfDoctors = no_of_doctors;
NoOfRooms = no_of_rooms;
}
}
define behavior for zismo_i_patient alias patient
persistent table zismo_dt_patient
lock dependent by _hospital
authorization dependent by _hospital
{
update;
delete;
field ( readonly ) HospitalId;
field ( readonly : update ) PatientId;
association _hospital;
mapping for zismo_dt_patient
{
HospitalId = hospital_id;
PatientId = patient_id;
PatientName = patient_name;
MedicalCause = medical_cause;
DoctorAssigned = doctor_assigned;
RoomNo = room_no;
PaymentStatus = payment_status;
}
}
Step by Step implementation
Early numbering managed
Let’s start with parent entity, in our case hospital view
For managed early numbering, ensure that the key field is of type SYSUUIDx16 (RAW16)
And in the behavior definition of your BO use syntax “numbering: managed” for your key field
That’s it, rest of the things will be managed by framework
Creation of record for parent entity, in our case its hospital view, using early numbering managed
As we can see the unique ID has been generated for us by the framework
Now let’s see how to do it with child entity, in my case patient view
Same steps we need to follow to achieve early numbering managed for child entity
Behavior definition of patient view
Creation of record for child entity, in our case patient view using early numbering managed
Early numbering unmanaged
Unlike managed early numbering here in unmanaged early numbering we can have key fields of any data type
Here in our scenario, I am not changing the data type of the field
To start with early numbering unmanaged, go to your behavior definition and write the syntax early numbering
Let’s start with parent entity, in our case hospital view
Here if we see we are getting an error because at a time only one type of numbering can be used, so remove other numbering and keep the early numbering syntax
Now if we see we are getting a warning at create method of Hospital entity
The warning is related to implementing the method, so put cursor on the line and do a quick fix (CTRL + 1)
System will give the quick fix suggestion to implement the method
Double click and you will enter the behavior pool where you can write implementation for this method
So, let’s write a basic logic to understand unmanaged early numbering
Before writing the logic put cursor on the method name and click F2 to see the parameters related to the method
Here we need to mandatorily fill mapped parameter consisting of %CID and our key field hospitalID
%CID refers to content id which should be unique while creation of new record, this %CID we can refer from entities parameter
So, let’s start writing the code for it
METHOD earlynumbering_create.
SELECT MAX( hospital_id ) FROM zismo_dt_hosp INTO (lv_hos_id).
lv_hos_id = COND #( WHEN lv_hos_id IS NOT INITIAL THEN lv_hos_id + 1
ELSE 1 ).
mapped-hospital = VALUE #( ( %cid = entities[ 1 ]-%cid
HospitalId = lv_hos_id ) ).
ENDMETHOD.
It’s a simple logic where i am checking for maximum hospital id present in the DB and if present then i will increment by one else i will start id by 1
And i am filling in the mapped parameter for hospital view.
Creation of record for parent entity in our case hospital view using early numbering unmanaged
As we can see the record has been created using the logic we implemented for unmanaged early numbering
Now let’s see how to do it with child entity, in my case patient view
Go to the behavior definition of patient view and write the syntax early numbering
Since creation of child entity is dependent on parent entity so the warning is being triggered at behavior definition of parent entity at association
So quick fix the warning and enter behavior pool
cba means create by association
So, let’s write a sample implementation to understand create by association in unmanaged early numbering
Before writing the logic let’s check the method signature by clicking F2
Here inside entities, we don’t have child entity’s key field patientid
So, if we click on %target then we can see the components related to child entity
So, we need to fill patientID present in %target and then we can append %target structure to mapped parameter of patient view
METHOD earlynumbering_cba_Patient.
SELECT MAX( patient_id ) FROM zismo_dt_patient INTO (lv_pat_id).
lv_pat_id = COND #( WHEN lv_pat_id IS NOT INITIAL THEN lv_pat_id + 1
ELSE 1 ).
DATA(ls_target) = entities[ 1 ]-%target[ 1 ].
ls_target-PatientId = lv_pat_id.
APPEND CORRESPONDING #( ls_target ) TO mapped-patient.
ENDMETHOD.
Creation of child entity in our case patient view, using unmanaged cba early numbering
Late numbering
In late numbering also we can do numbering for key fields of any data type
To implement late numbering write the syntax late numbering in the behavior definition of hospital view
And the moment we write late numbering for root/parent entity we get an error
The error is if parent entity is implemented as late numbering, then child entity must also have to contain late numbering
So, lets write late numbering for child entity’s behavior definition as well
Now the error is gone but we get a warning to implement the adjust number method
In case of late numbering every time method name will be adjust numbers where we can write the logic for late numbering
So quick fix the warning and enter behavior pool where we can see the method
Click F2 and analyze the method signature
Now here in this method itself we must write the late numbering logic for both parent and child entity
So, i have written a sample logic
Here whenever we perform create operation the mapped parameter related to that entity will not be initial so by using this condition, we can write a logic
Here to perform create by association we need to get the parent entity key value which we can get from %tmp of child entity, so based on that parent key the associated child will be created
METHOD adjust_numbers.
IF mapped-hospital IS NOT INITIAL.
SELECT MAX( hospital_id ) FROM zismo_dt_hosp INTO (lv_hos_id).
lv_hos_id = COND #( WHEN lv_hos_id IS NOT INITIAL THEN lv_hos_id + 1
ELSE 1 ).
DATA(ls_mapped_hos) = VALUE #( mapped-hospital[ 1 ] OPTIONAL ).
ls_mapped_hos-HospitalId = lv_hos_id.
APPEND CORRESPONDING #( ls_mapped_hos ) TO mapped-hospital.
ELSEIF mapped-patient IS NOT INITIAL.
SELECT MAX( patient_id ) FROM zismo_dt_patient INTO (lv_pat_id).
lv_pat_id = COND #( WHEN lv_pat_id IS NOT INITIAL THEN lv_pat_id + 1
ELSE 1 ).
DATA(ls_mapped_pat) = VALUE #( mapped-patient[ 1 ] OPTIONAL ).
ls_mapped_pat-HospitalId = ls_mapped_pat-%tmp-HospitalId.
ls_mapped_pat-PatientId = lv_pat_id.
APPEND CORRESPONDING #( ls_mapped_pat ) TO mapped-patient.
ENDIF.
ENDMETHOD.
Creation of record for parent entity in our case hospital view using late numbering
Creation of child entity in our case patient view, using late numbering
Yeah, this is about numbering in RAP
One thing to be careful of is while performing numbering with draft based BO we need to fill %is_draft field.
Thanks and Regards.
Introduction In SAP ABAP RESTful Application Programming Model (RAP), the concepts of Create and Create by Association are fundamental for managing data persistence in business objects. Implementing numbering mechanisms during these operations is essential to ensure unique identifiers for newly created entities.This blog explores strategies and best practices for numbering during the Create operation and Create by Association, highlighting how RAP supports these processes in both managed and unmanaged scenarios.Basic Information About Numbering Numbering in RAP refers to the process of assigning unique values to the key fields of business entities during Create operations.Types of Numbering Early Numbering:Primary key values are assigned immediately when a creation operation is initiated. This mechanism is triggered during the interaction phase. Types: Managed Early Numbering: The RAP framework automatically assigns a UUID (Universal Unique Identifier) to the key field during the create request. Applicable for key fields of type RAW (16) in managed scenarios. Unmanaged Early Numbering: Developers implement custom logic to assign key values during the creation operation. Use Cases: Suitable for scenarios requiring immediate key assignment, such as generating unique identifiers for new records upon clicking “Create.” Late Numbering:Primary key values are assigned just before the data is saved to the database. Triggered during the save sequence phase. Implementation: Developers implement the ADJUST_NUMBERS method to handle late numbering. This method is invoked during the save sequence to assign key values. Scenario Example In this example, we have designed a scenario with two views: Hospital View (Root entity) Patient View (Child entity, dependent on Hospital View) The Hospital View is the root entity, and the Patient View is related to it via a composition relationship. The patient data cannot exist independently of the hospital data. Below are the CDS view definitions and behavior implementations for the scenario: Hospital View @AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Hospital interface view’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity zismo_i_hospital
as select from zismo_dt_hosp
composition [1..*] of zismo_i_patient as _patient
{
@UI.facet: [{
label: ‘Hospital information’,
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
position: 10
},
{ label : ‘Patient information’,
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
position: 20,
targetElement: ‘_patient’ } ]
@UI.lineItem: [{ position: 10, label: ‘Hospital Id’ }]
@UI.identification: [{ position: 10, label: ‘Hospital Id’ }]
key hospital_id as HospitalId,
@UI.lineItem: [{ position: 20, label: ‘Hospital name’ }]
@UI.identification: [{ position: 20, label: ‘Hospital name’ }]
hospital_name as HospitalName,
@UI.lineItem: [{ position: 30, label: ‘Hospital location’ }]
@UI.identification: [{ position: 30, label: ‘Hospital location’ }]
hospital_location as HospitalLocation,
@UI.lineItem: [{ position: 40, label: ‘No of doctors’ }]
@UI.identification: [{ position: 40, label: ‘No of doctors’ }]
no_of_doctors as NoOfDoctors,
@UI.lineItem: [{ position: 50, label: ‘No of rooms’ }]
@UI.identification: [{ position: 50, label: ‘No of rooms’ }]
no_of_rooms as NoOfRooms,
_patient
} Patient View @AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘Patient interface view’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity zismo_i_patient
as select from zismo_dt_patient
association to parent zismo_i_hospital as _hospital on $projection.HospitalId = _hospital.HospitalId
{
@UI.facet: [{
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
position: 10
}]
@UI.lineItem: [{ position: 10, label: ‘Hospital Id’ }]
@UI.identification: [{ position: 10, label: ‘Hospital Id’ }]
key hospital_id as HospitalId,
@UI.lineItem: [{ position: 20, label: ‘Patient Id’ }]
@UI.identification: [{ position: 20, label: ‘Patient Id’ }]
key patient_id as PatientId,
@UI.lineItem: [{ position: 30, label: ‘Patient name’ }]
@UI.identification: [{ position: 30, label: ‘Patient name’ }]
patient_name as PatientName,
@UI.lineItem: [{ position: 40, label: ‘Medical cause’ }]
@UI.identification: [{ position: 40, label: ‘Medical cause’ }]
medical_cause as MedicalCause,
@UI.lineItem: [{ position: 50, label: ‘Doctor assigned’ }]
@UI.identification: [{ position: 50, label: ‘Doctor assigned’ }]
doctor_assigned as DoctorAssigned,
@UI.lineItem: [{ position: 60, label: ‘Room no’ }]
@UI.identification: [{ position: 60, label: ‘Room no’ }]
room_no as RoomNo,
@UI.lineItem: [{ position: 70, label: ‘Payment status’ }]
@UI.identification: [{ position: 70, label: ‘Payment status’ }]
payment_status as PaymentStatus,
_hospital
} To manage the functionality of the scenario, I have created a behavior definition for the root view (Hospital View). This behavior definition defines the operations and interactions that can be performed on the hospital entity and its associated patient entities. managed implementation in class zbp_ismo_i_hospital unique;
strict ( 2 );
define behavior for zismo_i_hospital alias hospital
persistent table zismo_dt_hosp
lock master
authorization master ( instance )
{
create;
update;
delete;
field ( readonly : update ) HospitalId;
association _patient { create; }
mapping for zismo_dt_hosp
{
HospitalId = hospital_id;
HospitalName = hospital_name;
HospitalLocation = hospital_location;
NoOfDoctors = no_of_doctors;
NoOfRooms = no_of_rooms;
}
}
define behavior for zismo_i_patient alias patient
persistent table zismo_dt_patient
lock dependent by _hospital
authorization dependent by _hospital
{
update;
delete;
field ( readonly ) HospitalId;
field ( readonly : update ) PatientId;
association _hospital;
mapping for zismo_dt_patient
{
HospitalId = hospital_id;
PatientId = patient_id;
PatientName = patient_name;
MedicalCause = medical_cause;
DoctorAssigned = doctor_assigned;
RoomNo = room_no;
PaymentStatus = payment_status;
}
} Step by Step implementation Early numbering managedLet’s start with parent entity, in our case hospital view For managed early numbering, ensure that the key field is of type SYSUUIDx16 (RAW16) And in the behavior definition of your BO use syntax “numbering: managed” for your key field That’s it, rest of the things will be managed by framework Creation of record for parent entity, in our case its hospital view, using early numbering managed As we can see the unique ID has been generated for us by the framework Now let’s see how to do it with child entity, in my case patient view Same steps we need to follow to achieve early numbering managed for child entity Behavior definition of patient viewCreation of record for child entity, in our case patient view using early numbering managed Early numbering unmanaged Unlike managed early numbering here in unmanaged early numbering we can have key fields of any data type Here in our scenario, I am not changing the data type of the field To start with early numbering unmanaged, go to your behavior definition and write the syntax early numbering Let’s start with parent entity, in our case hospital view Here if we see we are getting an error because at a time only one type of numbering can be used, so remove other numbering and keep the early numbering syntax Now if we see we are getting a warning at create method of Hospital entity The warning is related to implementing the method, so put cursor on the line and do a quick fix (CTRL + 1) System will give the quick fix suggestion to implement the method Double click and you will enter the behavior pool where you can write implementation for this method So, let’s write a basic logic to understand unmanaged early numbering Before writing the logic put cursor on the method name and click F2 to see the parameters related to the method Here we need to mandatorily fill mapped parameter consisting of %CID and our key field hospitalID %CID refers to content id which should be unique while creation of new record, this %CID we can refer from entities parameter So, let’s start writing the code for it METHOD earlynumbering_create.
SELECT MAX( hospital_id ) FROM zismo_dt_hosp INTO (lv_hos_id).
lv_hos_id = COND #( WHEN lv_hos_id IS NOT INITIAL THEN lv_hos_id + 1
ELSE 1 ).
mapped-hospital = VALUE #( ( %cid = entities[ 1 ]-%cid
HospitalId = lv_hos_id ) ).
ENDMETHOD. It’s a simple logic where i am checking for maximum hospital id present in the DB and if present then i will increment by one else i will start id by 1 And i am filling in the mapped parameter for hospital view. Creation of record for parent entity in our case hospital view using early numbering unmanaged As we can see the record has been created using the logic we implemented for unmanaged early numbering Now let’s see how to do it with child entity, in my case patient view Go to the behavior definition of patient view and write the syntax early numbering Since creation of child entity is dependent on parent entity so the warning is being triggered at behavior definition of parent entity at association So quick fix the warning and enter behavior pool cba means create by association So, let’s write a sample implementation to understand create by association in unmanaged early numbering Before writing the logic let’s check the method signature by clicking F2 Here inside entities, we don’t have child entity’s key field patientid So, if we click on %target then we can see the components related to child entity So, we need to fill patientID present in %target and then we can append %target structure to mapped parameter of patient view METHOD earlynumbering_cba_Patient.
SELECT MAX( patient_id ) FROM zismo_dt_patient INTO (lv_pat_id).
lv_pat_id = COND #( WHEN lv_pat_id IS NOT INITIAL THEN lv_pat_id + 1
ELSE 1 ).
DATA(ls_target) = entities[ 1 ]-%target[ 1 ].
ls_target-PatientId = lv_pat_id.
APPEND CORRESPONDING #( ls_target ) TO mapped-patient.
ENDMETHOD. Creation of child entity in our case patient view, using unmanaged cba early numbering Late numbering In late numbering also we can do numbering for key fields of any data type To implement late numbering write the syntax late numbering in the behavior definition of hospital view And the moment we write late numbering for root/parent entity we get an error The error is if parent entity is implemented as late numbering, then child entity must also have to contain late numbering So, lets write late numbering for child entity’s behavior definition as well Now the error is gone but we get a warning to implement the adjust number method In case of late numbering every time method name will be adjust numbers where we can write the logic for late numbering So quick fix the warning and enter behavior pool where we can see the method Click F2 and analyze the method signature Now here in this method itself we must write the late numbering logic for both parent and child entity So, i have written a sample logic Here whenever we perform create operation the mapped parameter related to that entity will not be initial so by using this condition, we can write a logic Here to perform create by association we need to get the parent entity key value which we can get from %tmp of child entity, so based on that parent key the associated child will be created METHOD adjust_numbers.
IF mapped-hospital IS NOT INITIAL.
SELECT MAX( hospital_id ) FROM zismo_dt_hosp INTO (lv_hos_id).
lv_hos_id = COND #( WHEN lv_hos_id IS NOT INITIAL THEN lv_hos_id + 1
ELSE 1 ).
DATA(ls_mapped_hos) = VALUE #( mapped-hospital[ 1 ] OPTIONAL ).
ls_mapped_hos-HospitalId = lv_hos_id.
APPEND CORRESPONDING #( ls_mapped_hos ) TO mapped-hospital.
ELSEIF mapped-patient IS NOT INITIAL.
SELECT MAX( patient_id ) FROM zismo_dt_patient INTO (lv_pat_id).
lv_pat_id = COND #( WHEN lv_pat_id IS NOT INITIAL THEN lv_pat_id + 1
ELSE 1 ).
DATA(ls_mapped_pat) = VALUE #( mapped-patient[ 1 ] OPTIONAL ).
ls_mapped_pat-HospitalId = ls_mapped_pat-%tmp-HospitalId.
ls_mapped_pat-PatientId = lv_pat_id.
APPEND CORRESPONDING #( ls_mapped_pat ) TO mapped-patient.
ENDIF.
ENDMETHOD. Creation of record for parent entity in our case hospital view using late numbering Creation of child entity in our case patient view, using late numbering Yeah, this is about numbering in RAP One thing to be careful of is while performing numbering with draft based BO we need to fill %is_draft field.Thanks and Regards. Read More Application Development Blog Posts articles
#SAP