BDL — Behavior Definition Language
BDL (Behavior Definition Language) — декларативна мова, якою описується transactional behavior RAP business object. Файл BDEF (behavior definition) каже фреймворку: «цей BO — managed, є такі-то поля, підтримує create/update/delete, має ось цю action, блокування через master, авторизація — global». А вже ABAP behavior pool (ABP) реалізує саму логіку handler-методів там, де BDL каже, що вона потрібна.
Головна ідея: максимум у BDL — мінімум у ABP. Чим більше можна декларувати (замість писати імперативний код), тим стабільніше BO і тим менше помилок.
Типовий BDEF цілком
Section titled “Типовий BDEF цілком”managed implementation in class zbp_r_order unique;strict ( 2 );with draft;
define behavior for ZR_Order alias Orderpersistent table zorderdraft table zorder_detag master LocalLastChangedAtlock mastertotal etag LastChangedAtauthorization master ( instance ){ field ( readonly ) OrderId, CreatedBy, CreatedAt; field ( mandatory ) Customer, Total;
create; update; delete;
association _Items { create; }
action ( features : instance ) approve result [1] $self; action cancel;
validation check_total on save { create; update; field Total; } determination calc_totals on modify { create; field Items; }
draft action Edit; draft action Activate optimized; draft action Discard; draft action Resume; draft determine action Prepare { validation check_total; }
mapping for zorder corresponding { OrderId = order_id; Customer = customer; }}
define behavior for ZR_OrderItem alias OrderItempersistent table zorderitemlock dependent by _Orderauthorization dependent by _Order{ field ( readonly ) OrderId, Position; update; delete;}Далі розберемо компоненти.
Header — властивості всього BO
Section titled “Header — властивості всього BO”Implementation type
Section titled “Implementation type”managed implementation in class zbp_r_order unique; " managedunmanaged implementation in class zbp_r_order_u unique; " unmanagedmanaged with unmanaged save ... " гібридmanaged with additional save ... " managed + розширена save-фаза- managed — фреймворк тримає транзакційний буфер і робить CRUD автоматично. Для грінфілду.
- unmanaged — buffer і всі операції пишемо самі. Для браунфілду, інтеграції з legacy.
- with unmanaged save — managed interaction, але save-фаза ручна (напр., треба писати у стару таблицю через FM).
- with additional save — стандартний save + додатковий метод
save_modifiedдля change docs, подій, логів.
Strict mode
Section titled “Strict mode”strict ( 2 );Вмикає суворі syntax-перевірки BDEF. Завжди — версія 2 (найновіша). Без strict компілятор прощає багато дрібниць, які потім стріляють у runtime.
Draft handling
Section titled “Draft handling”with draft;with collaborative draft;with draft вмикає draft-сценарій (чернетки на UI, автозбереження). Потрібна окрема draft table з адмін-ключами. collaborative draft — кілька користувачів працюють над тим самим draft одночасно.
Auxiliary classes
Section titled “Auxiliary classes”auxiliary class zcl_order_helpers;Допоміжні класи з додатковими правами доступу до BO (можуть робити IN LOCAL MODE).
Entity behavior — define behavior for
Section titled “Entity behavior — define behavior for”define behavior for ZR_Order alias Order external 'Order' " імʼя в OData metadata implementation in class zbp_r_order uniquealias — коротка назва, яку видно у handler-методах і derived types. external — публічне імʼя у OData.
Persistent & draft table
Section titled “Persistent & draft table”persistent table zorderdraft table zorder_dpersistent — де зберігаються активні дані. draft — де draft-instances. Ім’я полів у draft table повинно співпадати з entity; плюс обовʼязкова адмін-структура:
"%admin" : include sych_bdl_draft_admin_inc;Concurrency control
Section titled “Concurrency control”" Optimistic (через ETag)etag master LocalLastChangedAtetag dependent by _Ordertotal etag LastChangedAt " тільки для draft-enabled BO
" Pessimistic (lock table)lock masterlock master unmanaged " ти реалізовуєш lock самlock dependent by _Orderetag master— поле з timestamp, що оновлюється при кожному write. OData-клієнт повинен передати ETag — якщо не збігається, write відхиляється.total etag— для draft. Порівнюється між активним instance та draft при resume.lock master— ексклюзивний lock на запис уsm12-стилі.lock dependent by _Assoc— child блокується через parent (кращий варіант для composition).
Numbering
Section titled “Numbering”early numberinglate numberingfield ( numbering : managed ) OrderIdКерує, хто і коли заповнює ключ:
| Варіант | Коли | Хто | BDL |
|---|---|---|---|
| External early | interaction phase | споживач (UI) | дефолт |
| Managed internal early | interaction phase | фреймворк (UUID) | field ( numbering : managed ) |
| Unmanaged internal early | interaction phase | ABP (FOR NUMBERING) | early numbering |
| Late numbering | save sequence | saver method adjust_numbers | late numbering |
Authorization
Section titled “Authorization”authorization master ( global )authorization master ( instance )authorization master ( global, instance )authorization master ( none )authorization dependent by _Orderglobal— перевірка ролі (без конкретного instance, перед create).instance— перевірка залежно від стану instance (хто може update цей конкретний рядок).none— нічого не перевіряти (обережно).dependent by _Assoc— child наслідує дозволи parent через composition.
Для global/instance в ABP мають бути методи FOR GLOBAL AUTHORIZATION / FOR INSTANCE AUTHORIZATION.
Entity body — всередині фігурних дужок
Section titled “Entity body — всередині фігурних дужок”Field characteristics
Section titled “Field characteristics”field ( readonly ) OrderId, CreatedBy;field ( readonly : create ) Status;field ( readonly : update ) Customer;field ( mandatory ) Customer;field ( mandatory : create ) OrderId;field ( suppress ) InternalField; " прибрати з derived typesfield ( features : instance ) DynamicField; " динамічна видимістьПоле одночасно може бути mandatory : create і readonly : update — типова комбінація для ключа в external numbering.
Standard operations
Section titled “Standard operations”create;update;delete;
" з доповненнямиinternal create; " внутрішнє — не для ODatacreate ( authorization : none );update ( features : instance );delete ( authorization : update ); " delete використовує auth від updatecreate { default function GetDefaults; } " UI-дефолтиRead завжди неявно дозволено — окремого ключового слова немає.
Actions — нестандартні операції
Section titled “Actions — нестандартні операції”action approve; " регулярна actioninternal action recalc; " тільки з BOstatic action cleanup; " не привʼязана до instancerepeatable action log; " можна викликати багато разівaction act parameter ZR_ActParam; " з inputaction act result [1] $self; " з output (selfreturning)action act result [0..*] selective SomeEntity; " масив + selectivefactory action copy [1]; " створення instancedefault factory action newFromTemplate [1]; " default для UIsave( finalize ) action rebuild_index; " save-time action
action ( features : global ) act1;action ( features : instance ) act2;action ( precheck ) act3;action ( authorization : update ) act4;action ( lock : none ) act5;Cardinality у [...]: [1], [0..1], [0..*], [1..*].
Functions — read-only нестандартні
Section titled “Functions — read-only нестандартні”function calcTotal result [1] $self;static function getDefaults result [1] ZR_DefaultsType;Function не змінює стан, не блокує. Використовується для обчислень, пошуків, lookup.
Associations з операціями
Section titled “Associations з операціями”association _Items; " read-by-assoc автоматичноassociation _Items { create; } " + create-by-assocassociation _Items { create; link action attachItem; unlink action detachItem; inverse function findParentByItem;}Validations & determinations
Section titled “Validations & determinations”validation check_total on save { create; update; field Total; }validation check_status on save { delete; }
determination fill_defaults on modify { create; }determination recalc_total on modify { field Quantity, Price; }determination snapshot on save { create; }- Validation — перевіряє дані, може відхилити save. Реалізується у
FOR VALIDATE. - Determination — змінює дані при тригері.
on modify— одразу після зміни у буфері;on save— під час save sequence. Реалізується уFOR DETERMINE.
Determine actions
Section titled “Determine actions”determine action revalidate { determination recalc_total; determination ( always ) snapshot; " завжди, навіть без trigger validation check_total;}Дозволяє вручну викликати набір determinations/validations (напр., з UI «Перевірити»).
Draft actions
Section titled “Draft actions”draft action Edit;draft action Activate optimized; " optimized — дешевший save для draftdraft action Discard;draft action Resume;draft determine action Prepare { validation check_total; }Усі чотири (Edit, Activate, Discard, Resume) + Prepare обовʼязкові для draft-enabled BO. Імплементація — фреймворком; за бажанням розширюєш через with additional implementation.
Side effects
Section titled “Side effects”side effects { field Quantity affects field Total; " зміна Quantity → reload Total на UI $self affects field StatusText; action approve affects field *, messages; " reload усього + messages determine action revalidate executed on field Quantity, field Price affects field Total; event priceChanged affects field Price; field StatusCode affects permissions( action cancel ); " reload feature control}Side effects — про UX на UI, не про бізнес-логіку. Вони дають Fiori команду «перечитати це поле», коли щось змінилось. Без implementation у ABP.
Events
Section titled “Events”event orderCreated;event orderApproved parameter ZR_OrderEventParam;event orderClosed deep parameter ZR_OrderDeepEventParam;managed event orderSummary on orderCreated parameter ZR_Summary;event priceChanged for side effects;Піднімаються через RAISE ENTITY EVENT у saver method (save_modified). Потребують event binding, щоб мапитись на конкретний channel (SAP Event Mesh, logging, тощо).
Type mapping
Section titled “Type mapping”mapping for zorder corresponding{ OrderId = order_id; Customer = customer_name; Total = total_amount;}Потрібне коли поля CDS і DB-таблиці називаються по-різному. Для managed BO без mapping — warning; може зламати auto-save.
Projection BDEF
Section titled “Projection BDEF”Коли над base BDEF робиш projection (обмежений інтерфейс для UI/API):
projection;strict ( 2 );use draft;
define behavior for ZC_Order alias Orderuse etag{ use create; use update; use delete; use action approve; use action cancel; use association _Items { create; }}Projection не визначає поведінку заново — тільки вказує, які операції base BDEF включено у цей шар.
Посилання
Section titled “Посилання”- RAP BDL — ABAP Keyword Documentation.
- RAP Development Guide.
- Приклади — rap-гілка в репозиторії abap-cheat-sheets.
Адаптовано з 36_RAP_Behavior_Definition_Language.md (Apache 2.0). Детальніше — в оригіналі.