Рендеринг. Работа с потоком выполнения через REST¶
Создание и изменение данных происходят в системе атомарно. Подробнее о потоках выполнения можно прочитать в статье о потоках выполнения.
Запрос на сервер¶
Для работы через рест используется POST /universe-backend/api/v2/data/atomic
Структура запроса содержит блок payload с коллекцией идентификаторов модулей, которые обработают запрос
{
"payload": {
"org.unidata.mdm.rest.v2.data": {..},
"MODILE_ID": {...},
}
}
Рассмотрим на примере реестра ree
с одним атрибутом id
, связью link
на себя и назначенным классификатором clsf
. При работе в черновике записи, если заполнена запись и запись классифицирована, на сервер будет уходить запрос с двумя MODULE_ID
.
{
"payload": {
"org.unidata.mdm.rest.v2.data": {},
"com.unidata.mdm.rest.v1.classifiers": {}
}
Значению ключа org.unidata.mdm.rest.v2.data
соответствует объект org.unidata.mdm.rest.v2.data.ro.records.UpsertRequestRO
.
Обработка запроса на сервере¶
Рассмотрим, что происходит в процессе обработки атомик-запроса.
RenderingFragment¶
Для описания фрагмента минимально необходимо задать идентификатор, отображаемое имя и описание, входной и выходной тип.
Поле |
Обязательность |
Описание |
---|---|---|
id |
да |
идентификатор фрагмента |
name |
да |
отображаемое имя фрагмента |
description |
да |
отображаемое описание фрагмента |
InputType |
да |
какой класс обрабатывает фрагмент |
OutputType |
да |
возвращаемый класс |
moduleId |
нет |
идентификатор модуля |
ExecuteEarly |
нет |
задание приоритета выполнения, true - максимальный |
ExecuteOnNoInput |
нет |
выполнение запроса, даже если он пустой |
RenderByModuleId |
нет |
обработчик контекста будет использовать поле moduleId вместо id |
Пример конфигурации фрагмента. Фрагмент обрабатывает UpsertRequestRO.class
, результат обработки будет типа UpsertRecordResultRO
. Фрагмент соответствует модулю DataRestModule
и будет выполнен с максимальным приоритетом.
new RenderingFragment("fragment_id")
.withDisplayName(() -> TextUtils.getText("fragment_name"))
.withDescription(() -> TextUtils.getText("fragment_description"))
.withModuleId(DataRestModule.MODULE_ID)
.withExecuteEarly(true)
.withRenderByModuleId(true)
.withInputType(UpsertRequestRO.class)
.withOutputType(UpsertRecordResultRO.class);
org.unidata.mdm.system.type.rendering.RenderingType¶
RenderingType задает контракт для коллекции фрагментов, которые должны быть обработаны, способ преобразования и класс результата.
Допустимо использовать пустые входные тип NullInputCollector
, NullOutputContainer
.
RenderingType<>(RECORD_ATOMIC_UPSERT_TYPE, UpsertRequestContextBuilder.class, UpsertRecordDTO.class)
.withDisplayName(() -> TextUtils.getText("_name"))
.withDescription(() -> TextUtils.getText("_description"))
.withFragments(DataRestRenderingFragments.RECORD_UPSERT_FRAGMENT);
RenderingExtension¶
RenderingExtension - группировка RenderingType
, которая используется в аннотации и позволяет вызывать типизировать рендеринг.
@RenderingRef(DataRestFunctionalExtensions.DATA_RENDERING_V2_NAME)
RenderingInstance dataRenderingInstance;
RenderingExtension DATA_V2_RENDERING =
new RenderingExtension(DATA_RENDERING_V2_NAME)
.withDisplayName(() -> TextUtils.getText(DataRestModule.MODULE_ID + ".rendering.extension.name"))
.withDescription(() -> TextUtils.getText(DataRestModule.MODULE_ID + ".rendering.extension.description"))
.withRenderingTypes(DataRestRenderingTypes.values())
Регистрация в методе Module:
В интерфейсе ``org.unidata.mdm.system.type.module.Module`` есть метод getFunctionalExtensions()
@Override
public FunctionalExtension[] getFunctionalExtensions() {
return new FunctionalExtension[] { DataRestFunctionalExtensions.DATA_V2_RENDERING };
}
После старта модуля(реализация AfterModuleStartup) в renderingInstance добавляется метод рендеринга:
renderingInstance.inputAdd(
DataRestRenderingTypes.RECORD_ATOMIC_UPSERT,
DataRestRenderingFragments.RECORD_UPSERT_FRAGMENT, this::renderUpsertInput);
var rcb = RenderingContext.builder(DataRestRenderingTypes.RECORD_ATOMIC_UPSERT)
.collectorSupplier(UpsertRequestContext::builder)
.executionFunction(b -> dataRecordsService.upsertRecord(b.build()));
return renderRequest(renderingInstance, DataRestRenderingTypes.RECORD_ATOMIC_UPSERT, rcb, req, new AtomicDataUpsertResultRO());
RestRenderingSupport¶
Пример использования:
var rcb = RenderingContext.builder(DataRestRenderingTypes.RECORD_ATOMIC_UPSERT)
.collectorSupplier(UpsertRequestContext::builder)
.executionFunction(b -> dataRecordsService.upsertRecord(b.build()));
return renderRequest(renderingInstance, DataRestRenderingTypes.RECORD_ATOMIC_UPSERT, rcb, req, new AtomicDataUpsertResultRO());
где метод renderRequest
предоставляется RestRenderingSupport
и преобразует объект из rest запроса во внутренние контексты, выполняет соответствующий контекст потока выполнения и преобразует результат потока выполнения в заданный объект new AtomicDataUpsertResultRO()
.