Документация по разработке bpm’online
PDF
Документация по разработке
Описание платформы

Sandbox. Обмен сообщениями между модулями

Glossary Item Box

Общие сведения

Модуль в bpm'online является изолированной программной единицей. Ему ничего не известно об остальных модулях системы, кроме списка имен модулей, от которых он сам зависит. Подробнее модули bpm'online описываются в статье "Принципы модульной разработки в bpm'online".

Для организации взаимодействия разрозненных модулей между собой предназначен специальный объект — sandbox. Одним из ключевых механизмов, предоставляемых sandbox, является механизм обмена сообщениями между модулями.

Модули могут общаться друг с другом только посредством сообщений. Модуль, которому требуется сообщить об изменении своего состояния другим модулям в системе, публикует сообщение. Если модулю необходимо получать сообщения об изменении состояний других модулей, он должен быть подписанным на эти сообщения.

Чтобы модуль мог взаимодействовать с другими модулями системы, он должен импортировать в качестве зависимости модуль sandbox.

К СВЕДЕНИЮ

Указывать базовые модули в зависимостях ["ext-base", "terrasoft", "sandbox"] не обязательно, если модуль экспортирует конструктор класса. Объекты Ext, Terrasoft и sandbox после создания объекта класса модуля будут доступны как свойства объекта: this.Ext, this.Terrasoft, this.sandbox.

Регистрация сообщений

Чтобы модули могли обмениваться сообщениями, сообщения необходимо зарегистрировать.

К СВЕДЕНИЮ

Регистрация сообщений выполняется автоматически, если они объявлены в свойстве messages модуля.

Для регистрации сообщений модуля предназначен метод sandbox.registerMessages(messageConfig), где messageConfig — конфигурационный объект сообщений модуля.

Конфигурационный объект является коллекцией "ключ-значение", в которой каждый элемент имеет следующий вид:

"MessageName": {
    mode: [Режим работы сообщения],
    direction: [Направление сообщения]
}

Здесь "MessageName" — ключ элемента коллекции, содержащий имя сообщения. Значением является конфигурационный объект, содержащий два свойства:

  • mode — режим работы сообщения. Должно содержать значение перечисления Terrasoft.MessageMode (Terrasoft.core.enums.MessageMode).
  • direction — направление сообщения. Должно содержать значение перечисления Terrasoft.MessageDirectionType (Terrasoft.core.enums.MessageDirectionType).

Режимы обмена сообщениями (свойство mode):

  • Широковещательный — режим работы сообщения, при котором количество подписчиков заранее неизвестно. Соответствует значению перечисления Terrasoft.MessageMode.BROADCAST.
  • Адресный — режим работы сообщения, при котором сообщение может быть обработано только одним подписчиком. Соответствует значению перечисления Terrasoft.MessageMode.PTP.

ВАЖНО

В адресном режиме подписчиков может быть несколько, но сообщение обработает только один, как правило, последний зарегистрированный подписчик.

Направления сообщения (свойство direction):

  • Публикация — модуль может только опубликовать сообщение в sandbox. Соответствует значению перечисления Terrasoft.MessageDirectionType.PUBLISH.
  • Подписка — модуль может только подписаться на сообщение, опубликованное из другого модуля. Соответствует значению перечисления Terrasoft.MessageDirectionType.SUBSCRIBE.
  • Двунаправленное — позволяет публиковать и подписываться на одно и то же сообщение в разных экземплярах одного и того же класса или в рамках одной и той же иерархии наследования схем (см. "Sandbox. Двунаправленные сообщения"). Соответствует значению перечисления Terrasoft.MessageDirectionType.BIDIRECTIONAL.

Пример регистрации сообщений модуля:

// Коллекция конфигурационных объектов сообщений.
var messages = {
    "MessageToSubscribe": {
        mode: Terrasoft.MessageMode.PTP,
        direction: Terrasoft.MessageDirectionType.SUBSCRIBE
    },
    "MessageToPublish": {
        mode: Terrasoft.MessageMode.BROADCAST,
        direction: Terrasoft.MessageDirectionType.PUBLISH
    }
};
// Регистрация сообщения.
this.sandbox.registerMessages(messages);

ВАЖНО

В схемах модели представления регистрировать сообщения с помощью метода sandbox.registerMessages() не нужно. Достаточно объявить конфигурационный объект сообщений в свойстве messages (см. "Сообщения. Свойство messages").

Для отказа от регистрации сообщений в модуле можно воспользоваться методом sandbox.unRegisterMessages(messages), где messages — имя или массив имен сообщений. Пример отмены регистрации сообщения:

