Важнейшей составляющей инфраструктуры сообщений являются сами сообщения. Как уже отмечалось, сообщения передаются в рамках плана обмена от одного узла другому. То есть каждое сообщение точно ассоциировано с планом обмена, имеет одного отправителя и одного получателя.
Рассмотрим, что такое сообщение. Сообщение оформляется как документ XML, имеющий определенную структуру. В качестве примера рассмотрим следующее сообщение (листинг 3.13).
Листинг 3.13. Пример сообщения обмена
<v8msg:Message xmlns:v8msg="http://v8.1c.ru/messages">
<v8msg:Header>
<v8msg:ExchangePlan>УдаленныеСклады</v8msg:ExchangePlan>
<v8msg:To>Оптовый</v8msg:To>
<v8msg:From>ЦентрОфис</v8msg:From>
<v8msg:MessageNo>20</v8msg:MessageNo>
<v8msg:ReceivedNo>15</v8msg:ReceivedNo>
</v8msg:Header>
<v8msg:Body>
<!— Тело сообщения -->
</v8msg:Body>
</v8msg:Message>
Все сообщение находится внутри элемента XML с именем Message, относящимся к пространству имен http://v8.1c.ru/messages. Сообщение делится на заголовок Header и тело сообщения Body. Оба относятся к пространству имен http://v8.1c.ru/messages.
Структура заголовка жестко задана. Информация заголовка представлена в нескольких элементах XML, вложенных в элемент Header. Все элементы, вложенные в элемент Header, относятся к пространству имен http://v8.1c.ru/messages.
Тело сообщения содержится в элементе XML с именем Body, относящимся к пространству имен http://v8.1c.ru/messages. Данный элемент может иметь произвольное содержимое, определяемое прикладными потребностями. Инфраструктурой сообщений содержимое тела сообщения никак не регламентируется.
Сообщение для выгрузки данных может быть создано следующим образом (листинг 3.14).
Листинг 3.14. Пример сообщения для выгрузки данных
ЗаписьXML = Новый ЗаписьXML();
ЗаписьXML.ОткрытьФайл("c:\temp\выгрузка.xml");
ЗаписьXML.ЗаписатьОбъявлениеXML();
Узел = ПланыОбмена.УдаленныеСклады.НайтиПоКоду("Оптовый");
// Создать объект "ЗаписьСообщенияОбмена".
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, Узел);
// Записать тело сообщения.
// …
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть();
Выгрузка данных сопровождается созданием объекта типа ЗаписьСообщенияОбмена (переменная ЗаписьСообщения). Сразу после создания этот объект еще «не знает» своего номера, получателя и т. п. Вся подобная информация указывается при выполнении метода НачатьЗапись(). В качестве первого параметра передается объект ЗаписьXML, в качестве второго – ссылка на узел плана обмена (ссылка на получателя).
При выполнении этого метода сообщению присваивается номер, определяемый как номер предыдущего отправленного сообщения, увеличенный на 1 (информация берется из узла-получателя). Производится запись в XML-документ заголовка сообщения, а также записывается начало элемента XML, соответствующего телу сообщения. Устанавливается блокировка на запись базы данных, соответствующая узлу плана обмена.
Завершить запись сообщения можно с помощью двух методов объекта ЗаписьСообщенияОбмена:
Вызов метода ПрерватьЗапись() прерывает запись сообщения, при этом оно считается неотправленным (счетчик отправленных сообщений в итоге не увеличивается). Неявный вызов этого метода происходит также в случае повторного вызова метода НачатьЗапись() (без последующего вызова метода ЗакончитьЗапись()) либо при разрушении (окончании времени жизни переменной, связанной с объектом) объекта ЗаписьСообщенияОбмена.
Метод ЗакончитьЗапись() осуществляет нормальное завершение записи сообщения. В этом случае в сообщение записывается конец элемента XML (представляющего тело сообщения). В узел плана обмена записывается номер сообщения обмена данными. С записи узла плана обмена снимается блокировка, и сообщение считается отправленным.
Для чтения записанного в файл сообщения обмена в базе узла-получателя может использоваться следующий фрагмент кода (листинг 3.15).
Листинг 3.15. Пример чтения сообщения обмена
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл("c:\temp\выгрузка.xml");
// Создать объект "ЧтениеСообщенияОбмена".
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(ЧтениеXML, ДопустимыйНомерСообщения.Больший);
// Прочитать тело сообщения.
// …
ЧтениеСообщения.ЗакончитьЧтение();
ЧтениеXML.Закрыть();
После открытия XML-документа, содержащего сообщение, создается объект ЧтениеСообщенияОбмена. Чтение данных начинается с выполнения метода НачатьЧтение() объекта ЧтениеСообщенияОбмена. При этом производится чтение заголовка сообщения обмена данными, проверяются содержащиеся в заголовке данные. Если какие-либо данные указаны неправильно (задан неизвестный план обмена, указан узел, не входящий в план обмена, номер сообщения не соответствует ожидаемому), инициируется исключение.
При начале чтения сообщения устанавливается блокировка на запись узла плана обмена. Используя второй параметр метода, можно установить вариант ожидаемого номера сообщения:
Следует обратить внимание на тот факт, что в приведенном фрагменте кода нет ни указания на используемый план обмена (их в конфигурации может быть несколько), ни указания на узел-отправитель. Данная информация получается из заголовка сообщения (в случае невозможности определения, как и было сказано выше, возникает исключение).
Завершить чтение сообщения можно с использованием двух методов:
Обращение к методу ПрерватьЧтение() вызывает немедленное прерывание чтения сообщения. Блокировка с записи узла плана обмена снимается. В соответствующий узел плана обмена не вносится никаких изменений (не изменяется номер последнего принятого сообщения). Этот же метод вызывается неявно при разрушении (окончании времени жизни переменной, связанной с данным объектом) объекта ЧтениеСообщенияОбмена или перед повторным вызовом метода НачатьЧтение().
Выполнение метода ЗакончитьЧтение() вызывает попытку нормального завершения чтения сообщения. При этом проверяется нормальное завершение сообщения (текущим элементом в объекте ЧтениеXML является конец элемента, реализующего само сообщение). Номер принятого сообщения помещается в реквизит НомерПринятого узла плана обмена. Блокировка записи узла плана обмена снимается, и сообщение считается принятым.