Разберем распространенную и коварную проблему при разработке серверных механизмов обмена данными: при выполнении методов СериализаторXDTO.ПрочитатьXML() или Ссылка.ПолучитьОбъект() фоновое задание мгновенно падает. При этом стандартная конструкция Попытка ... Исключение не срабатывает, сеанс аварийно прерывается, а весь процесс обмена останавливается.
Проанализируем детально, почему так происходит на платформе 1С, как устранить ошибку и какие есть способы обойти подобное поведение системы.
В платформе 1С компиляция модулей объектов выполняется по принципу «ленивой» (отложенной) загрузки. Исходный код модуля компилируется сервером в исполняемый байт-код не в момент старта системы, а только тогда, когда в памяти физически создается первый экземпляр объекта. Это происходит при вызовах СоздатьЭлемент(), Ссылка.ПолучитьОбъект(), а также при десериализации через СериализаторXDTO.ПрочитатьXML(), когда платформа восстанавливает тип СправочникОбъект.
Если в коде модуля объекта присутствует вызов клиентских процедур (например, Предупреждение(), ОткрытьФорму() и т. п.), сервер на этапе компиляции выдает синтаксическую ошибку: «Процедура или функция с указанным именем не определена».
Ошибки компиляции модулей относятся к категории фатальных системных исключений платформы. В отличие от стандартных ошибок выполнения (деление на ноль, блокировка транзакции, обращение к несуществующему реквизиту), ошибка компиляции сразу прерывает выполнение всего контекста потока. Она принципиально не перехватывается блоком Попытка ... Исключение, в результате чего фоновое задание аварийно завершается.
Рассмотрим популярные заблуждения, с которыми сталкиваются разработчики при попытке обойти этот сбой:
ОбменДанными.Загрузка = Истина не помогает. Данный флаг предназначен для отключения прикладных проверок и событий (таких как ПередЗаписью или ПриЗаписи). Однако компиляция модуля происходит в момент инициализации объекта в памяти еще до того, как управление дойдет до установки этого свойства.СправочникОбъект, ДокументОбъект) без компиляции его модуля на стороне сервера.Самое правильное и надежное решение — устранить синтаксические ошибки в модулях объектов, сделав код совместимым с серверным контекстом. Разберем этот процесс по шагам:
Предупреждение()) в модулях объектов и обернем их в директивы препроцессора:
#Если Клиент Тогда
Предупреждение("Сообщение для пользователя");
#КонецЕсли
Если база данных находится на типовой поддержке и прямое редактирование модулей запрещено, воспользуемся механизмом расширений:
&Вместо, исключив вызов клиентских модальных методов или обернув его директивой препроцессора.Если цель фонового задания — прочитать данные из файла обмена и обойти падение при десериализации, рассмотрим альтернативные инструменты чтения XML, которые не компилируют модуль объекта:
ФабрикаXDTO.ПрочитатьXML вместо СериализаторXDTO. В отличие от СериализаторXDTO, который пытается напрямую создать прикладной тип 1С (вызывая загрузку модуля), ФабрикаXDTO десериализует данные в универсальный тип ОбъектXDTO. Модуль объекта метаданных при этом не задействуется, и ошибка компиляции не возникает. Из объекта XDTO можно вручную получить значения реквизитов и табличных частей.ЧтениеXML или ДокументDOM. Потоковый или объектный парсинг XML-документа работает исключительно со строковыми узлами и атрибутами без обращения к контексту метаданных, что гарантирует стабильность выполнения фонового потока.Если в процессе регулярного обмена требуется обрабатывать объекты, в модулях которых потенциально могут быть критические ошибки, используем изоляцию выполнения:
СериализаторXDTO.ПрочитатьXML() или обработку отдельного проблемного элемента в дочернее фоновое задание с помощью метода ФоновыеЗадания.Выполнить().ФоновыеЗадания.ОжидатьЗавершения().Состояние полученного задания. Если возникла ошибка компиляции, аварийно завершится только дочерний сеанс (состояние СостояниеФоновогоЗадания.АварийноЗавершено).