Збереження декількох сутностей в рамках однієї транзакції

ЗМІСТ
🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію.

1. Проблематика

При використанні делегата dataFactoryConnectorCreateDelegate та відповідного ендпоінта, за потреби запису 2-х і більше сутностей до бази даних, виникає проблема — це може бути реалізовано тільки по черзі, різними транзакціями.

Відповідно, одна транзакція може завершитися успішно, а наступна — з будь-якої причини не завершитися. Такий сценарій може призвести до неконсистентності даних, необхідності видалення успішної транзакції із БД і повторного виконання всіх процедур.

Такий підхід ускладнює моделювання, значно подовжуючи бізнес-процес, а також збільшує навантаження на базу даних, адже збільшується і кількість транзакцій при створенні сутностей.

Приклад 1. Приклад

Наприклад, необхідно записати дані про користувача (1), його навчальний профіль (2) та налаштування користувача (3). Маємо три послідовні БД-транзакції:

  1. Запис персональних даних користувача (простий об’єкт personProfile) до таблиці person_profile. Операція успішна.

  2. Запис даних для створення навчального профілю користувача (простий об’єкт personEduProfile) до таблиці person_edu_profile. Операція неуспішна.

  3. Запис налаштувань користувача (простий об’єкт userSettings) до таблиці user_setting. Транзакція не розпочалася взагалі.

В результаті, лише одна транзакція успішна. База даних не консистентна. Виникає необхідність відкотити БД до попереднього стану, тобто видалити кожну виконану транзакцію через DELETE-ендпоінт, і виконати всі три записи повторно.

Для розв’язання цієї проблеми впроваджено спеціальний делегат, що забезпечуватиме можливість одночасно зберігати декілька сутностей до різних таблиць бази даних в рамках однієї транзакції.

2. Загальний опис

З метою підтримки функціональності збереження декількох сутностей в рамках однієї транзакції[1], розроблено типове розширення до бізнес-процесів — делегат ${dataFactoryConnectorNestedCreateDelegate}, для якого імплементовано однойменний шаблон Create nested entities in data factory, представлений у вигляді JSON-файлу dataFactoryConnectorNestedCreateDelegate.json.

Делегат потрібний для того, щоб в рамках однієї транзакції створювати декілька сутностей у Фабриці даних.

На Платформі реєстрів реалізовано подібний делегат і відповідний шаблон до нього — Create entity in data factory, але він дозволяє створити лише одну сутність в рамках транзакції.

За таких обставин результат однієї сервісної задачі бізнес-процесу може створити тільки один запис у сховищі даних.

За допомогою делегата ${dataFactoryConnectorNestedCreateDelegate} реалізовано можливість створення декількох записів з однієї сервісної задачі.

Для того, щоб делегат міг функціонувати, на рівні Фабрики даних реалізована можливість створення вкладених сутностей (nested entities), тобто імплементовано окремий спеціальний ендпоінт, щоб приймати комплексні (вкладені) об’єкти, що містять декілька сутностей, від рівня бізнес-процесів і створювати відповідні записи у різних таблицях бази даних за одну транзакцію.

На рівні API, у контракті, описано, яким має бути тіло запита, щоб мати змогу створити декілька сутностей у БД.

Після опрацювання на рівні API, Фабрика даних сама розкладе дані до належних таблиць.

3. Моделювання бізнес-процесу для створення та використання вкладених сутностей

Передумови

Перед моделюванням процесу та налаштуванням делегата Create nested entities in data factory, переконайтеся, що папка /element-templates застосунку Camunda Modeler містить файл dataFactoryConnectorNestedCreateDelegate.json.

bp nested entities 1

3.1. Моделювання та налаштування бізнес-процесу

На прикладі бізнес-процесу для створення вкладених сутностей розглянемо налаштування делегата Create nested entities in data factory, а також кроки моделювання таких сутностей у процесі: створення користувача, створення навчального профілю користувача, а також створення наказів, на підставі яких додається навчальний профіль.

bp nested entities 01