// Отмена регистрации единичного сообщения.
this.sandbox.unRegisterMessages("MessageToSubscribe");
// Отмена регистрации массива сообщений.
this.sandbox.unRegisterMessages(["MessageToSubscribe", "MessageToPublish"]);

Добавление сообщений в схему модуля

Зарегистрировать сообщения можно также, добавив их в схему модуля с помощью дизайнера (см. "Дизайнер модуля").

Для добавления сообщения в схему модуля:

1. На вкладке [Структура] ([Structure]) дизайнера схемы модуля выделите узел [Messages] и, кликнув по нему правой кнопкой, выполните команду [Добавить] ([Add]) (рис. 1)

Рис. 1. — Добавление сообщения в структуру схемы модуля

2. Для добавленного сообщения установите необходимые свойства (рис. 2):

  • [Название] ([Name]) — имя сообщения, совпадающее с ключом в конфигурационном объекте модуля.
  • [Направление] ([Direction]) — направление сообщения. Возможные значения "Подписка" ("Follow") и "Публикация" ("Publish").
  • [Режим] ([Mode]) — режим работы сообщения. Возможные значения "Широковещательное" ("Broadcast") и "Адрес" ("Address").

Рис. 2. — Свойства сообщения

ВАЖНО

В схемах модели представления добавлять сообщения в структуру схемы не нужно.

Публикация сообщения

Для публикации сообщения предназначен метод sandbox.publish(messageName , messageArgs, tags).

Параметры метода:

  • messageName — строка, содержащая имя сообщения, например, "MessageToSubscribe".
  • messageArgs — объект, передаваемый в качестве аргумента в метод-обработчик сообщения в модуле-подписчике. Если в методе-обработчике нет входящих параметров, то параметру messageArgs необходимо присвоить значение null.
  • tags — массив тегов, позволяющий однозначно определить модуль, отправляющий сообщение. Как правило, используется значение [this.sandbox.id]. По массиву тегов sandbox определяет подписчиков и публикаторов сообщения.

К СВЕДЕНИЮ

Для сообщения, опубликованного с массивом тегов, будут вызваны только те обработчики, для которых совпадает хотя бы один тег. Сообщения, опубликованные без тегов, смогут обработать только подписчики без тегов.

Примеры вызова метода публикации сообщения:

// Публикация сообщения без аргумента и тегов.
this.sandbox.publish("MessageWithoutArgsAndTags");
// Публикация сообщения без аргументов для метода-обработчика.
this.sandbox.publish("MessageWithoutArgs", null, [this.sandbox.id]);
// Публикация сообщения с аргументом для метода-обработчика.
this.sandbox.publish("MessageWithArgs", {arg1: 5, arg2: "arg2"}, ["moduleName"]);
// Публикация сообщения с произвольным массивом тегов.
this.sandbox.publish("MessageWithCustomIds", null, ["moduleName","otherTag"]);

При публикации сообщения в адресном режиме можно получить результат его обработки подписчиком. Для этого метод-обработчик сообщения в модуле-подписчике должен вернуть соответствующий результат (см. "Подписка на сообщение"). Пример публикации такого сообщения:

// Объявление и регистрация сообщения.
var messages = {
    "MessageWithResult": {
        mode: Terrasoft.MessageMode.PTP,
        direction: Terrasoft.MessageDirectionType.PUBLISH
    }
};
this.sandbox.registerMessages(messages);
// Публикация сообщения и получение результата его обработки подписчиком.
var result = this.sandbox.publish("MessageWithResult", {arg1:5, arg2:"arg2"}, ["resultTag"]);
// Вывод результата в консоль браузера.
console.log(result);

При публикации сообщения в широковещательном режиме результат его обработки можно получить через объект, передаваемый в качестве аргумента для метода-обработчика:

// Объявление и регистрация сообщения.
var messages = {
    "MessageWithResult": {
        mode: Terrasoft.MessageMode.BROADCAST,
        direction: Terrasoft.MessageDirectionType.PUBLISH
    }
};
this.sandbox.registerMessages(messages);
var arg = {};
// Публикация сообщения и получение результата его обработки подписчиком.
// В методе-обработчике подписчика в объект нужно добавить свойство result,
// в которое следует записать результат обработки.
this.sandbox.publish("MessageWithResult", arg, ["resultTag"]);
// Вывод результата в консоль браузера.
console.log(arg.result);

Подписка на сообщение

Подписаться на сообщение можно, используя метод sandbox.subscribe(messageName, messageHandler, scope, tags).

Параметры метода:

  • messageName — строка, содержащая имя сообщения, например, "MessageToSubscribe".
  • messageHandler — метод-обработчик, вызываемый при получении сообщения. Это может быть анонимная функция или метод модуля. В определении метода может быть указан параметр, значение которого должно быть передано при публикации сообщения с помощью метода sandbox.publish().
  • scope — контекст выполнения метода-обработчика messageHandler.
  • tags— массив тегов, позволяющий однозначно определить модуль, который отправляет сообщение. По массиву тегов sandbox определяет подписчиков и публикаторов сообщения.

