Как исправить ошибку «Фабрика XDTO текущего контекста не совпадает с фабрикой, в рамках которой был создан объект» в 1С:Управление ВС после обновления платформы?

Программист 1С v8.3 (Управляемые формы)
← На главную

После обновления платформы 1С:Предприятие до версии 8.3.22.2175 или аналогичных версий, многие пользователи сталкиваются с новой категорией ошибок, связанных с преобразованием данных XDTO. Одна из наиболее распространенных и вызывающих затруднения – это сообщение «Ошибка преобразования данных XDTO: Фабрика XDTO текущего контекста не совпадает с фабрикой, в рамках которой был создан объект». Эта проблема особенно актуальна для конфигураций, активно использующих интеграцию с внешними системами через веб-сервисы, как, например, «1С:Управление ветеринарными сертификатами. Интеграция с ФГИС Меркурий» (1С:УВС).

Рассмотрим подробно, почему возникает эта ошибка, какие шаги можно предпринять для её исправления и какие особенности нужно учитывать при работе с XDTO-объектами на новых версиях платформы.

Суть проблемы: несовпадение XDTO-фабрик

Прежде чем углубиться в решение, выясним причину возникновения данной ошибки. В экосистеме 1С:Предприятия XDTO (XML Data Transfer Objects) используются для представления данных XML-схем в объектно-ориентированном виде. Это позволяет удобно работать со сложными структурами данных, которые часто встречаются при обмене информацией с внешними системами, такими как ФГИС Меркурий. Для создания и управления этими объектами платформа использует XDTO-фабрики.

Каждая XDTO-фабрика является своего рода «контейнером» или «производителем» XDTO-объектов, которые соответствуют определенным XML-схемам. В идеальной ситуации, если мы создаем объект и затем пытаемся с ним работать (например, добавлять его в коллекцию другого XDTO-объекта или устанавливать его свойства), все операции должны происходить в рамках одной и той же фабрики или совместимых фабрик. Проблема, возникающая на платформе 8.3.22.x, заключается в том, что даже при использовании одной и той же схемы, платформа начинает более строго контролировать «происхождение» XDTO-объектов. Если объект был создан одной фабрикой (например, глобальной ФабрикаXDTO), а затем пытаются изменить его свойства или добавить его в коллекцию объекта, который был создан другой, пусть даже логически идентичной, фабрикой (например, фабрикой, полученной через метод Объект.Фабрика()), возникает ошибка несовпадения контекстов.

Эта ошибка признана фирмой «1С» как проблема на уровне платформы. По ней был создан тикет в службу поддержки (например, 60003084), но она не была исправлена в ранних версиях 8.3.22.x и даже проявлялась в тестовых сборках 8.3.23.x. На платформах версии 8.3.21 и более ранних эта проблема, как правило, не проявляется, что подтверждает её связь с изменениями в работе платформы 8.3.22.

Исходная ошибка в 1С:УВС и её анализ

В нашем случае, пользователь столкнулся с ошибкой при выполнении регламентного задания «ОтправкаТранспортныхОпераций» в конфигурации «1С:Управление ветеринарными сертификатами». Трассировка стека указывает на следующие строки кода:


{ОбщийМодуль.ИнтеграцияВетисAPIСлужебный.Модуль(854)}:Объект[ИмяСвойства] = Фабрика.Создать(Свойство.Тип);
...
по причине:
Ошибка преобразования данных XDTO:
Фабрика XDTO текущего контекста не совпадает с фабрикой, в рамках которой был создан объект

Эта ошибка возникает в общем модуле ИнтеграцияВетисAPIСлужебный, в процедуре, ответственной за заполнение свойств XDTO-объекта. Строка Объект[ИмяСвойства] = Фабрика.Создать(Свойство.Тип); пытается создать новый XDTO-объект для заполнения определенного свойства другого объекта. Здесь Фабрика, по всей видимости, является локальной переменной или параметром, представляющим "глобальную" XDTO-фабрику или фабрику, переданную извне.

Проблема в том, что объект, свойство которого мы пытаемся заполнить (Объект), вероятно, был создан с использованием своей собственной XDTO-фабрики, которая не совпадает с фабрикой, используемой для создания вложенного объекта (Фабрика.Создать(Свойство.Тип)). Начиная с версии 8.3.22, платформа требует, чтобы вложенные XDTO-объекты, присваиваемые свойствам или добавляемые в коллекции родительских объектов, были созданы с помощью той же фабрики, что и родительский объект, или фабрики, полученной из его контекста.

