Архитектура адаптеров
Адаптер ESB
Адаптер ESB – это непосредственный участник обмена информацией между приложениями. Он может принимать участие в обмене как отправитель, так и получатель, в зависимости от настройки модели.
Архитектура адаптеров
Основой всех адаптеров являются RestierService, сервис адаптера, сервис отслеживания изменений и API.
Часть сервисов к адаптеру подключаются при помощи json-файла. В данном файле должны быть подключены как сервисы,
которые являются общими для всех адаптеров, так и сервисы, которые дифференцированы для каждого адаптера.
Примером такого сервиса является адаптер-сервис. Он подключен в разделе Modules
json-файла следующим образом:
{
"AssemblyQualifiedName": "Galaktika.ESB.Adapter.XAF.XafAdapterService, Galaktika.ESB.Adapter.AMM",
"AdapterId": "AMM_01"
}
Поле AssemblyQualifiedName
состоит из двух частей. Первая часть содержит полная имя класса, который подключается, а вторая – имя библиотеки.
Адаптер-сервис должен быть унаследован от ESBServiceReg, чтобы в адаптере были доступны все общие сервисы для адаптеров Галактики ESB. Помимо общих сервисов адаптер сервис в XAF осуществляет регистрацию OData-сервиса и реализует старт приложения, при помощи которого в последующем будут построены метаданные. Также необходим класс адаптера (в случае XAF-приложения это XafAdapter), который унаследован от BaseAdapter. Он содержит информацию о том, к какому типу относится адаптер, а также имя запускаемой информационной системы. API адаптера осуществляет управление различными сервисами для работы с OData и ее метаданными. В API также необходима реализация IQueryable для бизнес-объектов. Сервис отслеживания изменений создан для того, чтобы обнаруживать изменения, которые происходят в базе, и отправлять их в шину при помощи сервиса публикации (IPublisherService), который для всех адаптеров является общим. RestierService осуществляет работу с ESB-сессией, которая помогает манипулировать данными. При помощи «рестиера» можно осуществлять запросы к БД и выполнять бизнес-операции, хранящиеся в метаданных.
Разработка адаптера
Разработка API для OData
Изначально при разработке адаптера необходимо описать API для OData. Общую информацию по созданию API для OData можно посмотреть в документации RESTier.
Разработка API зависит от системы ORM. Необходимым условием в реализации API для адаптера является реализация IQueryable<T>
.
Если в случае EntityFramework’a достаточно наследования от EntityFrameworkApi<@EFContextName>
, то для других приложений необходимо наследование от ApiBase и реализация своего IQueryable<T>
.
Так, в адаптерах для XAF-приложений реализован следующий метод:
public IQueryable<T> GetQueryableSource<T>()
{
return new XpoQueryProxy<T>(Session.Query<T>());
}
Также, для поддержания какой-либо специфики информационной системы имеется возможность переопределения сервисов для API либо добавление своих сервисов для реализации специфических задач. Осуществляется это в методе ConfigureApi, который возвращает IServiceCollection. На примере XAF-адаптеров метод выглядит следующим образом:
Таким образом, например, в сервисе XpoQueryExpressionExpander используется метод GetQueryableSource<T>
для корректной работы с запросами к OData.
Аналогично в API подключен XafModelBuilder, который отвечает за построение метаданных для OData.
Построение метаданных для Odata
Метаданные OData представлены при помощи EDM (Entity Data Model). Данная модель состоит из сущностей (Entity), которые представлены сущностными типами (Entity Type) – они являются представлениями бизнес объектов с соответствующими свойствами и ключами. Комплексных типов (Complex Type) – структурированные типы, которые также состоят из набора свойств, но без ключа. Также сущности могут иметь ссылки на другие сущности в виде ассоциаций, т.е. ссылочных свойств типа другой сущности либо свойств-списков с типом другой сущности. В итоге сущности формируются в энтити сеты (Entity Set) и складываются в один общий контейнер – EntityContainer. Более подробную информацию можно посмотреть в документации по OData. Построение метаданных осуществляется при помощи ModelBuilder, который на основании бизнес объектов информационной системы строит EDM модель, которая и содержит в себе метаданные информационной системы.
Основная структура ModelBuilder
довольно проста. Необходимо унаследоваться от абстрактного класса EsbModelBuilder и реализовать два абстрактных метода:
• FillInQueue
• GenerateKeys.
Метод FillInQueue возвращает список типов ClassToGenerate.
ClassToGenerate – это тип, который содержит в себе всю необходимую информацию о бизнес объекте для включения его в EDM модель.
Соответственно в методе FillInQueue осуществляется заполнение списка с типами ClassToGenerate на основании бизнес объектов информационной системы.
В XAF-адаптере это выглядит следующим образом:
На основании этого сгенерированного списка и будет построена EDM-модель. Однако необходимо еще реализовать метод GenerateKeys, в котором в сущность добавляется ключевое поле. Сделано это для того, что в каждой информационной система может быть различные способы поиска и установки ключей. В целом реализации этих двух абстрактных методов достаточно для корректной работы ModelBuilder, однако, в случае необходимости можно переопределить методы для генерации отдельных свойств, как примитивных, так и ссылочных в зависимости от нужд информационной системы. Так, в XAF-адаптерах переопределены методы для генерации ссылочных свойств с учетом специфики Dev Express.
Сервис для манипуляции с данными
В настоящий момент за манипуляции с данными в ESB-адаптерах отвечает IEsbContext, объект которого хранится в сессии ESB-адаптера. Управление сессией осуществляет RestierService. На примере XAF-адаптеров общая архитектура по манипуляции данными выглядит следующим образом:
Непосредственно манипуляции с данными на низком уровне адаптера осуществляет класс, реализующий интерфейс IEsbContext:
Как видно из списка методов, объект, реализующий интерфейс IESBContext, имеет следующие возможности: • получение сущности либо сущностей; • получение ключа сущности; • удаление сущности; • сохранение внесенных изменений. На примере XAF-адаптеров таким классом является XafContext. Внутри себя он хранит логику по манипуляции с данными, связанную с конкретной информационной системой адаптера. В случае XAF манипуляции осуществляются при помощи ObjectSpace DevExpress, если работа осуществляется через EntityFramework, то это DbContext. В других информационных системах для манипуляции используются их особенности. Для того чтобы адаптер определил IEsbContext, API-класс адаптера должен реализовывать интерфейс IEsbContextApi. Сам интерфейс выглядит следующим образом:
public interface IEsbContextApi
{
IEsbContext CreatEsbContext(ISession session);
}
Реализация указанного интерфейса поможет рестиер-сервису создать объект, реализующий IESBContext конкретно под определенный адаптер с его ORM системой. Объект IEsbContext хранит в себе сессия (ISession) адаптера ESB и, управляя IEsbContext, осуществляет манипуляции с данными. Все манипуляции происходят в рамках одной ESB-сессии (она же ISession). Управление сессией осуществляется при помощи RestierService и, в связи с тем, что сессии зависят от информационной системы, методы создания сессии (CreateSession) и выполнения какого-либо метода в ней (ExecuteInSession) должны быть переопределены в каждом адаптере отдельно. Метод создания сессии позволяет создать сессию и в последствии использовать ее для различных манипуляция с данными. При использовании метода следует быть осторожным, так как в этом случае вопрос о закрытии сессии решается разработчиком. Если требуется осуществить небольшую операцию с данными, лучше воспользоваться ExecuteInSession, после выполнения чего сессия самостоятельно будет закрыта. Помимо указанных выше функций RestierService возвращает версии приложения и конкретного адаптера.
Отслеживание изменений
Рассмотрим сервис отслеживания изменений на примере XAF-адаптеров. Этот сервис, как и другие основные сервисы адаптера, подключаются в json-файле. Для этого в json-файл в секции «Modules» необходимо добавить новый модуль, в XAF-адаптерах это выглядит следующим образом:
"Modules": [
{
"AssemblyQualifiedName": "Galaktika.ESB.Adapter.XAF.XafDbUpdatesService, Galaktika.ESB.Adapter.AMM",
"DbUpdateCheckIntervalSec": 15,
"MaxRecordChangesCountInChunk": 20
}
Для включения и отключения сервиса отслеживания адаптеров XAF-приложений используется параметр IsCheckUpdates типа boolean.
Поле DbUpdateCheckIntervalSec
обозначает интервал, в который будет происходить проверка на наличие новых изменений в базе данных.
Поле MaxRecordChangesCountInChunk
определяет количество записей, которое будет отправлено в одном сообщении за раз.
Соответственно, при написании сервиса отслеживания изменений необходимо включать указанные выше опции для более гибкого управления сервисом отслеживания изменений.
Для корректной работы сервис отслеживания изменений должен реализовывать интерфейсы IDbUpdatesParserService и IDbUpdatesSerice. Выглядят они следующим образом:
Реализация метода GetTrackingTables позволяет на основании списка TrackingType вернуть json-массив со списком таблиц для отслеживания. TrackingType – это ESB-тип, который хранит в себе информацию про отслеживаемые типы адаптера, т.е. бизнес объекты. Json-объекты в массиве как минимум могут содержать в себе информацию об имени типа объекта (поле Name), информацию о том, включено ли для этого типа отслеживание (поле IsTrackingEnabled) и имя ключевого поля (поле PrimaryKey), а также любую другую информацию, зависящую от информационной системы, которая необходима для установки списка отслеживаемых типов.
Поля DbUpdateCheckIntervalSec
и MaxRecordChangesCountInChunk
должны возвращать значения, полученные из сеттингов.
Метод UpdateTrackingTables получает массив json-объектов каждый из которых содержит в себе необходимую информацию, которая была получена из метода GetTrackingTypes и служит для установки типов информационной системы для отслеживания.
В случае XAF-адаптеров в этом методе осуществляется запрос к базе данных с установкой об отслеживании всех типов, переданных в метод.
Метод CheckTracking проверяет доступно ли отслеживание в данном адаптере. В случае если отслеживание недоступно, работу сервиса следует остановить. В зависимости от платформы метод может работать по своей собственной логике, например, в ERP-адаптере также анализируется включена ли журнализация, так как всё отслеживание построено на формировании журнала изменений в ERP.
Свойство DbTables содержит в себе список отслеживаемых таблиц.
Основным методом сервиса является CheckDbUpdates. Он реализуется в зависимости от платформы. Внутри метода происходит обнаружение всех изменений в базе данных и их непосредственная отправка. Метод должен работать асинхронно с учетом настройки интервала, полученной из сеттингов файла json.
Также для полноценной работы сервиса необходимо класс сервиса унаследовать от ServiceBase, что позволит иметь доступ ко всем основным сервисам адаптера, а в частности доступ к сервису IPublisherService, который непосредственно и осуществляет отправку данных. Поэтому измененные данные следует преобразовывать в соответствующий формат в сервисе отслеживания изменений с учетом сигнатуры методов сервиса публикаций.