Способы интеграции ================== Существует два основных подхода для интеграции с Synergy: * Прямая интеграция — интеграционные модули разрабатываются с использованием API Synergy и интегрируемых систем. Синхронизация данных между системами и координация обмена между ними остаётся за разработчиком интеграционного модуля * Событийная интеграция — когда какая-либо из подсистем Synergy генерирует различные события, связанные с какими-либо данными. Обработчики этих событий (на стороне Synergy) при необходимости преобразовывают данные событий и передают их интегрируемой системе через какой-либо транспортный уровень Прямая интеграция ----------------- ARTA Synergy предоставляет API для доступа к своим функциям с помощью rest сервисов. Описание методов REST API можно найти в `данном разделе `_. Авторизация для всех методов API — ``Basic HTTP``. .. _event-integration: Событийная интеграция --------------------- Под «событием» мы будем подразумевать сообщение о каком-либо изменении в ARTA Synergy, содержащее тип события и минимально необходимые для получения связанной с событием информации либо воздействия на Synergy данные. Обработчик события (или событий) — программный модуль, читающий сообщения о событиях из ``JMS Queue`` или ``JMS Topic`` и осуществляющий, при необходимости, доступ к экземпляру Synergy, сгенерировавшему сообщение, с помощью API Synergy. Обработчик событий является отдельным от ARTA Synergy приложением, которое может работать как на том же сервере приложений, что и ARTA Synergy, так и на удалённом. Кроме этого, обработчик события может иметь собственные конфигурационные файлы, необходимые для реализации целевого назначения. Обработчик событий может обрабатывать как конкретное событие (например, ``event.registers.formdata.add``), так и класс событий (например, ``event.registers.*``). Обработка события может происходить в 3 этапа: 1. Получение события 2. Получение и преобразование необходимых обработчику данных 3. Передача сформированного пакета данных далее (опционально) ARTA Synergy генерирует событие в случае, если для этого события настроены обработчики. Обработчики событий настраиваются в конфигурационном файле ``${jboss.home}/standalone/configuration/arta/api-observation-configuration.xml``. .. note:: При установке Synergy файл ``{$jboss.home}/standalone/configuration/arta/api-observation-configuration.xml`` по умолчанию не создается. Создаете файл ``api-observation-configuration.xml`` в директории ``{$jboss.home}/standalone/configuration/arta/`` с содержимым: .. code-block:: xml список листенеров<--> Указываете владельца файла: .. code-block:: bash chown -R jboss:synergy /opt/synergy/jboss/standalone/configuration/arta/api-observation-configuration.xml Затем можете добавлять листенеры в файл. Сообщение, помещаемое в очередь ``JMS``, представляет собой экземпляр ``javax.jms.TextMessage``. Тело сообщения зависит от типа события, его описание можно посмотреть ниже среди описаний типов событий. Каждое событие содержит свойство ``api_event``, указывающее на тип события, вызвавшего его (содержимое тега ``event.registers.formdata.add`` в конфигурационном файле). Например: .. code-block:: xml java:jboss/queues/Synergy/UsersQueue event.users.* java:jboss/queues/Synergy/RegisterCreateDocQueue event.registers.formdata.add В этом примере настроены обработчики: 1. ``java:jboss/queues/Synergy/UsersQueue`` для всех событий класса ``event.users.*``, т.е. всех событий, связанных с пользователями: ``event.users.account.change``, ``event.users.formdata.change``, ``event.users.account.add`` и т.д. 2. ``java:jboss/queues/Synergy/RegisterCreateDocQueue`` для события добавления записи реестра ``event.registers.formdata.add``. Рассмотрим, например, код обработчика очереди ``UsersQueue``: .. code-block:: java @MessageDriven(name = "UsersQueue", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:jboss/queues/Synergy/UsersQueue"), @ActivationConfigProperty(propertyName = "reconnectAttempts", propertyValue = "32"), @ActivationConfigProperty(propertyName = "reconnectInterval", propertyValue = "4000"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class UsersMessagesListener implements MessageListener { public void onMessage(Message message) { //Получаем идентификатор пользователя, для которого //сгенерировано событие String userID = ((TextMessage) message).getText(); //Получаем тип события String eventType = message.getStringProperty("api_event"); //Выполнение действия по получению дополнительных данных через API //и прочих операций, зависящих от условий решаемой задачи } } В проекте `blocking-process-template `_ реализован пример обработчика очереди. Ниже описаны типы событий, которые могут быть сгенерированы ARTA Synergy. Для события ``[event.orgstructure.department.formdata.change]`` - идентификатор подразделения, для события ``[event.orgstructure.position.formdata.change]`` - идентификатор должности, для события ``[event.users.formdata.change]`` - идентификатор пользователя будет передаваться как основной параметр, остальные как свойства. Получить их можно следующим образом: .. code-block:: java public void onMessage(Message message) { //Получение идентификатора пользователя/должности/подразделения (В зависимости от события на которое подписаны) String userID = ((TextMessage) message).getText(); //Получаем идентификатор формы String formUUID = message.getStringProperty("formUUID"); } .. toctree:: :maxdepth: 2 :numbered: integration/events .. toctree:: :maxdepth: 1 :numbered: integration/client_events Блокирующий процесс ------------------- Блокирующий процесс предназначен для того, чтобы предоставить возможность в маршрут активации/изменения/удаления реестра вставить асинхронный вызов внешнего модуля. Основное отличие блокирующего процесса от событий реестра заключается в том, что: * при использовании блокирующего процесса маршрут реестра дожидается ответа о результате выполнения операции внешним модулем * блокирующий процесс может завершиться положительно или отрицательно, что повлияет на дальнейшую работу маршрута (Если блокирующий процесс завершится отрицательно — процесс остановится, если положительно — то продолжит работу дальше) Модуль, реализующий блокирующий процесс, должен представлять собой отдельное приложение, задеплоенное на jboss в соответствии с правилами, описанными в разделе `Как задеплоить интеграционное приложение`_. Запускается код модуля блокирующего процесса через очередь. При старте этапа маршрута, содержащего блокирующий процесс, в очередь добавляется сообщение, которое должен обработать модуль. Конфигурация блокирующего процесса ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Для того, чтобы добавить блокирующий процесс, необходимо выполнить следующие действия: 1. Добавить процесс с в маршрут реестра в конфигураторе: .. figure:: _static/img/integration/blocking-add.png :scale: 68% Название процесса должно начинаться с ``event.blocking.`` и далее строка, характеризующая суть блокирующего процесса. 2. Создать очередь JMS для блокирующего процесса. Для этого необходимо в конфигурационный файл (в стандартной установке это ``/opt/synergy/jboss/standalone/configuration/standalone-onesynergy.xml``) в секцию ```` добавить: .. code-block:: xml true 3. Связать очередь и процесс через конфигурационный файл ``{$jboss.home}/standalone/configuration/arta/api-observation-configuration.xml``, добавив в него следующее: .. code-block:: xml java:jboss/queues/Integration/ExampleQueue event.blocking.example Обратите внимание, что название блокирующего процесса, указанное в маршруте в конфигураторе должно быть равно значению тега в конфигурационном файле ``api-observation-configuration.xml`` (в данном примере: ``event.blocking.example``) и название очереди должно совпадать со значением тега ``queue`` конфигурационного файла ``api-observation-configuration.xml`` (в данном примере: ``java:jboss/queues/Integration/ExampleQueue``) Сообщение, передаваемое в очередь, является экземпляром ``TextMessage``. Содержимым сообщения является объект JSON с полями: 1. dataUUID — идентификатор данных по форме записи реестра 2. executionID — идентификатор блокирующего процесса 3. documentID — идентификатор документа реестра После того, как модуль обратится к внешней системе и выполнит необходимые действия, он должен вызвать метод API Synergy для того, чтобы возвратить результат выполнения процесса и продолжить работу маршрута. Для того, чтобы это сделать, необходимо вызвать метод API ``rest/api/processes/signal``. .. note:: Сигнал блокирующему процессу для его разблокировки/блокировки нужно отправлять после того, как этот процесс был запущен, то есть после того как транзакция с запуском процесса была завершена. Для этого, перед отправкой сигнала, проверяйте на наличие такого процесса в БД. В противном случае, блокирующий процесс может завершиться в транзакции, но в маршруте нет. В примере кода ниже разблокировка маршрута осуществляется в методе ``onMessage``. Если время выполнения действия значительно или зависит от внешних факторов (например, доступность интегрируемой системы, или необходимость ввода пользователем данных в интегрируемой системе), то разблокировка маршрута может произойти позже, в любой другой момент времени из другого метода, а сам метод onMessage должен завершиться без ошибок, «запомнив» переданные параметры. .. code-block:: java package kz.arta.synergy.samples.processes.blocking; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; /** *

<Пример блокирующего процесса

*/ @MessageDriven(name = "ExampleQueue", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"), @ActivationConfigProperty(propertyName = "destination", propertyValue = "java:jboss/queues/Integration/ExampleQueue"), @ActivationConfigProperty(propertyName = "reconnectAttempts", propertyValue = "32"), @ActivationConfigProperty(propertyName = "reconnectInterval", propertyValue = "4000"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class BlockingQueueListener implements MessageListener { public void onMessage(Message message) { String dataUUID = null; String executionID = null; String documentID = null; if (!(message instanceof TextMessage)){ return; } try { JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createJsonParser(((TextMessage) message).getText()); JsonToken token = null; while ((token = parser.nextToken()) != null) { if (token == JsonToken.FIELD_NAME) { String fieldName = parser.getText(); parser.nextToken(); String value = parser.getText(); if (fieldName.equals("dataUUID")){ dataUUID = value; } else if (fieldName.equals("executionID")){ executionID = value; } else if (fieldName.equals("documentID")){ documentID = value; } } } //Выполнение каких-либо действий …....... //Разблокировка маршрута String address = "http://127.0.0.1:8080/Synergy"; String login = "1"; String password = "1"; String signal = "got_agree"; boolean isSuccess = false; try { URL url = new URL(address + "/rest/api/processes/signal?signal=" + signal + "&executionID=" + executionID + "¶m1=resolution&value1=signal_is_" + signal); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Accept", "application/json; charset=utf-8"); String encoded = Base64.encode((login + ":" + password).getBytes()); conn.setRequestProperty("Authorization", "Basic " + encoded); String output; StringBuffer result = new StringBuffer(); BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); while ((output = br.readLine()) != null) { result.append(output); } conn.disconnect(); JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createJsonParser(result.toString()); JsonToken token = null; while ((token = parser.nextToken()) != null) { if (token == JsonToken.FIELD_NAME) { String fieldName = parser.getText(); token = parser.nextToken(); if (fieldName.equals("errorCode") && parser.getText().equals("0")){ isSuccess = true; } } } } catch (Exception exc){ logger.error(exc.getMessage(), exc); } } catch (Exception exc){ logger.error(exc.getMessage(), exc); } } } Дополнительный обработчик для стандартного процесса --------------------------------------------------- Цель данного вида интеграции — дать возможность повлиять на запуск стандартного процесса и, при необходимости, прервать его. Стандартная функциональность платформы ARTA Synergy дает возможность запретить отправку документов на согласование, утверждение, если количество уровней оргструктуры между отправителем и получателем превышает некоторое настроенное значение. Но в некоторых компаниях существуют более сложные правила, ограничивающие возможность отправки документов/работ. В этих случаях необходима разработка данного обработчика. Обработчик может быть применён к процессам: * «работа» (`assignment-single`) * «согласование» (`agreement-single`) * «утверждение» (`approval-single`) * «ознакомление» (`acquaintance-single`) * «отправка документа» (`send-document`) * «общий процесс при запуске по формам» (`common-process-by-form`) * «отправка документа по форме» (`send-document-by-form`) Обработчик представляет собой Java-класс, реализующий интерфейс ``kz.arta.synergy.integration.api.bp.StartHandlerIF`` Данный интерфейс находится в библиотеке ``integration-api.jar``, которую можно найти в установленном экземпляре ARTA Synergy в директории ``/opt/synergy/jboss/standalone/deployments/Synergy.ear/lib``. Интерфейс содержит два метода: * ``makeDecision()`` — проверяет возможно ли выполнение процесса * ``getResolution()`` — возвращает текст, который должен быть записан в ход исполнения Более подробную информацию о полях методов можно посмотреть в javadoc к этим методам, которые доступны в ``integration-api.jar`` (библиотека содержит и скомпилированные классы, и исходный код). Установка обработчика для процесса осуществляется с помощью конфигурационного файла ``${jboss.server.config.dir}/arta/process-handlers-configuration.xml``, имеющего следующий формат: .. code-block:: xml assignment-single kz.arta.synergy.ext.blocking.SendControlHandler agreement-single kz.arta.synergy.ext.blocking.SendControlHandler approval-single kz.arta.synergy.ext.blocking.SendControlHandler acquaintance-single kz.arta.synergy.ext.blocking.SendControlHandler send-document kz.arta.synergy.ext.blocking.SendControlHandler Обработчики выполняются последовательно до тех пор, пока метод ``makeDecision()`` одного из них не вернет ``false``, после этого процесс прерывается. Библиотеку, содержащую обработчик необходимо скопировать в папку ``/opt/synergy/jboss/standalone/deployments/Synergy.ear/lib``. После копирования библиотеки обработчика и изменения файла ``process-handlers-configuration.xml`` необходимо перезапустить JBoss. .. attention:: Процесс ``common-process-by-form`` запускает процессы ``agreement-single``, ``approval-single``, ``acquaintance-single``, ``assignment-single`` (подпроцессы). Поэтому, если обработчик будет запрещать выполнение подпроцесса и при этом разрешать выполнение процесса ``common-process-by-form``, то подпроцессы все равно будут прерваны. Аналогично, если выполнение ``common-process-by-form`` разрешено, а выполнение подпроцесса запрещено, подпроцессы будут прерваны. Пример использования ~~~~~~~~~~~~~~~~~~~~ С использованием этого способа интеграции был реализован внешний модуль, ограничивающий перепоручение и отправку каких-либо работ на согласование пользователям определенных групп. Для установки внешнего модуля из репозитория необходимо установить пакет ``arta-synergy-ext-sendcontrol``. Далее на остановленном JBoss в конфигурационном файле ``${jboss.server.config.dir}/arta/process-handlers-configuration.xml`` необходимо прописать следующие обработчики процесса: .. code-block:: xml assignment-single kz.arta.synergy.ext.blocking.SendControlHandler agreement-single kz.arta.synergy.ext.blocking.SendControlHandler Установка групп (каким группам пользователей Synergy) разрешать либо блокировать процессы осуществляется с помощью конфигурационного файла ``${jboss.server.config.dir}/arta/ext/send-control.xml``. Пример настройки: .. code-block:: xml 35 111 Способы авторизации в ARTA Synergy ---------------------------------- REST API ARTA Synergy доступно только авторизованным пользователям. Тип авторизации — ``BASIC HTTP``. Методы API выполняются от имени того пользователя, который авторизован. Имеются следующие типы авторизации: Авторизация по логину и паролю ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Авторизация пользователя по его логину и паролю приемлема в тех случаях, когда приложение может знать текущий логин и пароль пользователя, например: * Приложение предоставляет альтернативный интерфейс к некоторым модулям Synergy (мобильное приложение, десктопный клиент для хранилища) * Приложение представляет собой `server-side` утилиту для синхронизации, для которого создан выделенный пользователь, и его логин и пароль хранятся в конфигурационном файле на сервере. Для реализации данного типа авторизации надо передать в запросе заголовок ``Authorization`` со значением: ``"Basic " + Base64("login" + ":" + "password")`` Например: +--------------------+--------------------------------------+ | Логин | `Administrator` | +--------------------+--------------------------------------+ | Пароль | `123456` | +--------------------+--------------------------------------+ | Значение заголовка | `Basic QWRtaW5pc3RyYXRvcjoxMjM0NTY=` | +--------------------+--------------------------------------+ .. code-block:: :emphasize-lines: 3 POST /Synergy/rest/api/report/do?reportID=daa64ab2-1a79-4ea2-9c24-372e35d9da3e&fileName=report.pdf HTTP/1.1 Host: demo.arta.kz Authorization: Basic QWRtaW5pc3RyYXRvcjoxMjM0NTY= Cache-Control: no-cache Content-Type: multipart/form-data Пример кода на JAVA: .. code-block:: java :emphasize-lines: 5 String login = "Administrator"; String password = "123456"; HttpResponse response = Unirest.get("http://demo.arta.kz/Synergy/rest/api/admin/db/current_version") .header("authorization", Base64.getEncoder().encodeToString((login + ":" + password).getBytes(‌"UTF‌​-8"​))) .asString(); Пример кода на JavaScript (jQuery): .. code-block:: js :emphasize-lines: 10 var login = "Administrator"; var password = "123456"; var settings = { "async": true, "crossDomain": true, "url": "http://demo.arta.kz/Synergy/rest/api/admin/db/current_version", "method": "GET", "headers": { "authorization": ("Basic " + btoa(login + ":" + password)) } } $.ajax(settings).done(function (response) { console.log(response); }); Пример кода на PHP: .. code-block:: php :emphasize-lines: 11 setUrl('http://demo.arta.kz/Synergy/rest/api/admin/db/current_version'); $request->setMethod(HTTP_METH_GET); $request->setHeaders(array( 'authorization' => "Basic " . base64_encode("$login:$password") )); try { $response = $request->send(); echo $response->getBody(); } catch (HttpException $ex) { echo $ex; } Сессионная авторизация ~~~~~~~~~~~~~~~~~~~~~~ Сессионная авторизации используется для встроенных WEB-модулей. При cессионной авторизации также используется тип — ``BASIC HTTP``, но в качестве логина пользователя необходимо использовать значение ``$session`` и в качестве пароля — полученное значение ``sso_hash``. Таким образом заголовок ``Authorization`` должен иметь значение: ``"Basic " + Base64("$session" + ":" + "sso_hash")`` Например: +-----------------------+--------------------------------------------------------+ | Значение ``sso_hash`` | ``D3RONfC52dtJO5XgDyn5qUMv`` | +-----------------------+--------------------------------------------------------+ | Значение заголовка | ``Basic JHNlc3Npb246RDNST05mQzUyZHRKTzVYZ0R5bjVxVU12`` | +-----------------------+--------------------------------------------------------+ Получить значение ``sso_hash`` авторизованного пользователя можно следующими способами: #. В случае если приложение представляет собой `Внешний WEB-модуль`_, получить значение ``sso_hash`` можно из строки запроса. Пример кода на JavaScript (jQuery): .. code-block:: js :emphasize-lines: 13 function getURLParameter(name) { return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)') .exec(location.search) || [null, ''])[1] .replace(/\+/g, '%20')) || null; } var settings = { "async": true, "crossDomain": true, "url": "http://demo.arta.kz/Synergy/rest/api/admin/db/current_version", "method": "GET", "headers": { "authorization": ("Basic " + btoa("$session" + ":" + getURLParameter('sso_hash'))) } } $.ajax(settings).done(function (response) { console.log(response); }); #. С помощью переменной окружения ``$CURRENT_USER`` основного WEB-приложения Synergy, которая представляет собой JSON-объект следующего вида: .. code-block:: json { "id": "Идентификатор текущего пользователя", "sso_hash": "hash-сумма для идентификации пользователя", "surname": "Фамилия текущего пользователя", "name": "Имя текущего пользователя", "patronymic": "Отчество текущего пользователя" } Пример кода на JavaScript (jQuery): .. code-block:: js :emphasize-lines: 7 var settings = { "async": true, "crossDomain": true, "url": "http://demo.arta.kz/Synergy/rest/api/admin/db/current_version", "method": "GET", "headers": { "authorization": ("Basic " + btoa("$session" + ":" + $CURRENT_USER.sso_hash)) } } $.ajax(settings).done(function (response) { console.log(response); }); .. note:: Данный способ можно использовать только если код исполняется в основном приложении Synergy. Например, приложение представляет собой :ref:`extcmp-label` . .. _key_auth: Авторизация по ключам ~~~~~~~~~~~~~~~~~~~~~ Модуль, который хочет авторизоваться от имени какого-либо пользователя таким способом, должен сгенерировать для него ключевую пару, обеспечив сохранность закрытого ключа. Затем модуль сохраняет получивший открытый ключ для пользователя в Synergy, используя следующий вызов API: ``rest/api/person/generate_auth_key`` Этот вызов назначает ключ тому пользователю, от имени которого выполняется. Параметр ``user_token_expire_interval`` регулирует интервал устаревания ключей авторизации. Пример настройки интервала: .. code-block:: sql insert into options (id, value) values ('user_token_expire_interval', '5256000'); -- 10 лет .. note:: Интервал устаревания ключа указывается в минутах. Значение по умолчанию ``0``, то есть если ранее для данного пользователя был сгенерирован другой ключ, то предыдущий автоматически становится недействительным. Создать ключ можно только для существующего WEB-модуля, так как для этого требуется идентификатор приложения. .. tip:: Если у вас нет необходимости разрабатывать WEB модуль, но есть необходимость в использовании авторизации по ключам, можно добавить внешний модуль и отключить его использование в административном приложении SynergyAdmin для всех элементов оргструктуры. Использование этого ключа для авторизации аналогично использованию сессионного ключа. Тип авторизации ``Basic HTTP``, в качестве логина пользователя надо использовать строку ``$key``, в качестве пароля — полученный с помощью API ключ. Таким образом заголовок ``Authorization`` должен иметь значение: ``"Basic " + Base64("$key" + ":" + "значение_ключа")`` Например: +---------------------+------------------------------------------------------------------------------------------------------------------------+ | Значение ключа | ``MS03Y2Q0ZGU3YS0zYjRkLTQ2NjgtYWIyOC0zZDI1YzgxZGNmOGZfMjAxMy0xMC0zMSAxNzo0Mg==`` | +---------------------+------------------------------------------------------------------------------------------------------------------------+ | Значение заголовка | ``Basic JGtleTpNUzAzWTJRMFpHVTNZUzB6WWpSa0xUUTJOamd0WVdJeU9DMHpaREkxWXpneFpHTm1PR1pmTWpBeE15MHhNQzB6TVNBeE56bzBNZz09`` | +---------------------+------------------------------------------------------------------------------------------------------------------------+ Внешний WEB-модуль ------------------ Web-приложение внешнего модуля открывается в ``iframe`` в окне основного приложения. При этом рабочая область внешнего модуля занимает всю область страницы, кроме панели меню и панели задач: .. figure:: _static/img/integration/web-module.png :scale: 50% Внешний WEB-модуль Для добавления нового модуля нужно перейти в :menuselection:`Конфигуратор --> Настройки системы --> Управление модулями --> Внешние модули` и нажать на кнопку "Добавить". .. figure:: _static/img/integration/web-modules.png Внешние модули В открывшемся окне нужно заполнить следующие поля: * **«Название»** - название модуля в соответствующем интерфейсе. * **«Код»** - поле должно содержать уникальное значение. * **«Адрес приложения»** - поле для ввода URL. * **«Описание модуля»** - поле для описания данного модуля. * **«Иконка»** - задает иконку модуля в пользовательской подсистеме (по умолчанию внешний модуль имеет стандартную иконку). Для того, чтобы изменить стандартную иконку, нужно кликнуть по кнопке «Выберите файл» и в диалоге выбора файла указать файл формата PNG, размер которого не превышает 28х26. .. figure:: _static/img/integration/web-module-add.png Добавление нового внешнего модуля .. hint:: Добавить внешний web-модуль можно с помощью SQL-запроса в БД ``synergy.outer_modules``, вставив запись со следующими полями: * ``id`` — идентификатор модуля, должен совпадать с идентификатором вашего проекта в репозитории проектов * ``nameru``, ``namekz``, ``nameen`` — название модуля на русском, казахском и английском языках соответственно * ``url`` — адрес приложения * ``description`` — описание модуля * ``active`` — активен ли модуль, 1/0. Для реализации механизма :abbr:`SSO (Single Sign-On)` приложений, ARTA Synergy при загрузке внешнего web-модуля будет в строку URL добавлять три параметра: #. ``locale`` — локаль авторизованного пользователя #. ``sso_hash`` — hash-сумма для идентификации пользователя. #. ``host`` — адрес, с которого загружено приложение Synergy Например, если URL приложения ``http://host:port/plans_module``, то при обращении к модулю будет вызываться ``http://host:port/plans_module?locale=locale_value&sso_hash=sso_hash_value`` Интегрированный модуль должен будет будет получить из URL параметр ``sso_hash`` и запросить по REST API у ARTA Synergy информацию об авторизованном пользователе (идентификатор, имя). Если метод REST API возвращает информацию о пользователе, это подтверждает, что данный пользователь действительно авторизован с данного хоста, в данном браузере. Далее строка ``sso_hash`` может быть использована для `Сессионная авторизация`_ и вызова REST API Arta Synergy. В ARTA Synergy реализована возможность обращения к ее модулям по относительной ссылке. Такая же возможность существует для внешних web-модулей. Переход по ссылке вида: ``#submodule=outer&outerModuleID='код_модуля'&прочие_параметры_по_желанию_модуля`` активирует в Synergy заданный модуль и передаст ему заданные в url-e параметры (параметры ``locale``, ``sso_hash``, ``host`` также будут переданы, несмотря на то, что они отсутствуют в ссылке). Часто возникает необходимость в этой ссылке передать ссылку на текущий документ. Для этого можно добавить в ссылку параметр, значение которого будет равно ``${docID}`` — эта строка в web-интерфейсе проигрывателя форм Synergy будет заменена на идентификатор данного документа. Внешний проигрыватель форм -------------------------- В бизнес-приложениях на базе Synergy может возникнуть необходимость работы из внешних систем с формами Synergy. В этом случае можно использовать внешний проигрыватель форм. Проигрыватель форм - это инструмент, который даёт возможность работать с формами, созданными и используемыми в Synergy, а также выполняет скрипты. При использовании во внешней системе проигрыватель позволяет: * отображать и редактировать формы Synergy; * настраивать произвольный вид формы и ее компонентов, создавать новые компоненты; * автоматически заполнять поля формы данными из внешней системы; * обеспечивать обратную связь от проигрывателя к серверу, используя механизм событий; * обрабатывать наступившие события. .. note:: Проигрыватель форм запускается на стороне клиента, поэтому все события и скрипты срабатывают только при открытом проигрывателе. Подключение проигрывателя форм ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #. Для подключения проигрывателя на страницу необходимо добавить код в раздел ``head``: .. code-block:: xml и вставить элемент для размещения проигрывателя в тело страницы: .. code-block:: xml
#. Код скрипта, который использует проигрыватель, должен содержать ссылку на Synergy: .. code-block:: javascript AS.OPTIONS.coreUrl = "http://127.0.0.1:8080/Synergy/"; //ссылка на экземпляр Synergy Создание объекта проигрывателя выглядит следующим образом: .. code-block:: javascript 'use strict'; AS.OPTIONS.locale = "ru"; AS.OPTIONS.coreUrl = "http://127.0.0.1:8080/Synergy/"; var portal = { player : null, /** * очистить текущий проигрыватель форм */ clearPlayer : function() { if(portal.player) { portal.player.destroy(); } }, /** * добавить новый проигрыватель форм */ createPlayer : function(formCode){ portal.clearPlayer(); portal.player = AS.FORMS.createPlayer(); portal.player.showFormByCode(formCode); portal.player.view.appendTo($('#form_player_div')); } }; $(document).ready(function(){ AS.OPTIONS.login = "login"; AS.OPTIONS.password = "password"; portal.createPlayer("formCode"); }); См. также документацию по :ref:`form_scripting-label`. .. _extfp-usecases-label: Варианты использования внешнего проигрывателя форм ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ В данном разделе описываются основные примеры использования внешнего проигрывателя форм. Каждый пример отражает одно из базовых требований к внешнему проигрывателю и содержит: * описание примера; * реализованный пример внешнего проигрывателя форм, встроенного во внешний портал (в данном случае - в портал документации); * а также исходные коды JavaScript и CSS этих примеров. Примеры использования внешнего проигрывателя форм: .. toctree:: :maxdepth: 2 :numbered: integration/extfp-usecases/uc1 integration/extfp-usecases/uc2 integration/extfp-usecases/uc3 integration/extfp-usecases/uc4 integration/extfp-usecases/uc5 integration/extfp-usecases/uc6 integration/extfp-usecases/uc7 integration/extfp-usecases/uc8 Ссылки на модули системы и их внутренние элементы ------------------------------------------------- Ссылки на модули и различные объекты Synergy можно использовать как внутри основного web-приложения (в этом случае предпочтительно использовать относительные ссылки, чтобы не перезагружать страницу), так и во внешних системах. Общий вид ссылок: http[s]://**host***[:port]*/**Application**?*param1*=*value1*&*param2*=*value2*#*param3*=*value3*&*param4*=*value4* где * **host** - доменное имя или ip-адрес сервера Synergy * *port* - порт * **Application**: * `Synergy` - основное приложение * `Configurator` - Конфигуратор * `SynergyAdmin` - административное приложение * *param1*, *param2* - параметры абсолютной ссылки * *param3*, *param4* - параметры относительной ссылки Параметры абсолютной ссылки - это, как правило: * **locale** - локаль загружаемой системы * **nocache** - специальный параметр, предотвращающий случайное кэширование остальные параметры можно передавать как параметры относительной ссылки. Ниже для краткости будем приводить образец относительной ссылки Ссылка на модуль системы ~~~~~~~~~~~~~~~~~~~~~~~~ ``#submodule=module_id`` где ``module_id``: * **workflow** - Потоки работ * **calendar** - Ежедневник * **repository** - Хранилище * **plans** - Проекты * **pointers** - Цели и показатели * **employees** - Сотрудники При переходе по ссылке откроется указанный модуль. Ссылка на документ и файл в нём ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``#submodule=common&file_identifier=some_file_id&action=open_document&document_identifier=some_doc_id`` При переходе по такой ссылке откроется указанный документ с основным файлом, а если указан ``file_identifier`` - то откроется документ с этим файлом. Ссылка на проект и мероприятие в нем ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``#submodule=plans&action=open_action&action_identifier=some_action_id&project_identifier=some_project_id`` При переходе по такой ссылке откроется указанный проект, а если указан ``action_identifier`` - то в проекте будет выделено это мероприятие. Ссылка на профиль пользователя ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``#submodule=employees&innermodule=structure&action=open_user&user_identifier=some_user_id`` При переходе по такой ссылке будет открыт модуль «Сотрудники», а в нем - профиль указанного пользователя Отключение всего пользовательского клиентского скриптинга ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Если в абсолютной ссылке указать параметр ``noCustomScripting``, то все пользовательские ВМК, скрипты в формах и пользовательских компонентах будут отключены. Это можно использовать для отладки пользовательских компонентов, ВМК и скриптов на форме. Как задеплоить интеграционное приложение ---------------------------------------- ARTA Synergy работает на сервере приложений JBoss AS7. Интеграционное приложение может представлять собой *jar*-файл либо *war*-файл либо их комбинацию. Если приложение является одиночным файлом, его можно задеплоить, скопировав в директорию ``${jboss.home}/standalone/deployments``. Если приложение состоит из нескольких файлов, необходимо создать `*.ear` приложение. Если приложение имеет зависимости на внешние библиотеки и они находятся в модулях JBoss-а (``${jboss.home}/modules``), необходимо использовать их, прочие зависимости — помещать внутрь приложения. .. danger:: В целях безопасности работы приложения Synergy и сервера приложений категорически запрещается помещать артефакты интеграционного модуля в приложение ``Synergy.ear`` и изменять состав модулей (``${jboss.home}/modules``).