3.1.1. Створення пулу для бізнес-процесу

  1. Відкрийте додаток Camunda Modeler та створіть нову діаграму BPMN. Для цього у лівому верхньому куті натисніть меню FileNew FileBPMN Diagram.

    bp 1

  2. На панелі інструментів зліва знайдіть елемент Create pool/Participant та перетягніть його до області моделювання.

    bp 2

  3. Заповніть наступні поля відповідними значеннями:

    • У полі Participant Name введіть назву пулу, що відображатиметься у моделері — Бізнес-процес.

    • У полі Process id введіть ідентифікатор бізнес-процесу — nested_entity_test_process.

    • У полі Process Name вкажіть бізнес-назву процесу — nested entity test process.

    bp nested entities 02

3.1.2. Моделювання стартової події

Створіть початкову подію для запуску бізнес-процесу користувачем. Для цього виконайте наступні кроки:

  1. На панелі інструментів, зліва, знайдіть елемент (коло) CreateStartEvent та перетягніть його до панелі моделювання.

  2. На панелі налаштувань справа заповніть наступні параметри відповідними значеннями:

    • У полі Name введіть назву початкової події — Початок;

    • У полі Initiator введіть initiator.

      initiator — спеціальна змінна, що встановлюється для користувача, який розпочав процес.

    bp nested entities 03

3.1.3. Моделювання користувацьких форм для введення та підпису даних

Моделювальник має створити дві користувацькі задачі (форми) для внесення персональних даних користувача (1) та їх подальшого підпису КЕП (2).

bp nested entities 04

  1. Змоделюйте користувацьку задачу (User form) для внесення даних профілю користувача та пов’яжіть її із формою бізнес-процесу параметром Form key.

    • У полі Id вкажіть ідентифікатор задачі — addPersonProfileActivity. Він є ключем визначення задачі (task definition key).

    • У полі Name введіть назву задачі. Наприклад, Внести дані про освітній профіль.

    • У полі Form key введіть ключ форми бізнес-процесу — add-dataprof.

    • У полі Assignee вкажіть змінну, що використовується для зберігання користувача, який запустив екземпляр процесу, — ${initiator}.

      bp nested entities 05

  2. Змоделюйте користувацьку задачу (User form) для підпису даних профілю користувача за допомогою КЕП та пов’яжіть її із формою бізнес-процесу параметром Form key.

    • У полі Id вкажіть ідентифікатор задачі — signPersonProfileActivity. Він є ключем визначення задачі (task definition key).

    • У полі Name введіть назву задачі. Наприклад, Підписати дані про освітній профіль.

    • У полі Form key введіть ключ форми бізнес-процесу — add-signd.

    • У полі Assignee вкажіть змінну, що використовується для зберігання користувача, який запустив екземпляр процесу, — ${initiator}.

      bp nested entities 06

Тобто з погляду UI, після запуску бізнес-процесу, перед посадовою особою з’явиться форма для внесення даних профілю. Після внесення даних з’явиться нова форма для підпису даних за допомогою КЕП. Дані будуть передані бізнес-процесу за параметром Form key і використані у наступній задачі процесу.

3.1.4. Моделювання задачі скриптування "Підготовка даних до запису (transient var)" для формування простого об’єкта

Внесені на формі та підписані КЕП дані передаються задачі скриптування (Script task), де використовується groovy-скрипт, який формує із цих даних JSON-об’єкт і записує його до змінної createPersonPayload.

bp nested entities 07

  1. Створіть нову задачу, визначте її тип, натиснувши іконку ключа та обравши з меню пункт Script Task (Задача скриптування).

  2. На панелі налаштувань справа заповніть наступні поля:

    • У полі Name вкажіть назву задачі — Підготовка даних для запису (transient var).

    • У полі Script Format вкажіть формат скрипту — groovy.

    • У полі Script Type вкажіть тип скрипту — Inline Script.

    • У полі Script введіть безпосередньо groovy-скрипт:

      Приклад 2. Приклад. Groovy-скрипт, що формує JSON-об’єкт для подальшого запису до БД
      def cephData = [:]
      
              def formData = submission('signPersonProfileActivity').formData
      
              cephData['lastName'] = formData.prop('last_name').value()
              cephData['firstName'] = formData.prop('first_name').value()
              cephData['secondName'] = formData.prop('second_name').value()
              cephData['birthday'] = formData.prop('birthday').value()
      
              set_transient_variable('createPersonPayload', S(cephData, 'application/json'))

      bp nested entities 08

  3. В результаті виконання задачі, у виводі отримуємо сформований JSON, збережений до змінної createPersonPayload, що надалі використовуватиметься у бізнес-процесі.

    Приклад 3. Приклад. Сформований JSON-об’єкт, збережений до змінної 'createPersonPayload'
    {
    "secondName": "string",
    "firstName": "string",
    "lastName": "string",
    "birthday": "2022-02-16T13:17:10.952Z"
    }

