Early numbering is a critical concept in SAP’s RAP (ABAP RESTful Application Programming Model) that determines when and how unique identifiers are generated for business objects. Unlike traditional approaches where numbers might be assigned during the save sequence, early numbering provides significant advantages by generating keys before the transaction reaches the database.
Why Early Numbering Matters
- Immediate Feedback: Users see assigned numbers immediately after creation
- Transaction Integrity: Prevents collisions in complex business processes
- Downstream Processing: Enables reference to new objects before persistence
- Better UX: Allows showing generated numbers in UI before saving
Implementing Early Numbering
Basic Implementation
@ObjectModel.modelEntity: {
createEnabled: true,
earlyNumbering: cue
}
define behavior for ZI_SalesOrder alias SalesOrder
{
// Behavior implementation
}
Custom Early Numbering Handler
CLASS lhc_salesorder DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS earlynumbering FOR NUMBERING
IMPORTING entities FOR SalesOrder.
ENDCLASS.
CLASS lhc_salesorder IMPLEMENTATION.
METHOD earlynumbering.
DATA: max_so_id TYPE char10.
" Get current maximum SO number
SELECT MAX( sales_order ) FROM zsalesorders INTO @max_so_id.
" Assign numbers to new entities
LOOP AT entities INTO DATA(entity).
IF entity-sales_order IS INITIAL.
max_so_id = max_so_id + 1.
APPEND VALUE #( %cid = entity-%cid
sales_order = max_so_id )
TO mapped-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Key Technical Aspects
The Numbering Phase
Early numbering occurs:
- During draft handling (for draft-enabled scenarios)
- Before modify operations reach the database
- After input validation but before save sequence
The Mapped Table
The mapped
structure is crucial for early numbering:
- Contains mapping between %cid (client instance ID) and generated key
- Ensures consistency between UI and backend
Locking Considerations
For custom implementations:
METHOD earlynumbering.
" Acquire lock
CALL FUNCTION 'ENQUEUE_EZ_SO_NUM'.
" Number generation logic
" Release lock
CALL FUNCTION 'DEQUEUE_EZ_SO_NUM'.
ENDMETHOD.
Hybrid Numbering Approach
METHOD earlynumbering.
LOOP AT entities INTO DATA(entity).
IF entity-sales_order IS NOT INITIAL.
" Validate externally provided number
IF NOT is_valid( entity-sales_order ).
APPEND VALUE #( %cid = entity-%cid )
TO failed-salesorder.
APPEND VALUE #( %cid = entity-%cid
%msg = new_message(...) )
TO reported-salesorder.
ENDIF.
ELSE.
" Generate internal number
entity-sales_order = generate_number( ).
APPEND VALUE #( %cid = entity-%cid
sales_order = entity-sales_order )
TO mapped-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
Number Range Integration
METHOD earlynumbering.
DATA: number_range TYPE nriv.
CALL FUNCTION 'NUMBER_GET_NEXT'
EXPORTING
nr_range_nr = '01'
object = 'ZSO_NUM'
IMPORTING
number = DATA(new_number).
" Assign to entities...
ENDMETHOD.
End-to-End Example of Early Numbering in SAP RAP
We’ll create a Sales Order application with:
- Automatic number generation when no number is provided
- Validation for externally provided numbers
- Integration with SAP number ranges
- Full draft handling support
Data Model Definition
2.1 Base CDS View (ZC_SalesOrder
)
@AbapCatalog.sqlViewName: 'ZCSALESORDER'
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Sales Order CDS View'
define view ZC_SalesOrder as select from zsalesorder_db {
key sales_order : zsalesorder_id,
customer : zcustomer_id,
order_date : abap.dats,
total_amount : zamount,
currency : zcurrency,
status : zstatus
}
Projection View (ZC_SalesOrder_Projection)
@UI: {
headerInfo: {
typeName: 'Sales Order',
typeNamePlural: 'Sales Orders'
}
}
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
define view ZC_SalesOrder_Projection
as select from ZC_SalesOrder
{
key sales_order,
customer,
order_date,
total_amount,
currency,
status
}
Behavior Definition
Behavior Definition (ZC_SalesOrder)
managed implementation in class zbp_salesorder unique;
strict;
with draft;
define behavior for ZC_SalesOrder alias SalesOrder
persistent table zsalesorder_db
draft table zsalesorder_dft
lock master
authorization master ( instance )
early numbering
{
create;
update;
delete;
field ( readonly ) sales_order;
determination EarlyNumbering on save { create; }
validation ValidateCustomer on save { create; update; }
draft action Edit;
draft action Activate;
draft action Discard;
draft action Resume;
draft determine action Prepare;
}
Behavior Implementation
Behaviour Pool Class (ZBP_SalesOrder)
CLASS zbp_salesorder DEFINITION PUBLIC ABSTRACT FINAL
FOR BEHAVIOR OF zc_salesorder.
ENDCLASS.
CLASS zbp_salesorder IMPLEMENTATION.
ENDCLASS.
Behavior Implementation Class (ZCL_SalesOrder)
CLASS zcl_salesorder DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS earlynumbering FOR NUMBERING
IMPORTING entities FOR SalesOrder.
METHODS validatecustomer FOR VALIDATE ON SAVE
IMPORTING keys FOR SalesOrder~validatecustomer.
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR SalesOrder RESULT result.
ENDCLASS.
CLASS zcl_salesorder IMPLEMENTATION.
METHOD earlynumbering.
DATA: salesorder_numbers TYPE TABLE FOR NUMBERING zc_salesorder.
" Get next available numbers from number range
LOOP AT entities INTO DATA(entity).
IF entity-sales_order IS INITIAL.
CALL FUNCTION 'NUMBER_GET_NEXT'
EXPORTING
nr_range_nr = '01'
object = 'ZSO_NUM'
IMPORTING
number = DATA(salesorder_number).
APPEND VALUE #( %cid = entity-%cid
sales_order = salesorder_number )
TO mapped-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD validatecustomer.
" Validate customer exists
SELECT customer_id FROM zcustomers
FOR ALL ENTRIES IN @keys
WHERE customer_id = @keys-customer
INTO TABLE @DATA(valid_customers).
LOOP AT keys INTO DATA(key).
IF NOT line_exists( valid_customers[ customer_id = key-customer ] ).
APPEND VALUE #( %tky = key-%tky ) TO failed-salesorder.
APPEND VALUE #( %tky = key-%tky
%msg = new_message( id = 'ZSO_MSG'
number = '001'
severity = if_abap_behv_message=>severity-error ) )
TO reported-salesorder.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD get_instance_features.
" Implementation for UI controls
ENDMETHOD.
ENDCLASS.
Number Range Configuration
Create Number Range Object
- Go to transaction SNRO
- Create object ZSO_NUM
- Define intervals (e.g., 1000000000-1999999999)
Number Range Maintenance
" Alternative in-code initialization (optional)
CALL FUNCTION 'NUMBER_RANGE_INITIALIZE'
EXPORTING
object = 'ZSO_NUM'.
UI Service Definition
Service Definition (ZSD_SalesOrder)
@EndUserText.label: 'Sales Order Service'
define service ZSD_SalesOrder {
expose ZC_SalesOrder_Projection as SalesOrder;
}
Service Binding (ZSB_SalesOrder)
@EndUserText.label: 'Sales Order Service Binding'
service ZSB_SalesOrder {
bind ZSD_SalesOrder;
}
Testing the Implementation
Create Operation
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination(
cl_http_destination_provider=>create_by_url( '.../SalesOrder' )).
DATA(lo_request) = lo_client->get_http_request( ).
lo_request->set_method( 'POST' ).
lo_request->set_content_type( 'application/json' ).
DATA(lv_payload) = `{
"customer": "100001",
"order_date": "20231015",
"currency": "USD"
}`.
lo_request->set_text( lv_payload ).
DATA(lo_response) = lo_client->execute( lo_request ).
Adding Draft Support
METHOD earlynumbering.
IF draft-enabled( ) AND is_draft( entities[ 1 ]-%is_draft ).
" Special handling for draft numbering
ELSE.
" Regular numbering logic
ENDIF.
ENDMETHOD.
Custom Number Formatting
METHOD format_salesorder_number.
" Example: SO-2023-0000001
CONCATENATE 'SO-' sy-datum(4) '-' lpad( iv_number, 7, '0' )
INTO rv_formatted_number.
ENDMETHOD.
Early numbering in SAP RAP represents a significant evolution from traditional ABAP programming models. By generating identifiers early in the business object lifecycle, it enables:
- Better user experience with immediate feedback
- More robust transaction processing
- Simplified integration with downstream systems
- Flexible numbering schemes to meet business requirements
For developers transitioning to RAP, mastering early numbering is essential for building modern, responsive applications that meet today’s business demands.
1 thought on “Early Numbering in RAP ABAP”