Skip to content

Latest commit

 

History

History
147 lines (100 loc) · 9.64 KB

rest_api_v2_ex_json_transformations.adoc

File metadata and controls

147 lines (100 loc) · 9.64 KB
Примеры версионирования модели данных
Атрибут сущности переименован

Предположим, атрибут oldNumber сущности sales$Order был переименован в newNumber, а атрибут date был переименован в deliveryDate. В этом случае конфигурация трансформации будет выглядеть следующим образом:

link:../../../../../source/rest/rest-transform-attr-renamed-config.xml[role=include]

Если клиентскому приложению необходимо работать со старой версии сущности sales$Order, то приложение должно передать значение версии модели данных в параметре URL modelVersion:

http://localhost:8080/app/rest/v2/entities/sales$Order/c838be0a-96d0-4ef4-a7c0-dff348347f93?modelVersion=1.0

Будет возвращен следующий результат:

link:../../../../../source/rest/rest-transform-attr-renamed-response.json[role=include]

Видим, что ответ содержит атрибуты oldNumber и date, хотя сущность в последней версии приложения уже имеет переименованные атрибуты newNumber и deliveryDate.

Имя сущности изменено

Предположим, что в одном из следующих релизов приложения имя сущности sales$Order также было изменено. Новое имя сущности теперь sales$NewOrder.

Конфиг трансформации для версии 1.1 выглядит так:

link:../../../../../source/rest/rest-transform-entity-name-changed-config.xml[role=include]

В дополнение к конфигу из предыдущего примера здесь появился атрибут oldEntityName. Он описывает имя сущности, действительное для версии модели данных 1.1. Атрибут currentEntityName описывает текущее имя сущности.

Хотя сущность с именем sales$Order более не существует, следующий запрос будет работать:

http://localhost:8080/app/rest/v2/entities/sales$Order/c838be0a-96d0-4ef4-a7c0-dff348347f93?modelVersion=1.1

Контроллер REST API поймет, что поиск должен быть осуществлен среди экземпляров сущности sales$NewOrder, и после того, как сущность с заданным ID будет найдена, имя сущности и имя атрибута newNumber будут заменены в JSON:

link:../../../../../source/rest/rest-transform-entity-name-changed-response.json[role=include]

Клиентское приложение также может использовать старую версию модели данных для создания или изменения сущности.

Этот POST запрос использует старое имя сущности и имеет JSON в старом формате в теле запроса, однако, запрос будет работать:

http://localhost:8080/app/rest/v2/entities/sales$Order

link:../../../../../source/rest/rest-transform-entity-name-changed-response.json[role=include]
Атрибут должен быть удален из JSON

Иногда может возникнуть ситуация, когда в сущность был добавлен новый атрибут, но клиент, работающий со старой версией модели данных, не должен получать этот атрибут при запросе к сущности. В этом случае стандартный JSON трансформер может удалить атрибут из результата.

Конфиг трансформации для данного случае выглядит примерно так:

link:../../../../../source/rest/rest-transform-attr-removed-config.xml[role=include]

Описание трансформации здесь содержит тег toVersion с вложенной командой removeAttribute. Это значит, что при выполнении трансформации из текущей версии модели данных к определенной версии (например, при запросе списка сущностей) атрибут discount будет удален из JSON.

Если выполнить запрос к REST API без атрибута modelVersion, то атрибут discount будет возвращен.

http://localhost:8080/app/rest/v2/entities/sales$Order/c838be0a-96d0-4ef4-a7c0-dff348347f93

link:../../../../../source/rest/rest-transform-attr-removed-response-2.json[role=include]

Если указать modelVersion в запросе, то атрибут discount будет удален:

http://localhost:8080/app/rest/v2/entities/sales$Order/c838be0a-96d0-4ef4-a7c0-dff348347f93?modelVersion=1.1

link:../../../../../source/rest/rest-transform-attr-removed-response.json[role=include]
Использование кастомных трансформеров

Вы также можете создать и зарегистрировать свой собственный трансформер JSON. В качестве примера рассмотрим следующую ситуацию.

Сущность sales$OldOrder была переименована в sales$NewOrder. В сущности имеется поле orderDate с типом дата. В старой версии сущности это поле содержало часть со временем, в новой версии сущности часть со временем в поле отсутствует. Клиент REST API, запрашивающий сущность со старой версией модели данных 1.0 ожидает, что дата будет иметь часть со временем. Получается, что JSON трансформер должен изменить значение в JSON.

Так будет выглядеть конфигурация трансформации для данного случая:

link:../../../../../source/rest/rest-transform-custom-config.xml[role=include]

Конфигурация содержит элемент custom с вложенными элементами toVersion и fromVersion. Эти элементы содержат ссылки на бины, т.е. кастомный трансформер должен быть зарегистрирован как Spring bean.

Важная деталь: в кастомном трансформере возможно потребуется использовать бин платформы RestTransformations (он предоставляет доступ к трансформерам для других сущностей). Но бин RestTransformations зарегистрирован в Spring контексте сервлета REST API, а не в главном контексте веб-приложения. Это значит, что бин кастомного трансформера также должен быть зарегистрирован в контексте REST API.

Как это сделать. Во-первых, создайте файл rest-dispatcher-spring.xml в модуле web или portal (например в пакете com.company.test).

Затем зарегистрируйте этот файл в файле свойств app.properties соответствующего модуля.

cuba.restSpringContextConfig = +com/company/test/rest-dispatcher-spring.xml

Файл rest-dispatcher-spring.xml должен содержать определения бинов для кастомных трансформеров:

link:../../../../../source/rest/rest-transform-dispatcher-spring.xml[role=include]

Исходный код бина sales_OrderJsonTransformerToVersion:

link:../../../../../source/features/OrderJsonTransformerToVersion.java[role=include]

Данный трансформер находит элемент orderDate в JSON и изменяет значение элемента, добавляя к нему часть со временем.

Когда сущность sales$Order будет запрошена с версией модели данных 1.0, то JSON результат будет содержать сущность, поле orderDate которой содержит часть со временем, хотя текущий тип поля сущности - дата без времени.

Несколько слов о кастомных трансформерах. Они должны реализовывать интерфейс EntityJsonTransformer. Вы также можете унаследоваться от класса AbstractEntityJsonTransformer и переопределить его метод doCustomTransformations. Класс AbstractEntityJsonTransformer содержит функциональность стандартных трансформеров.