При интеграции систем на платформе 1С с внешними веб-сервисами разработчики часто сталкиваются со специфическими ошибками сериализации. Одна из самых распространенных и неприятных проблем — ошибка несоответствия типов XDTO, сообщающая, что определенный тип пакета не найден в фабрике типов. В этой статье мы подробно проанализируем причину возникновения этой ошибки, выясним, почему стабильно работающий код может внезапно дать сбой, и рассмотрим несколько эффективных способов решения проблемы.
Рассмотрим ситуацию на конкретном примере. Предположим, мы пытаемся передать структуру параметров документа во внешний веб-сервис со следующим кодом:
УникальныйИдентификаторШаблона = Новый УникальныйИдентификатор("22722772-d2da-11e8-80e7-005056b836bc");
// Записываем параметры документа.
ПараметрыДокумента = Новый Структура();
ПараметрыДокумента.Вставить("Заголовок", БП.ЗапросДок);
ПараметрыДокумента.Вставить("Содержание", Обоснование);
ПараметрыДокумента.Вставить("Комментарий", "Добавлено автоматически из IDM");
ПараметрыДокумента.Вставить("ШаблонДокумента", УникальныйИдентификаторШаблона);
// ОТПРАВКА ДАННЫХ В WEB-СЕРВИС И ПОЛУЧЕНИЕ ОТВЕТА
ПараметрыДокументаXDTO = СериализаторXDTO.ЗаписатьXDTO(ПараметрыДокумента);
РезультатВыполненияXDTO = Прокси.AddInternalDocument(ПараметрыДокументаXDTO);
При выполнении последней строки система генерирует критическую ошибку:
«Несоответствие типов XDTO: Тип '{http://v8.1c.ru/8.1/data/enterprise/current-config}DocumentRef.ЗапросПрав' не найден. Тип принадлежит пакету, отсутствующему в фабрике типов XDTO».
Давайте разберем по шагам, почему это происходит. Пространство имен current-config (полный URI: http://v8.1c.ru/8.1/data/enterprise/current-config) — это динамический пакет XDTO, который платформа 1С автоматически создает «на лету» для описания метаданных текущей информационной базы (справочников, документов, перечислений и т. д.). Когда мы вызываем глобальный метод СериализаторXDTO.ЗаписатьXDTO(ПараметрыДокумента), платформа задействует системную глобальную фабрику XDTO. Поскольку в свойство Заголовок передана прямая ссылка на документ (ДокументСсылка.ЗапросПрав), глобальный сериализатор преобразует эту ссылку в сложный объект XDTO, принадлежащий пространству имен current-config.
Однако, когда мы передаем полученный объект ПараметрыДокументаXDTO в метод Прокси.AddInternalDocument(), платформа использует фабрику XDTO самого веб-сервиса (сформированную на основе импортированного WSDL-описания). Эта фабрика ничего не знает о метаданных нашей конкретной базы 1С — пакет current-config в ней отсутствует. В результате сопоставления типов происходит сбой, и платформа выбрасывает исключение.
Часто разработчики утверждают, что интеграция долгое время функционировала корректно без каких-либо изменений в коде. Проанализируем возможные причины внезапного появления этой проблемы:
Заголовок (или аналогичное ему) записывалось простое текстовое значение (например, строка с наименованием или номером документа). Простые типы данных (такие как строка, число, дата) сериализуются в стандартные типы XML Schema (пространство имен http://www.w3.org/2001/XMLSchema), которые по умолчанию поддерживаются любой фабрикой XDTO. Как только тип реквизита изменился на ссылку (DocumentRef), сериализатор попытался передать сложный объект 1С.Структура или Соответствие) может несколько различаться, особенно при передаче их в параметры с типом anyType.Существует три основных подхода к устранению данной ошибки, в зависимости от архитектурных требований вашей системы.
Если веб-сервис на принимающей стороне изначально спроектирован для работы с типами вашей конфигурации 1С, и эти типы описаны в его WSDL, нам необходимо использовать фабрику самого прокси-клиента, а не глобальную фабрику платформы. Для этого достаточно изменить строку сериализации данных, обратившись к свойству СериализаторXDTO нашего объекта Прокси:
// Заменяем глобальный сериализатор на сериализатор конкретного WS-прокси
ПараметрыДокументаXDTO = Прокси.СериализаторXDTO.ЗаписатьXDTO(ПараметрыДокумента);
РезультатВыполненияXDTO = Прокси.AddInternalDocument(ПараметрыДокументаXDTO);
Этот способ быстро решает проблему, но только при условии, что импортированная в конфигурацию WS-ссылка действительно содержит описание схемы current-config.
С точки зрения правильного проектирования интеграционных решений, внешние веб-сервисы не должны зависеть от внутренних типов и метаданных конфигурации 1С. Передача прямых ссылок (DocumentRef, CatalogRef) между независимыми системами считается плохой практикой.
Мы рекомендуем передавать уникальные идентификаторы документов в виде обычных строковых значений. Если на принимающей стороне также развернута база 1С, она сможет легко найти или создать документ по полученному строковому представлению UUID. Модифицируем наш исходный код следующим образом:
УникальныйИдентификаторШаблона = Новый УникальныйИдентификатор("22722772-d2da-11e8-80e7-005056b836bc");
ПараметрыДокумента = Новый Структура();
// Вместо прямой ссылки 1С передаем строковое представление GUID
ПараметрыДокумента.Вставить("Заголовок", Строка(БП.ЗапросДок.УникальныйИдентификатор()));
ПараметрыДокумента.Вставить("Содержание", Обоснование);
ПараметрыДокумента.Вставить("Комментарий", "Добавлено автоматически из IDM");
ПараметрыДокумента.Вставить("ШаблонДокумента", Строка(УникальныйИдентификаторШаблона));
// Теперь сериализация пройдет успешно, так как структура содержит только базовые типы (строки)
ПараметрыДокументаXDTO = СериализаторXDTO.ЗаписатьXDTO(ПараметрыДокумента);
РезультатВыполненияXDTO = Прокси.AddInternalDocument(ПараметрыДокументаXDTO);
Использование строк вместо сложных объектов 1С полностью исключает возникновение ошибок пространства имен current-config и делает интеграцию максимально надежной и гибкой к изменениям метаданных в любой из баз.
Если веб-сервис разработан вами в другой информационной базе 1С и вы имеете к нему доступ для редактирования, можно явно разрешить использование типов текущей конфигурации. Для этого выполните следующие шаги в конфигураторе базы, где опубликован веб-сервис:
http://v8.1c.ru/8.1/data/enterprise/current-config.Важное предупреждение: Помните, что использование динамического пакета current-config в межбазовом обмене имеет серьезный недостаток. Если одна из конфигураций обновится (например, добавятся или удалятся реквизиты документа ЗапросПрав), структура пакета изменится, что снова приведет к ошибкам десериализации данных. Поэтому для долгосрочных интеграционных проектов всегда правильнее создавать собственные статические XDTO-пакеты с фиксированной структурой данных, состоящей из простых типов.