Столкнулся давеча с проблемой: необходимо реализовать обмен данными через ftp. Причём хотелось использовать механизм БСП, чтобы не городить свои велосипеды. Казалось бы, для этого стоит только почитать документацию с ИТС, но не всё так просто. Механизм БСП заточен на обмен XML по правилам обмена. Чтобы использовать его для любого другого обмена, коих в мире не мало, требуются доработки. В статье описан вариант, как из положения выйти (так сказать, и рыбку съесть и косточкой не подавиться и формат обмена использовать произвольный и стандартным механизмом нагло воспользоваться).
Ещё раз уточню. Здесь по сути нет инфы с ИТС, т.к. статья описывает использование механизмов БСП для произвольного обмена. Для обмена в формате XML по правилам обмена надо читать ИТС.
Какие возможности обмена БСП мы можем использовать:
Для начала стоит отметить, какие же такие типовые возможности я позарился использовать. Речь идёт о справочнике СценарииОбменовДанными.
Где можно прописать параметры обмена данными:
- действие - выгрузка или загрузка
- подключение - каталог или FTP или EMAIL или веб сервис или COM подключение (хранится это в РС "НастройкиТранспортаОбмена", значит нам не надо думать, где хранить эти данные)
- расписание - расписание РЗ (значит не надо добавлять своё)
Вдобавок нам не надо создавать форму, на которой можно задавать все эти настройки и имеются доп. возможности:
- выполнить сценарий обмена прямо сейчас
- Открыть журнал регистрации с отбором по событию обмена
Более подробно, о том, как сие выглядит в режиме предприятия написано ниже, в инструкции для пользователя.
Какие требуются доработки:
1. Добавить План обмена. Даже если он не нужен. Ибо без него ничего не взлетит. Это требование БСП. В модуль менеджера добавить следующий код, скопировав из типовых или взяв с ИТС. Естественно добавив только те виды транспорта, которые могут использоваться в вашем обмене. На всякий случай укажу, что вид "FILE" - это обмен через каталог.
Функция ИспользуемыеТранспортыСообщенийОбмена() Экспорт
Результат = Новый Массив;
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FILE);
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FTP);
Возврат Результат;
КонецФункции
2. Переопределить механизм обмена БСП. Для этого нам любезно предназначен специальный ОМ ОбменДаннымиПереопределяемый. В зависимости от задачи, нам нужна одна из двух (или сразу обе) процедур этого ОМ - ПриЗагрузкеДанных или ПриВыгрузкеДанных. Для нового обмена в означенные процедуры необходимо добавить следующий текст:
в ПриЗагрузкеДанных
Если ТипЗнч(Отправитель) = Тип("ПланОбменаСсылка._УТ_ДО_Пользователи") Тогда
ПриЗагрузке(СтандартнаяОбработка, Отправитель, ИмяФайлаСообщения, ДанныеСообщения,
КоличествоЭлементовВТранзакции, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов)
КонецЕсли;
в ПриВыгрузкеДанных
Если ТипЗнч(Получатель) = Тип("ПланОбменаСсылка._УТ_ДО_Пользователи") Тогда
ПриВыгрузке(СтандартнаяОбработка, Получатель, ИмяФайлаСообщения, ДанныеСообщения,
КоличествоЭлементовВТранзакции, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов)
КонецЕсли;
Также в модуль добавляем блок методов УниверсальныйОбменДаннымиСПомощьюБСП
#Область УниверсальныйОбменДаннымиСПомощьюБСП
//Если обмен инициализирован справочником СценарииОбменовДанными
//
Процедура ПриВыгрузке(СтандартнаяОбработка, Получатель, ИмяФайлаСообщения, ДанныеСообщения,
КоличествоЭлементовВТранзакции, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов) Экспорт
//КоличествоОтправленныхОбъектов - сюда можно присвоить количество выгруженного, которое потом запишется в ЖР
//ИмяСобытияЖурналаРегистрации - его использует БСП при записи в ЖР,
//нам надо делать также, чтобы удобно смотреть ЖР из сценария тестирования
//Планы обмена фиктивные, поэтому СтандартнаяОбработка не требуется
СтандартнаяОбработка = Ложь;
//Типовой механизм сам задаёт имя файла выгрузки и формат у него может быть только XML (так выглядит имя - Message_1_2.xml),
//поэтому,если мы хотим это переопределить, надо получить настройки обмена (такие, как каталог обмена или ftp)
НастройкиТранспорта = НастройкиТранспортаУзла(Получатель, Перечисления.ДействияПриОбмене.ВыгрузкаДанных);
//в структуре НастройкиТранспорта лежат настройки из РС НастройкиТранспортаОбмена. Присутствуют не все поля РС, а только те,
//которые соответствуют выбранному в сценарии обмена виду транспорта обмена (см. Перечисления.ДействияПриОбмене)
//ТЕЛО ВЫГРУЗКИ
//здесь мы знаем куда выгружать и описываем код выгрузки
ОбщегоНазначения.МенеджерОбъектаПоСсылке(Получатель).ПриВыгрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов);
//эта строка выполняется в самом конце, если выгрузка прошла успешно
СоздатьФайлВыгрузкиЗаглушкуДляОбменаНаБСП(ИмяФайлаСообщения);
КонецПроцедуры
//Если обмен инициализирован справочником СценарииОбменовДанными
//
Процедура ПриЗагрузке(СтандартнаяОбработка, Отправитель, ИмяФайлаСообщения, ДанныеСообщения,
КоличествоЭлементовВТранзакции, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов) Экспорт
СтандартнаяОбработка = Ложь;
НастройкиТранспорта = НастройкиТранспортаУзла(Отправитель, Перечисления.ДействияПриОбмене.ЗагрузкаДанных);
//ТЕЛО ЗАГРУЗКИ
//здесь мы знаем откуда загружать и описываем код загрузки
ОбщегоНазначения.МенеджерОбъектаПоСсылке(Отправитель).ПриЗагрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов);
КонецПроцедуры
Процедура СоздатьФайлВыгрузкиЗаглушкуДляОбменаНаБСП(ИмяФайлаСообщения)
//Чтобы типовой механизм понял, что выгрузка данных произошла,
//надо заполнить типовой файл выгрузки содержимым.
ЗаписьХМЛ = Новый ЗаписьXML;
ЗаписьХМЛ.ОткрытьФайл(ИмяФайлаСообщения);
ТекстЗаглушка = "Этот файл создаётся типовым механизмом обмена БСП. Его следует игнорировать. Можно удалять.";
ЗаписьХМЛ.ЗаписатьНачалоЭлемента("Данные");
ЗаписьХМЛ.ЗаписатьТекст(ТекстЗаглушка);
ЗаписьХМЛ.ЗаписатьКонецЭлемента();
ЗаписьХМЛ.Закрыть();
КонецПроцедуры
Функция НастройкиТранспортаУзла(Узел, ВыполняемоеДействие)
//к сожалению, здесь мы не имеем ссылки на сценарий обмена, откуда он и был запущен,
//а она нужна, чтобы определить ВидТранспортаОбмена, т.е. понять куда выгружать (в каталог, или ftp, или ещё куда)
//есть несколько вариантов решить эту задачу и все "кривые":
//
//1. в модуле менеджера ПО, в функции ИспользуемыеТранспортыСообщенийОбмена() разрешить только один ВидТранспортаОбмена
//2. сделать ВидТранспортаОбмена равным РегистрыСведений.НастройкиТранспортаОбмена.ВидТранспортаСообщенийОбменаПоУмолчанию(...),
//но тогда настройка транспорта в сценарии обмена станет фиктивной, что приведёт к непониманию со стороны пользователей
//(ВидТранспортаСообщенийОбменаПоУмолчанию задаётся в предприятии в настройках плана обмена)
//3. Для СОВОКУПНОСТИ (УЗЕЛ нашего ПО + выполняемое действие (загрузка или выгрузка))
//ограничить возможность использования сценариев для обмена одним сценарием.
//Если их будет создано больше - отменять обмен. Если найден один - брать ВидТранспортаОбмена оттуда.
//
//Здесь реализован лучший, на мой взгляд, третий путь. Таким образом, мы получим одно ограничение:
//чтобы выполнять несколько сценариев с данным обменом и выполняемым действием (загрузка или выгрузка),
//нужно на каждый новый сценарий создавать копированием узел ПО (на всякий случай уточню: в режиме предприятия)
//но для подавляющего большинства хватит и одного сценария (ведь возможность их множественности, это фича БСП).
Запрос = Новый Запрос;
Запрос.Текст =
//поскольку помеченный на удаление сценарий всё равно можно выполнять, отбирать в запросе только непомеченные нельзя
"ВЫБРАТЬ
| СценарииОбменовДаннымиНастройкиОбмена.ВидТранспортаОбмена
|ИЗ
| Справочник.СценарииОбменовДанными.НастройкиОбмена КАК СценарииОбменовДаннымиНастройкиОбмена
|ГДЕ
| СценарииОбменовДаннымиНастройкиОбмена.УзелИнформационнойБазы = &УзелИнформационнойБазы
| И СценарииОбменовДаннымиНастройкиОбмена.ВыполняемоеДействие = &ВыполняемоеДействие";
Запрос.УстановитьПараметр("УзелИнформационнойБазы", Узел);
Запрос.УстановитьПараметр("ВыполняемоеДействие", ВыполняемоеДействие);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Количество() > 1 Тогда
//Вызывающая процедура обработает исключение и запишет его в ЖР
ВызватьИсключение "Для узлов данного плана обмена нельзя задавать больше чем по одному сценарию обмена!!!";
ИначеЕсли Выборка.Количество() = 0 Тогда
//вообще, здесь мы не можем оказаться, но на всякий случай
ВызватьИсключение "Не найден сценарий обмена для данного узла обмена";
КонецЕсли;
Выборка.Следующий();
НастройкиТранспорта = РегистрыСведений.НастройкиТранспортаОбмена.НастройкиТранспорта(Узел, Выборка.ВидТранспортаОбмена);
Возврат НастройкиТранспорта;
КонецФункции
#КонецОбласти
Сами процедуры обмена данными находятся в модуле менеджера плана обмена. Таким образом, шаблон модуля менеджера ПО будет выглядеть так:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область ПрограммныйИнтерфейс
#Область ПроцедурыИФункцииБсп
// Возвращает массив используемых транспортов сообщений для этого плана обмена
//
// 1. Например, если план обмена поддерживает только два транспорта сообщений FILE и FTP,
// то тело функции следует определить следующим образом:
//
// Результат = Новый Массив;
// Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FILE);
// Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FTP);
// Возврат Результат;
//
// 2. Например, если план обмена поддерживает все транспорты сообщений, определенных в конфигурации,
// то тело функции следует определить следующим образом:
//
// Возврат ОбменДаннымиСервер.ВсеТранспортыСообщенийОбменаКонфигурации();
//
// Возвращаемое значение:
// Массив - массив содержит значения перечисления ВидыТранспортаСообщенийОбмена
//
Функция ИспользуемыеТранспортыСообщенийОбмена() Экспорт
Результат = Новый Массив;
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FILE);
Результат.Добавить(Перечисления.ВидыТранспортаСообщенийОбмена.FTP);
Возврат Результат;
КонецФункции
#КонецОбласти
#Область ВыгрузкаЗагрузкаЭкспортныеМетоды
//Вызывается из _омОбмен.ПриВыгрузке
//
Процедура ПриВыгрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоОтправленныхОбъектов) Экспорт
КонецПроцедуры
//Вызывается из _омОбмен.ПриВыгрузке
//
Процедура ПриЗагрузке(НастройкиТранспорта, ИмяСобытияЖурналаРегистрации, КоличествоПолученныхОбъектов) Экспорт
КонецПроцедуры
#КонецОбласти
#КонецОбласти
#Область Выгрузка
#КонецОбласти
#Область Загрузка
#КонецОбласти
#КонецЕсли
Ограничения, особенности использования нашего механизма:
- Для СОВОКУПНОСТИ (УЗЕЛ нашего ПО + выполняемое действие (загрузка или выгрузка)) можно задать только один сценарий. Если необходимо больше, то, на каждый новый сценарий надо создавать копированием узел ПО (на всякий случай уточню: в режиме предприятия), но для подавляющего большинства хватит и одного сценария (ведь возможность их множественности, это фича БСП).
- В папке обмена будет находиться один лишний файл или (в случае "2.в") придётся смириться с типовым именем файла. Но это тоже легко пережить =)
- а) Выгрузка. В папке выгрузки автоматом создаётся ненужный файл "Message_1_2.xml" с текстом "<Данные>Этот файл создаётся типовым механизмом обмена БСП. Его следует игнорировать. Можно удалять.</Данные>"
- б) Загрузка. В папку загрузки надо кинуть файл "Message_2_1.xml". Можно поместить в него следующий текст: "<Данные>ФАЙЛ НЕ УДАЛЯТЬ!! Без него него не будет работать механизм загрузки на БСП.</Данные>".
- в) Если выгрузка в ХМЛ, то можно обойтись без минусов 1 и 2, больше используя механизм БСП. Поскольку БСП как раз рассчитана именно на выгрузку в ХМЛ, то здесь лишних хлопот не требуется и мы можем прямо в ПриВыгрузкеДанных писать файл выгрузки (т.е. блок методов УниверсальныйОбменДаннымиСПомощьюБСП тут не нужен). Пример, как это сделать см в процедуре СоздатьФайлВыгрузкиЗаглушкуДляОбменаНаБСП. Но, у данного решения есть один недостаток: Имя файла генерирует БСП ("Message_1_2.xml", где "1" и "2" это коды узлов "откуда" и "куда" соответственно).
Особенности использования механизма БСП:
В предприятии надо создать два узла ПО, т.к. обмен с самим собой делать нельзя. Также обоим узлам надо задать Код, иначе обмен не взлетит. Данные проверки производятся в процедуре ОбменДаннымиСервер.ВыполнитьПроверкуСтруктурыОбменаНаВалидность.
Инструкция для пользователей:
В плане обмена создаём два узла. Узел Этой базы (у него на картинке зелёная точка справа внизу) и узел базы приёмника. Обязательно заполняем им код и наименование (для простоты можно назвать как на скрине «1» и «2»). Далее для обмена (выгрузки или загрузки) данными надо выбирать узел базы с которой идёт обмен, т.е. «2». Если выберем «1», то обмен проходить не будет а в ЖР появится запись «Нельзя организовать обмен данными с текущим узлом информационной базы. Обмен отменен.».
Спр. «Сценарии синхронизации данных».
Задаём имя сценария, добавляем строку настройки обмена в ТЧ.
Настраиваем параметры подключения.
После того, как всё настроено, можно настроить РЗ или выполнить обмен прямо сейчас.
После выполнения обмена, можно посмотреть его лог в ЖР.
ОпосляСкриптум:
Пришлось немного разобрать механизмы БСП, вследствие чего родилась сия статья. В сухом остатке мы имеем:
- Чтобы использовать механизм обмена данными БСП для произвольного обмена, нужно просто скопировать описанные процедуры. Всё. Дальше можно заняться собственно самими процедурами обмена.
- Также представлена инструкция для пользователей.
------------------------------------
ИНТЕРЕСНЫХ ВАМ ЗАДАЧ, ПЛОДОТВОРНОЙ РАБОТЫ И ОРИГИНАЛЬНЫХ/ОПТИМАЛЬНЫХ РЕШЕНИЙ!!