Решение первой ошибки: корректировка метода создания XDTO-объектов

Для устранения первой ошибки, как предложено на одном из форумов, необходимо изменить способ создания вложенных XDTO-объектов. Вместо использования переданной или глобальной фабрики, следует использовать фабрику того объекта, к которому относится создаваемое свойство. Это гарантирует, что все объекты находятся в одном контексте XDTO-фабрики.

Разберем по шагам, как это можно исправить:

  1. Определяем проблемное место. Согласно трассировке стека, ошибка возникает в модуле ОбщийМодуль.ИнтеграцияВетисAPIСлужебный, строка 854: Объект[ИмяСвойства] = Фабрика.Создать(Свойство.Тип);
  2. Вносим изменение в код. Необходимо заменить вызов Фабрика.Создать(Свойство.Тип); на Объект.Фабрика().Создать(Свойство.Тип);. Метод Объект.Фабрика() возвращает XDTO-фабрику, связанную непосредственно с данным XDTO-объектом, что обеспечивает корректное соответствие контекстов.

Пример изменения кода будет выглядеть так:


// Было (примерно):
// Объект[ИмяСвойства] = Фабрика.Создать(Свойство.Тип);

// Стало:
Объект[ИмяСвойства] = Объект.Фабрика().Создать(Свойство.Тип);

После применения этого изменения и перезапуска регламентного задания, первая ошибка, связанная с несовпадением фабрик при установке свойства, должна исчезнуть. Это подтверждается сообщением пользователя, который успешно применил данный патч.

Возникновение новой ошибки после исправления первой

К сожалению, исправление одной проблемы иногда выявляет другие, связанные с тем же корневым механизмом. После применения вышеописанного исправления, пользователь столкнулся с новой ошибкой в другом месте кода, также связанной с XDTO-объектами:


Если ДанныеУсловийПеремещения <> Неопределено Тогда
    Для Каждого ТекУсловие Из ДанныеУсловийПеремещения Цикл
        ЗапросУсловиеПеремещения = ФабрикаXDTO.Создать("http://api.vetrf.ru/schema/cdm/mercury/vet-document/v2", "RegionalizationClause");
        СоответсвиеУсловиеПеремещения = Новый Соответствие;
        СоответсвиеУсловиеПеремещения.Вставить("condition/guid", ТекУсловие.УсловиеПеремещенияGUID);
        ИнтеграцияВетисAPIСлужебный.ЗаполнитьСвойстваОбъектаXDTO(ФабрикаВетисAPI, ЗапросУсловиеПеремещения, СоответсвиеУсловиеПеремещения, "VetDocument", ОшибкиЗаполнения);
        ЗапросСертификат.authentication.r13nClause.Добавить(ЗапросУсловиеПеремещения); // Ошибка здесь
    КонецЦикла;
КонецЕсли;

Ошибка теперь возникает в строке ЗапросСертификат.authentication.r13nClause.Добавить(ЗапросУсловиеПеремещения);. Это происходит при попытке добавить объект ЗапросУсловиеПеремещения в коллекцию r13nClause, которая является частью более крупного XDTO-объекта ЗапросСертификат.

Проанализируем ситуацию: объект ЗапросУсловиеПеремещения создается с использованием "глобальной" или общей фабрики ФабрикаXDTO.Создать("...", "RegionalizationClause"). С другой стороны, объект ЗапросСертификат, скорее всего, был создан своей собственной фабрикой, которая может отличаться от фабрики, используемой для создания ЗапросУсловиеПеремещения. Когда мы пытаемся добавить ЗапросУсловиеПеремещения в коллекцию r13nClause объекта ЗапросСертификат, платформа снова обнаруживает несовпадение XDTO-фабрик.

Пользователь не предоставил прямого решения этой новой ошибки в рамках темы, однако мы можем применить тот же принцип, который помог в первом случае. Критически важно: если объект должен быть добавлен в коллекцию другого XDTO-объекта, он должен быть создан с использованием фабрики того объекта, к которому он добавляется, или фабрики, полученной из его контекста.

Посмотрим на пример возможного исправления для новой ошибки:

  1. Идентифицируем родительский объект и коллекцию. В данном случае, это ЗапросСертификат и его коллекция ЗапросСертификат.authentication.r13nClause.
  2. Изменяем способ создания вложенного объекта. Вместо использования общей ФабрикаXDTO, попробуем получить фабрику из объекта ЗапросСертификат и использовать её для создания RegionalizationClause.

Предполагаемое изменение кода может выглядеть следующим образом:


