Разработка HTTP-сервисов в среде 1С:Предприятие часто преподносит сюрпризы, которые сложно отловить стандартными методами. Одной из самых коварных проблем является ситуация, когда код внутри серверного вызова (HTTP-сервис, фоновое задание или внешнее соединение) просто прекращает выполнение на определенной строке без каких-либо сообщений об ошибках, игнорируя блоки Попытка...Исключение. Рассмотрим детально этот сценарий на примере создания элемента справочника ФизическиеЛица.
Представим ситуацию: в HTTP-сервисе выполняется стандартный код создания нового элемента. Программист видит, что процесс доходит до строки Объект = Справочники.ФизическиеЛица.СоздатьЭлемент();, и на этом месте отладка прерывается. Соединение закрывается, отладчик «вылетает», в Журнале регистрации (ЖР) пусто, а блок Исключение не отрабатывает.
Разберем, почему это происходит. Блок Попытка...Исключение предназначен для обработки ошибок времени выполнения (Runtime errors). Однако, когда мы вызываем метод СоздатьЭлемент(), платформа инициирует компиляцию модуля объекта этого справочника. Если в модуле содержится синтаксическая ошибка или обращение к недоступному в данном контексте (на сервере) общему модулю, происходит ошибка компиляции. В контексте HTTP-сервисов или фоновых заданий такая ошибка часто приводит к немедленному завершению потока выполнения, и управление просто не доходит до обработчика исключений.
Проанализируем фрагмент кода модуля объекта, который может стать причиной такого «молчаливого» отказа. Рассмотрим пример функции печати, обернутой в директиву препроцессора, которая была добавлена в модуль объекта справочника ФизическиеЛица:
#Если ТолстыйКлиентОбычноеПриложение Тогда
// Функция формирует табличный документ с данными физ. лица
Функция ПечатьДанныхФизЛица(ДатаАктуальности = Неопределено, ТабДокумент = Неопределено) Экспорт
Если ТабДокумент = Неопределено Тогда
ТабДокумент = Новый ТабличныйДокумент;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ФизЛицо", Ссылка);
// ... логика запроса ...
// Обращение к общему модулю, который может быть недоступен на сервере
УниверсальныеМеханизмы.НапечататьДокумент(ТабДокумент, 1, Ложь, "Данные", Ссылка);
Возврат ТабДокумент;
КонецФункции
#КонецЕсли
На первый взгляд кажется, что директива #Если ТолстыйКлиентОбычноеПриложение должна защитить серверный код (HTTP-сервис) от исполнения этой функции. Однако, если внутри этого блока затесалась синтаксическая ошибка (например, обращение к переменной, которая не определена, или опечатка в имени метода), компилятор 1С при попытке инициализировать объект на сервере может выдать критический сбой. Особенно часто это случается, если внутри модуля объекта есть обращения к общим модулям, у которых в свойствах стоит только флаг «Клиент». Платформа пытается проверить связи модуля, обнаруживает отсутствие метода в серверном контексте и «схлопывает» процесс.
Для надежной работы обмена данными через HTTP-сервисы мы должны следовать строгому алгоритму проверки данных перед созданием объекта. Рассмотрим правильный подход к реализации поиска и создания элемента:
Процедура ВыполнитьОбработкуДанных(СтруктураДанных, ЗапросСервиса)
// 1. Инициализируем соответствия и параметры
СоответствиеПолов = Новый Соответствие();
СоответствиеПолов.Вставить("Мужской", Перечисления.ПолФизическихЛиц.Мужской);
СоответствиеПолов.Вставить("Женский", Перечисления.ПолФизическихЛиц.Женский);
Для каждого СтрокаИзДанных Из СтруктураДанных Цикл
// Проверяем наличие ссылки, чтобы не плодить дубли
СсылкаНаФизЛицо = НайтиФизЛицоПоРеквизитам(СтрокаИзДанных);
Если СсылкаНаФизЛицо.Пустая() Тогда
// Если не нашли, создаем новый элемент
// Важно: здесь может произойти сбой, если модуль объекта "битый"
НовыйОбъект = Справочники.ФизическиеЛица.СоздатьЭлемент();
// Заполняем реквизиты, исключая системные (например, Код)
ЗаполнитьЗначенияСвойств(НовыйОбъект, СтрокаИзДанных, , "Код");
// Установка специфических значений через соответствия
НовыйОбъект.Пол = СоответствиеПолов.Получить(СтрокаИзДанных.Пол);
Попытка
НовыйОбъект.Записать();
СсылкаНаФизЛицо = НовыйОбъект.Ссылка;
Исключение
// Здесь мы поймаем ошибки записи (нарушение уникальности, проверки в ПередЗаписью)
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("HTTP.ЗагрузкаДанных",
УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
КонецПопытки;
КонецЕсли;
// Дальнейшая логика обработки...
КонецЦикла;
КонецПроцедуры
Если вы столкнулись с тем, что СоздатьЭлемент() «тормозит» или вылетает без ошибок, выполним следующие шаги для локализации проблемы:
Alt + F7). В настройках проверки обязательно оставьте включенным только чекбокс «Сервер». Если система выдаст ошибки — это и есть причина падения HTTP-сервиса.#Если...) и попробуйте выполнить СоздатьЭлемент(). Если ошибка исчезнет, постепенно раскомментируйте блоки, пока не найдете виновника.Важный момент: Имена переменных в 1С не рекомендуется начинать с подчеркивания (например, _ФизическоеЛицо). Хотя платформа это допускает, стандарты разработки 1С (ИТС) это запрещают, а в некоторых специфических режимах выполнения это может приводить к конфликтам с внутренними свойствами объектов платформы.
Подводя итог, проанализируем ситуацию еще раз: если отладка в HTTP-сервисе обрывается на создании объекта, всегда ищите проблему в статическом анализе модуля объекта. Сервер 1С крайне чувствителен к доступности процедур и функций в своем контексте, и малейшее нарушение правил компиляции приводит к мгновенному отказу всей транзакции HTTP-запроса.