RAP To-Do List
A full-stack ABAP RAP application — CDS views, behavior definitions, draft handling, and an OData V4 Fiori Elements UI
Overview
A managed RAP business object for a simple to-do list. The application covers the full vertical slice of a RAP stack: a database table, two CDS layers, a managed behavior definition with draft support, an OData V4 service binding, and a Fiori Elements List Report.
Data model
The root table ZTODO_100 stores tasks with the following fields:
| Field | Type | Note |
|---|---|---|
TASK_UUID | RAW(16) | Primary key, UUID |
TITLE | String | Mandatory |
DESCRIPTION | String | Optional |
STATUS | Domain ZTODO_STATUS | OPEN / IN_PROGRESS / DONE |
PRIORITY | Integer | |
DUE_DATE | Date | |
COMPLETED_AT | Timestamp |
Administrative fields (CREATED_BY, CREATED_AT, LOCAL_LAST_CHANGED_AT, LAST_CHANGED_AT) are managed by the framework via @Semantics annotations.
CDS layer
Two views follow the standard RAP naming convention:
ZR_TODO_100 — the root view entity. Maps directly from the database table and exposes all fields including the administrative ones annotated with @Semantics so the framework fills them automatically.
ZC_TODO_100 — the consumption (projection) view. Declares provider contract transactional_query and adds a value help on Status pointing to ZI_TODO_STATUS_VH_100. Metadata extensions are enabled via @Metadata.allowExtensions: true, allowing the Fiori UI layout to be defined in a separate .ddlx file without touching the view itself.
Behavior definition
The behavior is managed — the framework handles the persistence layer automatically.
managed implementation in class ZBP_TODO_100 unique;
strict ( 2 );
with draft;
Draft
Draft is enabled with a dedicated draft table ZTODO_100_D. This gives the Fiori UI full draft support: users can start editing a record, navigate away, and return to their unfinished changes without losing data.
Early numbering
UUIDs are assigned in the behavior handler before the record reaches the database:
METHOD earlynumbering_create.
LOOP AT entities INTO DATA(entity).
IF entity-TaskUUID IS INITIAL.
DATA(lv_uuid) = cl_system_uuid=>create_uuid_x16_static( ).
APPEND VALUE #( %cid = entity-%cid TaskUUID = lv_uuid ) TO mapped-zr_todo_100.
ENDIF.
ENDLOOP.
ENDMETHOD.
Using early numbering rather than late numbering means the key is known client-side immediately after creation, which is required for draft.
Determination — setDefaultStatus
When a task is created without a status, the determination sets it to OPEN:
METHOD setDefaultStatus.
LOOP AT todos INTO DATA(todo).
IF todo-Status IS INITIAL.
APPEND VALUE #( %tky = todo-%tky Status = 'OPEN' ) TO update_todos.
ENDIF.
ENDLOOP.
MODIFY ENTITIES OF zr_todo_100 IN LOCAL MODE
ENTITY zr_todo_100 UPDATE FIELDS ( Status ) WITH update_todos.
ENDMETHOD.
IN LOCAL MODE bypasses authorization checks for the internal update — correct since this is framework-driven logic, not a user action.
Validation — validateTitle
Fires on save for create and update, rejects blank titles with a field-level message:
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Title must not be empty' )
Field-level messages (%element-Title = if_abap_behv=>mk-on) highlight the exact input in the Fiori UI.
Service exposure
The OData V4 service is exposed via ZUI_TODO_100_O4:
- Service definition (
SRVD) — bindsZC_TODO_100to a service - Service binding (
SRVB) — publishes the service as OData V4, consumed directly by Fiori Elements as a List Report page