3.1.5. Моделювання Call Activity для підпису простого об’єкта системним ключем

Далі необхідно створити Call Activity для виклику глобального підпроцесу підпису даних системним ключем. Call Activity використовує змінну createPersonPayload, дані з якої передаються до підпроцесу для подальшого їх підпису.

В результаті виконання підпроцесу, викликаного у Call Activity, дані підписуються системним Ceph-ключем. Ключ зберігається до змінної person_profile_system_signature_ceph_key.

  1. Змоделюйте елемент Call Activity.

  2. Перейдіть до панелі налаштувань справа та застосуйте делегат System digital signature. Для цього оберіть відповідний шаблон із каталогу (Open Catolog).

    Приклад налаштування делегата System digital signature наведено за посиланням.
  3. Виконайте подальші налаштування:

    • У полі Name вкажіть назву елемента — Підписати дані системним ключем.

    • У полі Input data вкажіть вхідні дані, які необхідно передати підпроцесу, що викликатиметься — ${createPersonPayload}.

    • У полі Output variable name введіть назву змінної, в яку буде записано системний Ceph-ключ — person_profile_system_signature_ceph_key. Він потрібний для додаткового системного підпису у Фабриці даних.

      Ідентифікатор підпроцесу, що викликатиметься, передається у полі Called Element і має стале значення system-signature-bp. Ці та деякі інші налаштування "вшито" до шаблону з метою спрощення моделювання.

      bp nested entities 09

3.1.6. Моделювання сервісної задачі для створення профілю користувача

Надалі дані використовуються у сервісній задачі "Створити профайл".

У задачі необхідно застосувати делегат для створення однієї сутності у базі даних (Create entity in data factory), використавши підписані дані (Payload) зі змінної ${createPersonPayload}, та надіслати запит до відповідного API-ендпоінту (ресурсу) person-profile.

Разом із даними передається і ключ для перевірки системного підпису Фабрикою даних, який взято зі змінної ${person_profile_system_signature_ceph_key}.

В результаті отримуємо відповідь від API, яка зберігатиметься у змінній createPersonProfileResponse.

  1. Змоделюйте нову задачу.

  2. Визначте її тип, натиснувши іконку ключа та обравши з меню пункт Service Task (сервісна задача).

  3. Перейдіть до панелі налаштувань справа та застосуйте делегат Create entity in data factory. Для цього оберіть відповідний шаблон із каталогу (Open Catalog).

  4. Виконайте подальші налаштування:

    • У полі Id вкажіть ідентифікатор сервісної задачі — createProfile.

    • У полі Name вкажіть назву задачі. Наприклад, Створити профайл.

    • У полі Resource вкажіть ресурс (API-ендпоінт), куди необхідно виконати запит — person-profile.

      На рівні API ендпоінт виглядає наступним чином: /<resource name>, де <resource name> — назва ресурсу. Тобто у полі Resource необхідно ввести значення, вказане після косої риски (/).
    • У полі Payload введіть тіло запита — JSON-об`єкт, тобто дані зі змінної ${createPersonPayload}, які необхідно зберегти до Фабрики даних.

      Майте на увазі, що необхідно попередньо побудувати цей JSON-об`єкт, тобто payload, в рамках задачі скриптування.
    • У полі X-Access-Token вкажіть токен доступу до ресурсу.

      Токен доступу береться з АБО ініціатора (наприклад, ${initiator().accessToken}), АБО виконавця задачі (наприклад, ${completer('taskDefinitionId').accessToken}):

      • Якщо перед сервісною задачею у бізнес-процесі немає жодної користувацької задачі, використовуємо токен ініціатора процесу (initiator).

      • Якщо перед сервісною задачею є користувацька задача, використовуємо токен виконавця задачі (completer).

      Таким чином ми від імені користувача, який АБО запустив бізнес-процес, АБО виконав користувацьку задачу, створюємо сутність у базі даних.

    • У полі X-Digital-Signature-source вкажіть джерело цифрового підпису (КЕП), тобто передайте функції sign_submission() ID користувацької форми, де застосовували КЕП — ${sign_submission('signPersonProfileActivity').signatureDocumentId}.

    • У полі X-Digital-Signature-Derived-source вкажіть джерело системного підпису, тобто змінну, з якої необхідно взяти системний ключ, — ${person_profile_system_signature_ceph_key}.

    • У полі Result variable вкажіть назву змінної, до якої необхідно зберегти відповідь від API, — createPersonProfileResponse.

      bp nested entities 2

