7.10. Руководство по разработке интеграционных маршрутов

7.10.1. Назначение и описание.

7.10.1.1. Назначение

Частью приложения является интеграционный сервис, предназначеный для сопровождения логики, исполняемой на сервере приложения или интеграционном сервере. Интеграционный сервис приложения является модульным и расширяемым решением.

Основой сервиса является маршрут. Маршрут - поток исполняемой логики, позволяющий описывать исполнение процесса обработки данных («сообщений») или взаимодействие с внешними системами, такими как:

  • Веб сервисы
  • Базы данных
  • BMP системы
  • Очереди сообщений
  • и др..
Интеграционные маршруты могут быть подключены как к запросам приложения к адаптерам, так и к ответам адаптеров на запросы.
Подключение маршрутов к запросам осуществляется с помощью маппинга маршрута к запросам системы к адаптерам (см: Раздел 5.19.5.5).
Список требуемых внешних маршрутов динамически строится в зависимости от схемы, метода и типа запроса.
Последовательность выполнения внешних маршрутов определяется приоритетом маршрута в маппинге.

7.10.1.2. Описание структуры маршрута

7.10.1.2.1. Элементы маршрута

Маршрут состоит из следующих элементов:

Прием потока обработки данных (from)
Элемент маршрута, описывающий начало маршрута, источник данных для получения данных.
По умолчанию данные поступают из бекенда, в ходе исполнения процесса пользователями. Bдентификатор маршрута, соответствует идентификатору маршрута в системе.
Передача потока обработки данных (to)
Элемент маршрута, описывающий передачу данных внешней системе или в другой маршрут обработки данных.
Процесс (process)
Элемент описывает использование интерфейса Processor для обработки данных в ветке потока обработки данных.
Java Bean (bean)
Элемент описывает использование JavaBean для обработки данных в ветке потока обработки данных.
Установка тела сообщения (setBody)
Элемент маршрута, позволяющий изменить тело сообщения (например сформировать запрос к внешней системе или изменить значение атрибутов для сохранения на адаптере.
Установка заголовка сообщения (setHeader)
Элемент маршрута, позволяющий установить заголовок сообщения
Удалить заголовок (removeHeader)
Элемент маршрута, позволяющий удалить заголовок сообщения
Удалить заголовки (removeHeaders)
Элемент маршрута, позволяющий удалить заголовки сообщения по шаблону
Преобразование (transform)
Элемент transform предназначен для трансформации тела сообщения (изменения значений атрибутов, изменения тела сообщения для передачи внешней системе.
Выбор (choice)
Элемент, позволяющий организовать ветвление в процессе обработки данных.
Условие (when)
Элемент, описывающий одну из веток ветвления потока обработки по условию.
Иначе (otherwise)
Элемент, описывающий альтернативную ветку потока, в случае, если условия ветвления не были выполнены.
Ошибка (onException)
Элемент маршрута, описывающий процесс обработки данных в случае появления ошибки.

Предупреждение

Классы JavaBeans и Processors, используемые в маршрутах должны быть размещены на сервере. Соответствующие им компоненты маршрута должны быть настроены в реестре компонентов (см: Раздел 5.20).

7.10.1.2.2. Описание маршрута в конфигурационной базе

Конфигурации маршрутов хранятся в формате JSON в таблице ROUTE конфигурационной базе приложения.
Параметры запуска внешнего маршрута, такие как схема, тип, метод, приоритет, а также статус и синхроность/ассинхроность, хранятся в таблице ROUTE_MAPPING.
Конфигурации компонентов реестра хранятся в таблице ENDPOINTS.
Таблица ROUTE имеет следующие поля:
  • id – идентификатор маршрута;
  • tenant_id – идентификатор tenant;
  • definition – описание маршрута в формате JSON;
  • modify_date – дата последнего изменения маршрута;
  • status – статус маршрута. Данный параметр позволяет включать/отключать маршрут глобально в рамках данного приложения.
Таблица ROUTE_MAPPING имеет следующие поля:
  • id – идентификатор маршрута;
  • tenant_id – идентификатор tenant;
  • schema_id – идентификатор схемы запроса;
  • method – метод запроса (GET, POST);
  • type – тип маршрута, определяющий принадлежность к преинтерсептору или постинтерсептеру ;
  • priority – приоритет маршрута в списке маршрутов данного запроса;
  • route_id – ссылка на описание маршрута в таблице ROUTE;
  • status – статус, позволяющий включать или отключать маршрут в рамках обработки для данного типа запроса;
  • async – параметр, определяющий синхронность/асинхронность выполнения маршрута.

Таблица ENDPOINTS имеет следующие поля: * id– идентификатор компонента; * tenant_id – идентификатор tenant; * name - имя компонента; * type -тип компонента; * definition - описание компонента; * status - статус компонента; * modify_date – дата последнего изменения ;

7.10.1.3. Описание структуры сообщения

По маршруту обрабатываются сообщения. Сообщение состоит из:

Заголовки (Headers)
Описываются параметры сообщения.
Параметры запроса к адаптеру описаны в заголовке requestParams.
Тело сообщения (Body)
Описывается тело сообщения, например перечень атрибутов записи.

7.10.2. Правила формирования JSON описания маршрута.

7.10.2.1. Структура JSON маршрута

JSON описание маршрута используется для построения XML описания на языке Apche Camel DSL.

При этом JSON представляет собой усеченную версию описания маршрута, в которой отсутствуют некоторые атрибуты и вершины. Необходимые недостающие вершины автоматически добавляются в процессе трансляции из JSON в XML. Таким образом, процессе трансляции, к создаваемому внешнему маршруту будет добавлен аттрибут идентификатора маршрута, и вершина from, которые отсутствуют в JSON, но информация о которых приходит из Базы Данных при получении описания маршрута.

JSON описание должно содержать всю необходимую информацию о маршруте, расположенную после вершины from. Пример JSON описания внешнего маршрута приведен ниже:

{"route":
 [{"setHeader":{"name":"RT000000000000", "type":"constant", "value":"This text1 added by async Enriching Route RT000000000000"}},
 {"removeHeader":{"name":"RT000000000000"}},
 {"setHeader":{"name":"RT000000000000", "type":"constant", "value":"This text2 added by async Enriching Route RT000000000000"}},
 {"setHeader":{"name":"currentTime", "type":"groovy", "value":"new java.util.Date().getTime()/1000"}},
 {"to":{"uri":"log:ru.igtel", "options":{"level":"WARN","showHeaders":"true","showException":"false","showCaughtException":"false"}}},
 {"to":{"uri":"sql:SELECT * FROM route_mapping?dataSource=#postgresSQL"}},
 {"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}},
 {"setBody":{"type":"constant", "value":"Test Body"}},
 {"to":{"uri":"http://webservice:8080/wsdl/ExtSys_SAES2_MI.wsdl?httpMethod=GET"}},
 {"transform":{"type":"simple", "value":"<out>${body}</out>"}},
 {"to":{"uri":"log:ru.igtel", "options":{"level":"WARN","showHeaders":"true","showException":"false","showCaughtException":"false"}}},
 {"choice":[
 {"when":[    {"type":"groovy","condition":"request.headers['RT000000000000'] == null"},
 {"setHeader":{"name":"RT000000000000C1", "type":"constant", "value":"This header was added by the route RT000000000000C1 condition 1"}},
 {"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}]},
 {"when":[    {"type":"groovy","condition":"request.headers['RT000000000000'] != null"},
 {"setHeader":{"name":"RT000000000000C1", "type":"constant", "value"="This header was added by the route RT000000000000C1 condition 2"}},
 {"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}]},
 {"otherwise":[
 {"setHeader":{"name":"RT000000000000C1", "type":"constant", "value":"This header was added by the route RT000000000000C1 condition otherwise"}},
 {"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}]}]},
 {"onException": [    {"exception":"java.lang.NullPointerException"},     {"setHeader":{"name":"RT000000000000", "type":"constant", "value":"This header was added by the exception handler"}},    {"to":{"uri":"log:ru.igtel", "options":{"level":"ERROR","showHeaders":"true","showException":"true","showCaughtException":"true"}}}
 ]}
 ]
 }

Примечание

В теле маршрута можно передать XML описание маршрута, для этого XML должен быть преобразован в JSON строку. Тело запроса должно содержать только XML.

Прмер такой строки приведен ниже:

"<route id=\"RT000000000001\" xmlns=\"http://camel.apache.org/schema/spring\"><from uri=\"direct:RT000000000001\"/><setHeader headerName=\"RT000000000001\"><constant>........</route>"

JSON описание маршрута должно начинаться с корневого элемента “route”.

Далее элемент “route” содержит список JSON компонентов, последовательность которых полностью определяет описание маршрута за исключением вершины from.

{"route":[{элемент1:{набор параметров}, элемент2:{набор параметров}... элементN:{набор параметров}]}

7.10.2.2. Типовая структура элемента маршрута

Многие из элементов языка Spring DSL могут быть описаны объектом JSON, содержащей несколько ключевых параметров.

В текущей версии приложения допускается использовать следующие не обязательные параметры: uri, options, ref, method.

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

В общем случае JSON формат описания типового элемента имеет следующий вид:

{"name":{"uri":"url value","options":{"option1":"value1","option2":"value2",optionN":"valueN"},“ref”:”value”, “method”:”method_name”}}
  • name – имя элемента (обязательный параметр);
  • uri – uri (если необходимо для данного элемента);
  • options – список возможных опций элемента (если необходимо для данного элемента). В текущей версии данный параметр задает опции параметра uri;
  • ref – ссылка на другие элементы (если необходимо для данного элемента);
  • method – вызываемый метод (если необходимо для данного элемента).

7.10.2.3. Элемент to

Например, для элемента типа “to” описание в формате JSON может иметь следующий вид:

{"to":{"uri":"direct:start"}},
{"to":{"uri":"sql:SELECT * FROM route_mapping?dataSource=#postgresSQL"}},
{"to":{"uri":"http://mgts-remedytst02:8080/wsdl/ExtSys_SAES2_MI.wsdl", "options":{"httpMethod":"GET"}}},
{"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}

7.10.2.4. Элемент bean

Элемент “bean” может быть описан следующим образом:

{"bean":{"ref":"testBean"}},
{"bean":{"ref":"testBean", "method":"removeComment"}},
{"bean":{"ref":"testBean", "method":"removeComment(${body}, ${headers})"}}

7.10.2.5. Элемент process

Элемент “process” можно описать так:

{"process":{"ref":"testProcess"}}

7.10.2.6. Элемент setBody

Элемент setBody предназначен для установки нового значения тела сообщения. JSON формат этого элемента имеет следующую структуру:

{"setBody":{"type":"способ указания значения тела", "value":"новое значение тела"}}

Для указания значения тела сообщения могут быть применены разного рода конструкции, основанные на скриптовых языках (simple, spel, groovy) или просто константа (constant).

Рассмотрим некоторые JSON примеры этого элемента.

{"setBody":{"type":"constant", "value":"New Body"}},
{"setBody":{"type":"groovy", "value":"new java.util.Date().getTime()/1000"}},
{"setBody":{"type":"spel", "value":"#{request.body['-method'] “ }

7.10.2.7. Элемент setHeader

Элемент setHeader предназначен для установки значения заголовка сообщения. JSON формат данного элемента имеет следующую структуру:

{"setHeader":{”name":"имя заголовка", "type":"способ указания значения заголовка", "value":"значение заголовка"}}

Для указания значения заголовка могут быть применены разного рода конструкции, основанные на скриптовых языках (simple, spel, groovy) или просто константа (constant). Рассмотрим некоторые JSON примеры этого элемента.

{"setHeader":{"name":"RT000000000000","type":"constant","value":"New Header"}},
{"setHeader":{"name":"RT000000000001","type":"groovy", "value":"new java.util.Date().getTime()/1000"}},
{"setHeader":{"name":"RT000000000002",""type":"spel", "value":"#{request.body['-method'] “ }

7.10.2.8. Элемент transform

Элемент transform предназначен для трансформации тела сообщения. JSON формат данного элемента имеет следующую структуру:

{"transform":{"type":"тип правила трансформации", "value":"правило трансформации"}}

Для указания значения типа правила трансформации могут быть применены разного рода конструкции, основанные на скриптовых языках (simple, spel, groovy). Рассмотрим некоторые JSON примеры этого элемента.

{"transform":{"type":"simple", "value":"<out>${body}</out>"}},
{"transform":{"type":"spel", "value":"#{request.body}"}}

7.10.2.9. Элемент removeHeader

Элемент removeHeader предназначен для удаления заголовка сообщения. JSON формат данного элемента имеет следующую структуру:

{"removeHeader":{"name":"имя заголовка"}}

Рассмотрим JSON пример этого элемента.

{"removeHeader":{"name":"RT000000000000"}}

7.10.2.10. Элемент removeHeaders

Элемент removeHeaders предназначен для удаления списка заголовков сообщения. JSON формат данного элемента имеет следующую структуру:

{"removeHeaders":{"pattern":"шаблон имен для удаления","excludePattern":"шаблон имен для исключения удаления"}}

Рассмотрим JSON пример этого элемента.

{"removeHeaders":{"pattern":"*", "excludePattern":"Content-Type|Content-Length|MIME-Version"}}

7.10.2.11. Элементы choice и when

Элементы choice и when предназначены для организации ветвлений внутри маршрута. JSON формат для данного случая имеет следующую структуру:

{"choice":[
{"when:[{"type":"тип условного выражения","condition":”условное выражение”},{элемент1}, {элемент2} … {элементN}]},
{"when:[{"type":"тип условного выражения","condition":”условное выражение”},{элемент1}, {элемент2} … {элементN}]},
{"when:[{"type":"тип условного выражения","condition":”условное выражение”},{элемент1}, {элемент2} … {элементN}]},
{"otherwise":[{элемент1}, {элемент2} … {элементN}]} ]}

Рассмотрим JSON пример данной структуры.

{"choice":[
{"when":[    {"type":"groovy","condition":"request.headers['RT000000000000'] == null"},
{"setHeader":{"name":"RT000000000000C1", "type":"constant", "value":"This header was added by the condition 1"}},
{"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}]},
{"when":[    {"type":"groovy","condition":"request.headers['RT000000000000'] != null"},
{"setHeader":{"name":"RT000000000000C1", "type":"constant", "value":"This header was added by the condition 2"}},
{"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}]},
{"otherwise":[
{"setHeader":{"name":"RT000000000000C1", "type":"constant", "value":"This header was added by condition otherwise"}},
{"to":{"uri":"log:ru.igtel", "options":{"level":"INFO","showHeaders":"true","showException":"false","showCaughtException":"false"}}}]}]}

7.10.2.12. Элемент обработки исключения onException

Элемент onException используется для организации обработки исключения внутри маршрута. В каждом маршруте может присутствовать несколько секций обработки исключения. JSON формат для данного случая имеет следующую структуру:
{"onException": [{"exception":"тип исключения"}, {элемент1}, {элемент2} … {элементN}]}
Рассмотрим JSON пример данной структуры.
{"onException": [
{"exception":"java.lang.NullPointerException"},
{"setHeader":{"name":"RT000000000000", "type":"constant", "value":"This header was added by the exception handler"}},    {"to":{"uri":"log:ru.igtel", "options":{"level":"ERROR","showHeaders":"true","showException":"true","showCaughtException":"true"}}}
]}

7.10.3. Примеры

7.10.3.1. Пример настройки компонента «SqlComponent» в реестре

{
"driver": "org.postgresql.Driver",
 "username": "sa",
 "password": "123456",
 "url": "jdbc:h2:D:/var3/db/sgate;DB_CLOSE_DELAY=-1;TRACE_LEVEL_FILE=1;DATABASE_TO_UPPER=false;MODE=POSTGRES"
}