chumpa написал:
Решение конечно несложное и очевидное -- реализовать ejb-модуль к ресивер-каналу SMTP и указывать в параметрах модуля новые значения атрибутов, которые будут вписаны после меппинга.
Написал на форуме, прошло 2 дня и внезапно эта долбанная EJB перестала отрабатывать в продуктиве для части обращений. Вообще сама идея EJB и её реализация и использование в промышленных масштабах по-моему полная задница. Недиагностируемая, тяжёлая в работе, ненужная избыточность. Тем не менее продолжу рассказывать про другой полезный в хозяйстве хабар.
Работа с БДСама шина XI не является полноценным ETL-средством и работа с базами данных в ней реализована достаточно примитивно, ну а что делать, для простых задач хватает и этого. "Но есть нюансы".
Если требуется работать с большим количеством исходных БД/таблиц, лучше сразу отказаться от идеи использования sender-каналов. Иначе ситуация легко выходит на монструозный уровень в Directory: сначала 3-4 базы данных и по одному селекту на каждую БД. Такое ещё можно представить как 4CC + 4SA + 1RD + 1ID + 4party + 1BusinessSystem = 15 объектов в директори. Однако Заказчик может потом сказать "давайте из каждой БД тащить по 5 таблиц, а в будущем будет 10БД", и что же делать православному христианину в таком случае? На самом деле есть как минимум 5 подходов которые стоит рассмотреть:
1. Использовать существующий подход. Тогда число объектов Directory будет: 50CC + 50SA ну и т.д. уже не столь страшно, особенно при универсальных меппингах. Для неручного создания и сопровождения такого зоопарка есть IDAPI, каковой можно использовать. Однако это решение порождает собственные проблемы и не гарантирует победы над сложностью, каковая победа должна являться смыслом любой осмысленной деятельности. Хотя создание в директори помогает документировать решение и даёт стандартные рычаги остановки/старта CC по расписанию.
Но! в моей реальности селекты очень часто пишутся не в расчёте на иксайную логику выборки! Иксайная логика предполагает либо статические селекты по флаговым признакам (какой-нибудь XI_FLAG с двумя состояниями) либо предполагает отсутствие/наличие записей в таблице как естественный флаговый признак. У меня же на входе часто pipelined-процедура вида `select * from table(procedure_name( to_date('01012010','ddmmyyyy'), to_date('31122010','ddmmyyyy') ))', то бишь возвращает какие-то бизнес-данные за указанный период дат. Вместо pipelined-процедуры можно подставить обычный select с выборкой по WHERE того же диапазона дат, не в этом проблема. При этом состояние исходной БД вообще не меняется, а интервал надо задавать учитывая запросы бизнеса и пропускную способность шины (как правило эффективная обработка сообщений размером более 100 метров невозможна на большинстве инсталляций).
Тогда наступает коллизия -- необходимо дробить исходную выборку на набор нескольких поменьше, а дальше либо склеивать их в процессе, либо так и по частям передавать, но сложность конечно не в этом а в невозможности лёгкой модификации всех 50 CC -- без IDAPI это нереально. Нужен внешний диспетчер.
2. Вынести все сендеры во внешний Plain J2SE Adapter Engine с возможностью лёгкой модификации запросов на нём, возможно что эти изменения должны делаться отдельными людьми службы сопровождения в составе команд на их собственных базах данных. То есть каждую БД обслуживает свой человек, правит свои селекты и все довольны -- в XI всё приходит по XI-протоколу, в directory всё просто.
Подход имеет смысл только при необходимости делегировать полномочия, так как ручная работа никуда не девается а размазывается, что ещё хуже (из 10 человек гарантированно кто-нибудь налажает).
3. Фантастический подход -- реализовать свой EJB-модуль либо свой вообще свой адаптер для JDBC sender. Вариант с EJB какое-то время обсуждался и прорабатывался, но по многим очевидным причинам был отвергнут. Свой адаптер это уже более интересная тема, но результат непредсказуем.
4. Прагматический подход, породивший множество продуктивных идей -- на каждую БД завести один-единственный receiver-CC и инициативу запроса переложить на внешний шедулер. Это будет описано отдельным постом "О шедулере".
5. Реализовать на каждой БД единую точку отдачи данных в XI, одинаковую хранимую процедуру с унифицированным интерфейсом. Потребуются права разработчика БД и соответствующие знания, и я даже применял такой подход дважды, от невозможности в тот раз применить подход №4 из-за его малой пропускной способности.
В ходе развития данной темы было придумано целых 2 оригинальных, не встречавщихся мне в других местах, подхода:
* Все 50 исходных таблиц объединяются в один union, обобщённый табличный формат. Писать такой SQL руками конечно же невозможно, приходится писать генерирующий скрипт. Вместе с данными передаётся информация о структуре/меппинге полей для обработки в шине. Выбор таблиц для помещения в результирующую выборку происходит либо как параметр pipelined-процедуры, либо как функция от времени. В целом слабожизнеспособно, но сама идея объединять разные таблицы в одну выборку заслуживает внимания (поскольку унифицирует меппинги и уменьшает число интерфейсов).
* Все 50 исходных таблиц выбираются как XML-дерево. Это супер-идея Димы Ольшанского, каковая помогла вообще по-новому взглянуть на возможности сендер-канала JDBC. Результат выборки (см. пакет DBMS_XMLGEN для Oracle) выглядит так:
Code:
<?xml version="1.0" encoding="utf-8"?>
<ns:SqlClause xmlns:ns="urn:1">
<row>
<COLUMN_VALUE><?xml version="1.0"?>
<ROWSET>
<ROW>
<ZZZZ_ID>2251018</ZZZZ_ID>
<TYPE_ID>1</TYPE_ID>
<YYYY_ID>121634470</YYYY_ID>
</ROW>
</ROWSET>
</COLUMN_VALUE>
</row>
</ns:SqlClause>
Сделать unescaping такого дерева совсем не трудно. И построить в Оракле его тоже нетрудно, по 1 курсору на таблицу + один селект из 50 курсоров, а затем DBMS_XMLGEN построит дерево сам!
Теперь можно, при минимальной доработке на стороне БД либо реализацией нового/стороннего адаптера, выбирать одним запросом хоть стопятьсот таблиц, лишь бы размер сообщения был приемлем. Однако при большом количестве таблиц так же приходится генерировать запрос и основу меппингов.