При построении сложных распределенных информационных систем часто возникает задача бесшовной интеграции баз данных. Типичный сценарий: при создании документа «Реализация товаров и услуг» в одной конфигурации необходимо мгновенно отразить соответствующее «Поступление товаров и услуг» в другой. Исторически для этого использовалось COM-соединение, однако современная архитектура систем (особенно при переходе серверов на операционную систему Linux) диктует новые правила.
В этой статье мы подробно разберем, как технически реализовать вызовы процедур и функций внешней базы через COM-соединение, проанализируем ограничения этого подхода, выясним, почему Linux накладывает жесткое вето на использование COM, и рассмотрим надежные альтернативные варианты интеграции.
Для того чтобы вызвать процедуру или функцию из другой информационной базы 1С, необходимо предварительно настроить COM-подключение. Разберем по шагам, как это сделать программно.
Прежде всего, в базе-приемнике вызываемый общий модуль должен обладать определенными свойствами. Перейдем в конфигуратор базы-приемника, найдем нужный общий модуль и убедимся, что у него установлены следующие флаги:
Экспорт.Теперь рассмотрим пример кода в базе-источнике, который создает COM-соединение с базой-приемником и вызывает процедуру общего модуля для установки договора контрагента:
// Инициализация COM-соединения
COMСоединитель = Новый COMОбъект("V83.COMConnector");
ПараметрыПодключения = "Srvr=""MyServer"";Ref=""TargetBase"";Usr=""IntegrationUser"";Pwd=""SecretPassword"";";
Попытка
БазаПриемник = COMСоединитель.Connect(ПараметрыПодключения);
Исключение
ЗаписьЖурналаРегистрации("ИнтеграцияCOM", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
ВызватьИсключение "Не удалось подключиться к базе-приемнику: " + ОписаниеОшибки();
КонецПопытки;
После успешного подключения мы можем обращаться к метаданным и общим модулям базы-приемника напрямую через переменную БазаПриемник. Выясним, как передать параметры и вызвать метод:
// Получаем ссылки на объекты в контексте БАЗЫ-ПРИЕМНИКА
// Внимание: мы не можем передать ссылку из текущей базы напрямую, нужно найти ее аналог в приемнике!
КонтрагентПриемник = БазаПриемник.Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ДанныеДляЗаполнения.КонтрагентИНН);
ОрганизацияПриемник = БазаПриемник.Справочники.Организации.НайтиПоРеквизиту("ИНН", ДанныеДляЗаполнения.ОрганизацияИНН);
// Если объекты найдены, вызываем экспортный метод общего модуля базы-приемника
Если ЗначениеЗаполнено(КонтрагентПриемник) И ЗначениеЗаполнено(ОрганизацияПриемник) Тогда
// Получаем пустую ссылку на договор для заполнения
ДоговорПриемник = БазаПриемник.Справочники.ДоговорыКонтрагентов.ПустаяСсылка();
// Непосредственный вызов процедуры из общего модуля внешней базы
БазаПриемник.РаботаСДоговорамиКонтрагентовБП.УстановитьДоговорКонтрагента(
ДоговорПриемник,
КонтрагентПриемник,
ОрганизацияПриемник,
ДанныеДляЗаполнения.ВидОперации
);
КонецЕсли;
Посмотрим на пример внимательно: передача примитивных типов данных (числа, строки, булево, даты) происходит прозрачно. Однако сложные типы данных (ссылки на справочники, документы, перечисления) требуют поиска соответствующих элементов в пространстве базы-приемника по ключевым полям, таким как ИНН, Уникальный Идентификатор (UUID) или наименование.
Что делать, если вам нужно передать из одной базы в другую сложную коллекцию данных, например, ТаблицаЗначений или Структура? Напрямую передать объект таблицы значений через COM-границу нельзя, так как это вызовет ошибку несоответствия типов. Нам потребуется сериализация.
Рассмотрим устаревший, но все еще встречающийся в коде метод сериализации с использованием внутренних строк:
// Преобразование таблицы на стороне источника в строку
СтрокаТаблицы = ЗначениеВСтрокуВнутр(МояТаблицаЗначений);
// Передача в базу-приемник и десериализация
ТаблицаВПриемнике = БазаПриемник.ЗначениеИзСтрокиВнутр(СтрокаТаблицы);
Важное предупреждение: метод ЗначениеВСтрокуВнутр крайне нестабилен. Если конфигурации базы-источника и базы-приемника имеют даже минимальные различия в структуре метаданных или работают на разных версиях платформы 1С, десериализация завершится аварийным завершением сеанса. Вместо этого настоятельно рекомендуется использовать универсальный формат JSON.
Разберем современный и безопасный способ передачи таблиц значений через JSON-сериализацию:
// На стороне источника упаковываем таблицу значений в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МояТаблицаЗначений);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Передаем СтрокаJSON через COM-параметр.
// На стороне приемника пишем функцию в общем модуле, которая принимает эту строку:
Функция ВосстановитьТаблицуИзJSON(СтрокаJSON) Экспорт
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
ТаблицаДанных = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Возврат ТаблицаДанных;
КонецФункции
Бывают ситуации, когда в целевой базе нет общего модуля с флагом «Внешнее соединение», а вносить изменения в конфигурацию (снимать с поддержки, писать расширения) запрещено правилами компании. В таких случаях программисты используют так называемую «обработку-агент».
Идея заключается в том, что весь необходимый код для работы во внешней базе помещается в модуль внешней обработки. В базе-источнике мы считываем файл этой обработки в двоичные данные или просто передаем путь к файлу на диске. Давайте посмотрим на этот механизм в действии:
// Инициализируем COM-соединение
БазаПриемник = COMСоединитель.Connect(ПараметрыПодключения);
// Подключаем внешнюю обработку внутри удаленной базы
ПутьКФайлуОбработки = "C:\Share\AgentProcessor.epf";
ОбработкаАгент = БазаПриемник.ВнешниеОбработки.Создать(ПутьКФайлуОбработки);
// Теперь мы можем запускать любые экспортные методы модуля этой обработки
// Важно то, что этот код выполняется полностью в контексте базы-приемника,
// и имеет доступ ко всем серверным процедурам, обходя ограничения флагов общих модулей!
ОбработкаАгент.ВыполнитьСозданиеДокументов(СтрокаJSON);
Если сервер вашей системы 1С работает под управлением операционной системы Linux, использование COM-технологий превращается в серьезную архитектурную проблему.
COM (Component Object Model) — это проприетарная технология корпорации Microsoft, глубоко интегрированная в ядро Windows. В операционных системах семейства Linux полноценной реализации COM нет. Чтобы обойти это ограничение, разработчики вынуждены переносить выполнение кода с сервера на клиента. Это означает, что метод Новый COMОбъект вызывается в контексте клиентского приложения на Windows-машине пользователя.
Проанализируем последствия такого обхода:
Для надежной интеграции баз в гетерогенных средах (где серверы могут работать на Linux) фирма «1С» рекомендует полностью отказаться от COM. Рассмотрим наиболее эффективные инструменты взамен устаревшей технологии.
Если вам нужно просто создавать документы «Поступление» на основе «Реализаций», платформа 1С предоставляет готовый REST API «из коробки».
Вам не нужно писать ни одной строчки кода в базе-приемнике. Достаточно в конфигураторе (вкладка «Вспомогательные» в свойствах конфигурации) настроить состав стандартного интерфейса OData, выбрав нужные справочники и документы. После этого из базы-источника отправляется обычный HTTP-запрос:
// Пример отправки HTTP-запроса POST для создания документа через OData
Соединение = Новый HTTPСоединение("ServerName", , "Login", "Password");
Запрос = Новый HTTPЗапрос("/1c_base/odata/standard.odata/Document_ПоступлениеТоваровУслуг");
Запрос.УстановитьТелоИзСтроки(ДанныеДокументаВФорматеJSON, КодировкаТекста.UTF8);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 201 Тогда
ЗаписьЖурналаРегистрации("ИнтеграцияOData", УровеньЖурналаРегистрации.Информация, , , "Документ успешно создан");
КонецЕсли;
Когда требуется сложная логика проведения документов или заполнения специфических реквизитов (как в случае с подбором договоров), лучшим решением является создание собственного HTTP-сервиса в базе-приемнике. Он принимает структурированный JSON, выполняет на сервере любые проверки и возвращает результат. Данный подход абсолютно независим от операционной системы и версии платформы 1С.
Если базы находятся в постоянном обмене данными, рекомендуется использовать встроенную в Библиотеку Стандартных Подсистем (БСП) технологию EnterpriseData. Обмен XML/JSON-пакетами настраивается через регламентные задания и может передаваться через веб-сервисы, FTP или папки обмена. Для критически важных систем с высокой нагрузкой отличным решением будет интеграция через брокеры сообщений (например, RabbitMQ, Apache Kafka или отечественную 1С:Шина).
Использование COM-объектов в среде 1С сегодня оправдано только для локальных утилит на операционной системе Windows. При работе сервера 1С на Linux интеграция через COM становится источником регулярных сбоев. Переход на HTTP-сервисы, REST API (OData) или обмен данными в формате JSON позволит вам выстроить масштабируемую, отказоустойчивую и современную архитектуру, которая будет работать быстро и стабильно на любой операционной системе.