Примеры вызова метода подписки на сообщение:

// Подписка на сообщение без аргументов для метода-обработчика.
// Метод-обработчик — анонимная функция. Контекст выполнения — текущий модуль.
// Метод getsandboxid() должен вернуть тег, совпадающий с тегом опубликованного сообщения.
this.sandbox.subscribe("MessageWithoutArgs", function(){console.log("Message without arguments")}, this, [this.getSandBoxId()]);
// Подписка на сообщение с аргументом для метода-обработчика.
this.sandbox.subscribe("MessageWithArgs", function(args){console.log(args)}, this, ["moduleName"]);
// Подписка на сообщение с произвольным тегом.
// Тег может быть любым из массива тегов опубликованного сообщения.
// Метод-обработчик myMsgHandler должен быть реализован отдельно.
this.sandbox.subscribe("MessageWithCustomIds", this.myMsgHandler, this, ["otherTag"]);

Для сообщения в адресном режиме метод-обработчик сообщения должен вернуть соответствующий результат. Пример подписки на такое сообщение:

// Объявление и регистрация сообщения.
var messages = {
    "MessageWithResult": {
        mode: Terrasoft.MessageMode.PTP,
        direction: Terrasoft.MessageDirectionType.SUBSCRIBE
    }
};
this.sandbox.registerMessages(messages);
// Подписка на сообщение.
this.sandbox.subscribe("MessageWithResult", this.onMessageSubscribe, this, ["resultTag"]);
...            
// Метод-обработчик реализован в модуле-подписчике.
// args — объект, передаваемый при публикации сообщения.
onMessageSubscribe: function(args) {
    // Изменение параметра.
    args.arg1 = 15;
    args.arg2 = "new arg2";
    // Обязательный возврат результата.
    return args;
},

Асинхронный обмен сообщениями

Если метод-обработчик сообщения в модуле-подписчике генерирует результат асинхронно, то необходимо использовать подход с функцией обратного вызова (callback-функцией).

Пример публикации сообщения и получения результата:

this.sandbox.publish("AsyncMessageResult",
//Объект, передаваемый как аргумент функции-обработчика в подписчике.
{
    // Функция обратного вызова.
    callback: function(result) {
        this.Terrasoft.showInformation(result);
    },
    // Контекст выполнения функции обратного вызова.
    scope: this
});

Пример подписки на сообщение:

this.sandbox.subscribe("AsyncMessageResult",
// Функция-обработчик сообщения
function(config) {
    // Обработка входящего параметра.
    var config = config || {};
    var callback = config.callback;
    var scope = config.scope || this;
    // Подготовка результирующего сообщения.
    var result = "Message from callback function";
    // Выполнение функции обратного вызова.
    if (callback) {
        callback.call(scope, result);
    }
},
// Контекст выполнения функции-обработчика сообщения.
 this);

Пример модуля, использующего сообщения

Пример модуля, в котором реализована публикация и подписка на сообщение, приведен ниже:

define("UsrSomeModule", [], function() {
    Ext.define("Terrasoft.configuration.UsrSomeModule", {
        alternateClassName: "Terrasoft.UsrSomeModule",
        extend: "Terrasoft.BaseModule",
        Ext: null,
        sandbox: null,
        Terrasoft: null,
        messages: {
            "MessageToSubscribe": {
                mode: Terrasoft.MessageMode.PTP,
                direction: Terrasoft.MessageDirectionType.SUBSCRIBE
            },
            "MessageToPublish": {
                mode: Terrasoft.MessageMode.BROADCAST,
                direction: Terrasoft.MessageDirectionType.PUBLISH
            }
        },
        init: function() {
            this.callParent(arguments);
            this.sandbox.registerMessages(this.messages);
            this.processMessages();
        },
        processMessages: function() {
            this.sandbox.subscribe("MessageToSubscribe", this.onMessageSubscribe, this);
            this.sandbox.publish("MessageToPublish", null, [this.sandbox.id]);
        },
        onMessageSubscribe: function() {
            console.log("'MessageToSubscribe' received");
        },
        destroy: function() {
            if (this.messages) {
                var messages = this.Terrasoft.keys(this.messages);
                this.sandbox.unRegisterMessages(messages);
            }
            this.callParent(arguments);
        }
    });
    return Terrasoft.UsrSomeModule;
});

Смотрите также

© Terrasoft 2002-2019.

Был ли данный материал полезен?

Как можно улучшить эту статью?