В результаті виконується одна транзакція, що записує один простий об’єкт personProfile до відповідної таблиці person_profile у базі даних.

3.1.7. Моделювання задачі скриптування "Підготовка даних" для формування комплексного об’єкта

Далі у задачі скриптування необхідно створити комплексний об’єкт (nested object), що містить вкладені сутності:

  • об’єкт personEduProfile (навчальний профіль користувача), в якому ми передаємо вкладений об’єкт з ID щойно створеного користувача (personProfileId);

  • а також об’єкт orders, в якому передається список атрибутів наказу, тобто додаткові налаштування (підстави) для створення такого навчального профілю.

Комплексний JSON-об’єкт із вкладеними сутностями записуємо до змінної createComplexPayload.

bp nested entities 3

  1. Створіть нову задачу, визначте її тип, натиснувши іконку ключа та обравши з меню пункт Script Task (Задача скриптування).

  2. На панелі налаштувань справа заповніть наступні поля:

    • У полі Name вкажіть назву задачі — Підготовка даних.

    • У полі Script Format вкажіть формат скрипту — groovy.

    • У полі Script Type вкажіть тип скрипту — Inline Script.

    • У полі Script введіть безпосередньо groovy-скрипт:

      Приклад 4. Приклад. Groovy-скрипт, що формує комплексний JSON-об’єкт для подальшого запису до БД
      def personProfileId = createPersonProfileResponse.responseBody.prop('id').value()
      
              def personEduProfile = ['personProfileId':personProfileId]
      
              def formData = submission('signPersonProfileActivity').formData
      
              def orders = [:]
              orders['ordersType'] = formData.prop('order_type').value()
              orders['ordersNumber'] = formData.prop('order_number').value()
              orders['ordersDate'] = formData.prop('order_date').value()
              orders['personProfileId'] = personProfileId
      
              def cephData = ['personEduProfile':personEduProfile,'orders':orders]
      
              set_transient_variable('createComplexPayload', S(cephData, 'application/json'))

      bp nested entities 4

  3. В результаті виконання задачі, у виводі отримуємо сформований JSON, збережений до змінної createComplexPayload, що надалі використовуватиметься у бізнес-процесі.

    Приклад 5. Приклад. Сформований JSON-об’єкт, збережений до змінної 'createComplexPayload'
    {
      "personEduProfile": {
        "personProfileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      },
      "orders": {
        "ordersType": "string",
        "ordersNumber": "string",
        "ordersDate": "2022-02-16T13:33:30.660Z",
        "personProfileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
      }
    }

3.1.8. Моделювання Call Activity для підпису комплексного об’єкта системним ключем

Далі необхідно створити Call Activity для виклику глобального підпроцесу підпису даних системним ключем. Call Activity використовує змінну createComplexPayload, дані з якої передаються до підпроцесу для подальшого їх підпису.

В результаті виконання підпроцесу, викликаного у Call Activity, дані підписуються системним Ceph-ключем для перевірки системного підпису Фабрикою даних. Ключ зберігається до змінної transaction_system_signature_ceph_key.

  1. Змоделюйте елемент Call Activity.

  2. Перейдіть до панелі налаштувань справа та застосуйте делегат System digital signature. Для цього оберіть відповідний шаблон із каталогу (Open Catolog).

    Приклад налаштування делегата System digital signature наведено за посиланням.
  3. Виконайте подальші налаштування:

    • У полі Name вкажіть назву елемента — Підписати дані системним ключем.

    • У полі Input data вкажіть вхідні дані, які необхідно передати підпроцесу, що викликатиметься — ${createComplexPayload}.

    • У полі Output variable name введіть назву змінної, до якої буде записано системний Ceph-ключ — transaction_system_signature_ceph_key. Він потрібний для перевірки системного підпису у Фабриці даних.

      Ідентифікатор підпроцесу, що викликатиметься, передається у полі Called Element і має стале значення system-signature-bp. Ці та деякі інші налаштування "вшито" до шаблону з метою спрощення моделювання.

      bp nested entities 5

3.1.9. Моделювання сервісної задачі для створення декількох сутностей в рамках однієї транзакції

Далі дані використовуються у сервісній задачі "Збереження даних".

У задачі необхідно застосувати делегат для створення декількох сутностей у базі даних в рамках однієї транзакції (Create nested entities in data factory), використавши підписані дані (Payload) зі змінної ${createСomplexPayload}.

В рамках виконання задачі бізнес-процес:
  • надсилає підписані дані (${createComplexPayload}) до API-ендпоінту (ресурсу) nested-transaction-entity.

  • передає токен доступу до ресурсу.

  • передає у запиті КЕП користувача.

  • передає системний ключ зі змінної ${transaction_system_signature_ceph_key}.

Результат (відповідь) від API записуємо до змінної response.

  1. Змоделюйте нову задачу.

  2. Визначте її тип, натиснувши іконку ключа та обравши з меню пункт Service Task (сервісна задача).

  3. Перейдіть до панелі налаштувань справа та застосуйте делегат Create nested entities in data factory. Для цього оберіть відповідний шаблон із каталогу (Open Catalog).

    Приклад налаштування делегата Create nested entities in data factory наведено за посиланням.
  4. Виконайте подальші налаштування:

    • У полі Id вкажіть ідентифікатор сервісної задачі — createComplex.

    • У полі Name вкажіть назву задачі. Наприклад, Збереження даних.

    • У полі Resource вкажіть ресурс (API-ендпоінт), куди необхідно виконати запит — nested-transaction-entity.

      На рівні API ендпоінт виглядає наступним чином: /nested/<resource name>, де <resource name> — назва ресурсу. Тобто у полі Resource необхідно ввести значення, вказане після останньої косої риски (/).
    • У полі Payload введіть тіло запита — JSON-об`єкт, тобто дані зі змінної ${createComplexPayload}, які необхідно зберегти до Фабрики даних.

      Майте на увазі, що необхідно попередньо побудувати цей JSON-об`єкт, тобто payload, в рамках задачі скриптування.
    • У полі X-Access-Token вкажіть токен доступу до ресурсу.

      Токен доступу береться з АБО ініціатора (наприклад, ${initiator().accessToken}), АБО виконавця задачі (наприклад, ${completer('taskDefinitionId').accessToken}):

      • Якщо перед сервісною задачею у бізнес-процесі немає жодної користувацької задачі, використовуємо токен ініціатора процесу (initiator).

      • Якщо перед сервісною задачею є користувацька задача, використовуємо токен виконавця задачі (completer).

      Таким чином ми від імені користувача, який АБО запустив бізнес-процес, АБО виконав користувацьку задачу, створюємо сутності у базі даних.

    • У полі X-Digital-Signature-source вкажіть джерело цифрового підпису (КЕП), тобто передайте функції sign_submission() ID користувацької форми, де застосовували КЕП, — ${sign_submission('signPersonProfileActivity').signatureDocumentId}.

    • У полі X-Digital-Signature-Derived-source вкажіть джерело системного підпису, тобто змінну, з якої необхідно взяти системний ключ, — ${transaction_system_signature_ceph_key}.

    • У полі Result variable вкажіть назву змінної, в якій необхідно зберегти відповідь від API, — response.

      bp nested entities 6

  5. Виконайте Unlink шаблону, тобто від’єднайте шаблон від задачі, щоб побачити деталі його імплементації, що передзаповнюються автоматично з метою спрощення моделювання:

    • У полі Implementation визначено тип — Delegate Expression.

    • У полі Delegate Expression визначено назву делегата — $dataFactoryConnectorNestedCreateDelegate.

      bp nested entities 7

      bp nested entities 8

В результаті виконується одна транзакція, що записує комплексний об’єкт, який складається із декількох вкладених об’єктів (сутностей): personEduProfile та orders, до відповідних БД-таблиць person_edu_profile та order, які посилаються за зовнішнім ключем personProfileId до таблиці person_profile.

Таким чином маємо виконану транзакцію одночасно до 3-х таблиць у базі даних. Рівень API Фабрики даних автоматично розкладає дані, що надходять у тілі запита, за різними таблицями.

  1. Продовжіть бізнес-процес за необхідності або завершіть.

3.2. Використання комплексного об’єкта у бізнес-процесі

Розглянемо приклад подальшого використання комплексного об’єкта у цьому ж бізнес-процесі, дані якого були збережені до бази даних в рамках попередньої транзакції.

3.2.1. Моделювання сервісної задачі "Get transaction"

Для подальшого використання комплексного об’єкта та його збережених сутностей, необхідно спочатку отримати ID транзакції, в рамках якої був записаний цей об’єкт.

Для цього потрібно надіслати GET-запит на відповідний ендпоінт Get transaction, вказавши ID транзакції зі змінної response останньої сервісної задачі — ${response.value.responseBody.prop('id').value()}, а також токен доступу до ресурсу.

bp nested entities 9

  1. Змоделюйте нову задачу.

  2. Визначте її тип, натиснувши іконку ключа та обравши з меню пункт Service Task (сервісна задача).

  3. Перейдіть до панелі налаштувань справа та застосуйте делегат Read entity from data factory. Для цього оберіть відповідний шаблон із каталогу (Open Catalog).

  4. Виконайте подальші налаштування:

    • У полі Name вкажіть назву задачі. Наприклад, Get transaction.

    • У полі Resource вкажіть ресурс (API-ендпоінт), куди необхідно виконати запит — transaction.

      На рівні API ендпоінт виглядає наступним чином: /<resource name>, де <resource name> — назва ресурсу. Тобто у полі Resource необхідно ввести значення, вказане після косої риски (/).
    • У полі Resource id введіть ID транзакції зі змінної response останньої сервісної задачі — ${response.value.responseBody.prop('id').value()}, що необхідно передати до Фабрики даних.

    • У полі X-Access-Token вкажіть токен доступу до ресурсу — ${completer('signPersonProfileActivity').accessToken}.

      Токен доступу береться з АБО ініціатора (наприклад, ${initiator().accessToken}), АБО виконавця задачі (наприклад, ${completer('taskDefinitionId').accessToken}):

      • Якщо перед сервісною задачею у бізнес-процесі немає жодної користувацької задачі, використовуємо токен ініціатора процесу (initiator).

      • Якщо перед сервісною задачею є користувацька задача, використовуємо токен виконавця задачі (completer).

      Таким чином ми від імені користувача, який АБО запустив бізнес-процес, АБО виконав користувацьку задачу, виконуємо пошук сутності у базі даних.

    • У полі Result variable вкажіть назву змінної, в якій необхідно зберегти відповідь від API, — txResponse.

      bp nested entities 10

3.2.2. Моделювання сервісної задачі "Пошук даних за наказом"

Після отримання ID транзакції в результаті виконання попередньої задачі, ми можемо виконати пошук за певними даними, що збереглися в рамках такої транзакції (тут — за наказом, тобто об’єктом orders).

Для цього потрібно надіслати GET-запит на відповідний ендпоінт orders, вказавши ID транзакції зі змінної txResponse останньої сервісної задачі — ${txResponse.value.responseBody.prop('ordersId').value()}, а також токен доступу до ресурсу.

  1. Змоделюйте нову задачу.

  2. Визначте її тип, натиснувши іконку ключа та обравши з меню пункт Service Task (сервісна задача).

  3. Перейдіть до панелі налаштувань справа та застосуйте делегат Read entity from data factory. Для цього оберіть відповідний шаблон із каталогу (Open Catalog).

  4. Виконайте подальші налаштування:

    • У полі Name вкажіть назву задачі. Наприклад, Пошук даних за наказом.

    • У полі Resource вкажіть ресурс (API-ендпоінт), куди необхідно виконати запит — orders.

      На рівні API ендпоінт виглядає наступним чином: /<resource name>, де <resource name> — назва ресурсу. Тобто у полі Resource необхідно ввести значення, вказане після косої риски (/).
    • У полі Resource id введіть ID транзакції зі змінної txResponse останньої сервісної задачі — ${txResponse.value.responseBody.prop('ordersId').value()}, що необхідно передати до Фабрики даних.

    • У полі X-Access-Token вкажіть токен доступу до ресурсу — ${completer('signPersonProfileActivity').accessToken}.

      Токен доступу береться з АБО ініціатора (наприклад, ${initiator().accessToken}), АБО виконавця задачі (наприклад, ${completer('taskDefinitionId').accessToken}):

      • Якщо перед сервісною задачею у бізнес-процесі немає жодної користувацької задачі, використовуємо токен ініціатора процесу (initiator).

      • Якщо перед сервісною задачею є користувацька задача, використовуємо токен виконавця задачі (completer).

      Таким чином ми від імені користувача, який АБО запустив бізнес-процес, АБО виконав користувацьку задачу, виконуємо пошук сутності у базі даних.

    • У полі Result variable вкажіть назву змінної, в якій необхідно зберегти відповідь від API, — ordResponse.

      bp nested entities 11

  5. Продовжіть бізнес-процес за необхідності або завершіть.

4. Імплементація на рівні API

Для окремого типу запита використовують окремий делегат. Тобто в загальному випадку є REST-контролер, який підтримує певні типи запитів (методи): POST, GET, PUT та DELETE. Для кожного методу — свій делегат.

Для ресурсу /nested/<resource name> та делегата $dataFactoryConnectorNestedCreateDelegate використовується лише метод PUT.

І хоча метод PUT зазвичай використовується для оновлення записів, та у нашому випадку PUT може як створити сутність, так і оновити її, в залежності від того, які параметри ми передаємо у запиті:

  • Якщо необхідно створити сутність, то ми НЕ передаємо параметр <table_primary_key>_id у тілі запита. Наприклад, orders_id.

  • Якщо необхідно оновити сутність, то ми включаємо параметр <table_primary_key>_id у тіло запита. Наприклад, orders_id.

Приклад 6. Приклад. Тіло запита
{
  "personEduProfile": {
    "personProfileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  },
  "orders": {
    "ordersType": "string",
    "ordersNumber": "string",
    "ordersDate": "2022-02-16T13:33:30.660Z",
    "personProfileId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
  }
}
Приклад 7. Приклад відповіді від API-сервісу:
HTTP-код:
200 OK
Тіло відповіді:
{
   "id":"d1394f5d-5274-4831-90ac-0dfdb6d7bd35"
}

Отже, нема потреби створювати окремий контролер із різними ендпоінтами для різних цілей. Достатньо використовувати один окремий ендпоінт, який матиме можливість приймати й правильно опрацьовувати комплексний JSON-об’єкт, в якому одночасно передаватимуться всі необхідні дані користувача та його налаштування, і параметри якого можна буде зберегти до різних таблиць в одній БД-транзакції.


1. Транзакція — група послідовних операцій із базою даних, яка є логічною одиницею роботи з даними. Транзакція може бути виконана або цілком і успішно, дотримуючись цілісності даних і незалежно від інших транзакцій, що ідуть паралельно, або не виконана зовсім.