Если ДанныеУсловийПеремещения <> Неопределено Тогда
    Для Каждого ТекУсловие Из ДанныеУсловийПеремещения Цикл
        // Получаем фабрику из ЗапросСертификат для создания RegionalizationClause
        ЗапросУсловиеПеремещения = ЗапросСертификат.Фабрика().Создать("http://api.vetrf.ru/schema/cdm/mercury/vet-document/v2", "RegionalizationClause");
        СоответсвиеУсловиеПеремещения = Новый Соответствие;
        СоответсвиеУсловиеПеремещения.Вставить("condition/guid", ТекУсловие.УсловиеПеремещенияGUID);
        // Здесь ФабрикаВетисAPI должна быть либо ЗапросСертификат.Фабрикой(), либо совместимой
        ИнтеграцияВетисAPIСлужебный.ЗаполнитьСвойстваОбъектаXDTO(ЗапросСертификат.Фабрика(), ЗапросУсловиеПеремещения, СоответсвиеУсловиеПеремещения, "VetDocument", ОшибкиЗаполнения);
        ЗапросСертификат.authentication.r13nClause.Добавить(ЗапросУсловиеПеремещения);
    КонецЦикла;
КонецЕсли;

Важно убедиться, что ФабрикаВетисAPI, которая передается в процедуру ИнтеграцияВетисAPIСлужебный.ЗаполнитьСвойстваОбъектаXDTO, также является фабрикой, совместимой с ЗапросСертификат.Фабрика(). Возможно, после изменений в ИнтеграцияВетисAPIСлужебный, эта процедура теперь корректно обрабатывает внутренние свойства, но сам объект ЗапросУсловиеПеремещения должен быть создан в правильном контексте с самого начала.

Общие рекомендации при работе с XDTO-объектами на платформах 8.3.22+

Для предотвращения подобных ошибок и их оперативного устранения на платформах 8.3.22 и выше, рекомендуем придерживаться следующих практических советов:

  1. Всегда используйте фабрику родительского объекта: При создании вложенных XDTO-объектов или объектов, которые будут присваиваться свойствам или добавляться в коллекции других XDTO-объектов, старайтесь получать фабрику через метод ОбъектРодитель.Фабрика(), а не использовать глобальную ФабрикаXDTO, если только вы не уверены в их совместимости.
  2. Внимательно отслеживайте трассировку стека: Каждая ошибка XDTO может указывать на новое место, где нарушается контекст фабрик. Трассировка стека — ваш главный инструмент для локализации проблемного кода.
  3. Тестируйте после каждого обновления платформы: Особенно если ваша конфигурация активно использует интеграцию через XDTO. Изменения в поведении платформы, как мы видим, могут существенно влиять на стабильность таких обменов.
  4. Рассмотрите расширения: Для типовых конфигураций (или тех, что когда-то были типовыми, как «1С:УВС») могут существовать готовые расширения, исправляющие известные проблемы совместимости с новыми версиями платформы. Например, для ошибки condition в «1С:УВС» упоминаются расширения на Инфостарте, хотя для их установки может потребоваться отключение безопасного режима.
  5. Будьте готовы к ручной доработке: Если конфигурация не поддерживается активно (например, «1С:Управление ветеринарными сертификатами» снята с продаж с 1 ноября 2020 года), то разработчику придется самостоятельно адаптировать код под новые версии платформы. Это требует хорошего понимания механизмов XDTO и архитектуры интеграции.
  6. Используйте актуальные конфигурации: Если есть возможность, рассмотрите переход на более новые типовые конфигурации 1С (например, 1С:Розница, 1С:Управление торговлей, 1С:Бухгалтерия), которые продолжают активно поддерживать интеграцию с ФГИС Меркурий и обновляются с учетом изменений платформы.

Заключение

Ошибка «Фабрика XDTO текущего контекста не совпадает с фабрикой, в рамках которой был создан объект» — это характерная проблема платформы 1С:Предприятие версии 8.3.22 и выше, требующая внимательного подхода к созданию и управлению XDTO-объектами. Основной принцип решения заключается в обеспечении того, чтобы вложенные объекты создавались с использованием фабрики родительского объекта. Хотя это может потребовать изменений в нескольких местах кода, последовательное применение этого подхода позволит восстановить работоспособность интеграционных механизмов.

Мы настоятельно рекомендуем тщательно тестировать все изменения и, по возможности, консультироваться с актуальной документацией 1С или сообществом разработчиков, чтобы быть в курсе последних изменений в поведении платформы.

← На главную