Как правильно передавать данные и перечисления через веб-сервисы 1С без пакета current-config?

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

При интеграции 1С со сторонними системами (например, клиентскими приложениями на Java) через веб-сервисы (SOAP/WSDL), разработчики часто сталкиваются с проблемой огромного размера WSDL-файла. Разберем типичную ситуацию: в XDTO-пакете для передачи кастомной модели данных используется ссылка на перечисление из стандартного пространства имен http://v8.1c.ru/8.1/data/enterprise/current-config. В результате при генерации WSDL клиентское приложение получает описание тысяч внутренних типов данных 1С, включая вложенные пакеты core и enterprise. Проанализируем, почему это происходит и как правильно организовать передачу данных, чтобы стороннее приложение получало только нужные DTO-объекты.

Почему пакет current-config не подходит для внешних интеграций?

Рассмотрим подробнее назначение системных пакетов XDTO в платформе 1С. Пакет current-config — это, как следует из его названия, полное описание всех типов метаданных текущей конфигурации. Пакеты core и enterprise содержат базовые типы платформы. Если вы работаете с крупной конфигурацией (например, ERP), количество типов в этих пакетах исчисляется тысячами.

Использование current-config в веб-сервисах оправдано только в специфических случаях:

  1. Когда необходимо обмениваться данными между базами с абсолютно идентичной конфигурацией (например, в распределенных информационных базах — РИБ).
  2. Для сериализации объекта с целью его последующего восстановления в этой же базе (сохранение настроек, реализация сложного внешнего версионирования объектов).

Для интеграции со сторонними системами передача объектов платформы напрямую — это антипаттерн. Если ссылаться на типы конфигурации, система автоматической сериализации действительно может преобразовать объект 1С в XML одной строкой, но ценой экспорта всей схемы базы данных наружу. Стороннему клиенту эти тысячи моделей данных не нужны и лишь усложняют генерацию классов на их стороне.

Создание правильного независимого XDTO пакета

Выясним, как грамотно спроектировать обмен. Золотое правило интеграции: необходимо создавать собственный пакет XDTO, описывая в нем только те структуры (DTO-классы), которые действительно нужно отдать сторонней системе. В этот пакет нельзя добавлять типы данных из дерева конфигурации.

Создадим свои типы непосредственно в пакете XDTO. Важно, чтобы они опирались только на простые примитивные типы (такие как string, int, boolean) из стандартного пространства имен http://www.w3.org/2001/XMLSchema. Никаких ссылок на current-config быть не должно.

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


// Получаем данные из базы 1С
Результат = СписокЗаказовПокупателей(ДатаНачала, ДатаОкончания, Параметры, Ошибка, ТекстОшибки);

// Инициализируем типы из нашего кастомного независимого пакета
XDTO_TypeOrder = ФабрикаXDTO.Тип(XDTO_URI, "Order");
XDTO_TypeOrderList = ФабрикаXDTO.Тип(XDTO_URI, "OrderList");

// Создаем корневой объект списка
OrderListXDTO = ФабрикаXDTO.Создать(XDTO_TypeOrderList);

// В цикле "накачиваем" XDTO данными из результата запроса/функции
Для каждого элРезультат Из Результат Цикл
    OrderXDTO = ФабрикаXDTO.Создать(XDTO_TypeOrder);
    
    // Заполняем простые поля (строки, числа, даты)
    OrderXDTO.number = элРезультат.Номер;
    OrderXDTO.date = элРезультат.Дата;
    OrderXDTO.customer = элРезультат.Контрагент;
    OrderXDTO.summa = элРезультат.Сумма;
    OrderXDTO.organization = элРезультат.Организация;
    OrderXDTO.manager = элРезультат.Ответственный;
    OrderXDTO.department = элРезультат.Подразделение;
    OrderXDTO.comment = элРезультат.Комментарий;
    
    // Добавляем заполненный объект в список
    OrderListXDTO.Order.Добавить(OrderXDTO);
КонецЦикла; 

Как передать перечисление (Enum) клиенту в виде строгого типа?

Теперь разберем самый интересный нюанс — передачу перечислений (Enums). В 1С значение типа ПеречислениеСсылка можно легко преобразовать в строковый идентификатор с помощью функции XMLСтрока(). Но если мы просто определим в нашем XDTO пакете поле с типом string, то клиентское приложение (например, на Java) тоже сгенерирует это поле как обычную строку (String).

Проблема такого подхода в том, что теряется строгая типизация. В строковое поле можно передать что угодно, а хотелось бы, чтобы на стороне клиента сгенерировался строгий Java Enum, исключающий передачу некорректных статусов.

Чтобы решить эту задачу, применим механизм Фасетов (ограничений типа) в XDTO. Проанализируем по шагам, как это правильно настроить:

  1. Создание типа значения. Откроем наш кастомный пакет XDTO в дереве метаданных. Перечисления должны описываться не как «Типы объектов» (ObjectType), а как «Типы значений» (ValueType). Создадим новый тип значения, например, OrderStatusEnum.
  2. Выбор базового типа. В свойствах созданного типа значения найдем поле «Базовый тип» и укажем стандартную строку — тип string из пространства имен http://www.w3.org/2001/XMLSchema.
  3. Настройка фасетов. В свойствах этого типа значений найдем свойство «Фасеты». Фасеты позволяют наложить ограничения на базовый тип. Выберем фасет с типом «Перечисление» (Enumeration).
  4. Заполнение значений фасета. В настройках фасета вручную построчно пропишем строковые идентификаторы, которые разрешены для этого поля (например: Wait, Processed, Canceled). Эти значения должны строго совпадать с тем, что возвращает функция XMLСтрока() для соответствующих элементов перечисления 1С.

В коде обработчика веб-сервиса присвоение значения такому полю будет выглядеть стандартно:

OrderXDTO.status = XMLСтрока(элРезультат.СтатусЗаказа);

Что это дает? При таком подходе ФабрикаXDTO сама проверит, входит ли полученная строка в список разрешенных в фасете значений. А главное — при публикации веб-сервиса платформа 1С корректно сгенерирует в WSDL/XSD схеме классическое ограничение типа (restriction). В XML-разметке контракта это преобразуется в блок с тегами enumeration.

Когда генераторы кода на стороне Java (например, утилита wsimport) прочитают такой WSDL, они автоматически распознают паттерн ограничения строки и создадут в клиентском коде полноценный строгий Enum. Клиент больше не увидит внутренностей пакета current-config, но при этом получит жесткий контракт с конечным набором допустимых статусов.

← На главную