BeanExplorer5 API
Содержание
Backend
BeanExplorer5 проект - это OSGi бандл, поддерживающий расширения через plugin.xml.
При сборке BeanExplorer5 проекта он воспринимается как OSGi бандл, поэтому у него должен быть манифест META-INF/MANIFEST.MF. В этом манифесте указывается, от каких бандлов зависит данный бандл. Основные классы API находятся в бандле com.beanexplorer.be5, поэтому его необходимо указать в манифесте.
Помимо этого в структуру BeanExplorer5 проекта входит plugin.xml, в котором возможно объявлять свои компоненты, используя точку расширения com.beanexplorer.be5.component, которая объявлена в бандле com.beanexplorer.be5. Пример объявления компонента:
<extension point="com.beanexplorer.be5.component">
...
<component
class="com.beanexplorer.enterprise.components.Menu"
id="menu"
name="Menu">
</component>
Указанный класс должен реализовывать интерфейс Component:
package com.beanexplorer.enterprise.components;
public interface Component {
void generate(ComponentParameters parameters);
}
com.beanexplorer.be5.component - это единственная точка расширения BeanExplorer5, она позволяет регистрировать свои backend компоненты, которые будут доступны по следующим URL:
//domain/app/main/:componentId //domain/app/main/:componentId/:any/:path
Например:
http://localhost:8080/biostore_be5/main/menu http://localhost:8080/biostore_be5/main/menu/withIds
При запросе к веб-приложению по этим запросам будет создан новый экземпляр компонента и вызван его метод generate. Для того, чтобы узнать путь после имени компонента (:any/:path), нужно вызвать метод parameters.getRequestUri(). В случае пустого пути возвращается пустая строка. В случае наличия пути, он возвращается без начального слеша.
Основные интерфейсы и классы API
-
Component- главный интерфейс, который должны реализовывать BE5 компоненты. Поскольку проще всего общаться с frontend посредством пересылки JSON, существуют абстрактные классы, которые упрощают написание таких компонентов:-
JsonComponent- при наследовании этого класса необходимо только реализовать один метод, возвращающий строку, представляющую собой JSON. -
NetSfJsonComponent- при наследовании этого класса необходимо только реализовать один метод, возвращающийnet.sf.json.JSONObject.
-
-
ComponentParameters- всё, что необходимо компоненту. Если необходимо что-то ещё, то либо мы что-то забыли или не предусмотрели (и об этом непременно стоит сообщить нам), либо вы неправильно используете API BeanExplorer5. К чему возможно доступиться из этого компонента:-
Project- BE4 проект. -
Meta- полезные методы для работы с BE4 проектом. -
UserService- работа с сессиями, ролями, выбором языка. -
ResponseService- формирование текстового ответа. Необходимо только для абстрактных компонентов, обеспечивающих обмен текстовыми сообщениями в каком-нибудь формате (JSON, XML и т.п.). -
HttpServletRequestиHttpServletResponse- предполагается, что в обычной ситуации они не используются. Необходимы только для реализации абстрактных компонентов, обеспечивающих работу с каким-нибудь протоколом на низком уровне. Для обмена текстом достаточноResponseService.
-
Обратите внимание на то, что другие классы не являются частью API, в т.ч. класс Be5 и классы, связанные с реализацией конкретных компонентов.
Частью API также не являются соглашения о том, какие данные возвращают компоненты, поскольку эти соглашения используются обмена сообщениями между frontend и backend частями компонентов. Исключением являются соглашения о том, какие данные возвращают компоненты, описанные в разделе REST API.
Frontend
Компоненты BE5 на frontend - это React.js компоненты.
Компоненты подключаются через SystemJS, при этом используется синтаксис ES2015 или метод define.
import Component from 'components/component';
define([ 'components/component' ], function(Component) {
// use(Component)
// ...
return {};
});
Кнопки и ссылки на компоненты (в частности запросы и формы) в BE5 не должны писаться вручную.
Не всё, что находится в проекте be5-frontend, является частью API.
Основные части API
-
be5- ядро frontend. Функции, являющиеся частью API:-
be5.net.request: function(path, params, success, failure)- делает асинхронный POST запрос к вашему backend компоненту (path-componentId/any/path). -
be5.registerAction: function(actionName, fn)- регистрирует действие, которое будет вызвано при клике по кнопке или ссылке. Вызов действия является следствием смены hash url, при этом адрес разбирается на позиционные и именованные параметры. В зарегистрированную функцию передаются все позиционные параметры, за которыми идёт объект с именованными параметрами. Именованными параметрами считаются части URL, которые содержат символ '=', а позиционными считаются все остальные. -
be5.ui.registerDocumentType: function(type, creator)- регистрирует новый вид документа. Функция, переданная вторым параметром вregisterDocumentTypeобычно вызываетReact.createElementи возвращает результат вызова. Результат будет помещён в стандартное для проекта место отображения документа. На данный момент на backend невозможно добавлять свои виды документов, но документ возможно создать посредством вызоваbe5.ui.recreateDocument. -
be5.ui.recreateDocument- пересоздаёт документ. В качестве аргумента передаётся объект с двумя полями:typeиvalue. Первое указывает тип документа, второе - значение документа, которое интерпретируется обработчиком документа, зарегистрированным посредством вызоваbe5.ui.registerDocumentType. -
be5.ui.createDocument- похож наbe5.ui.recreateDocument, однако позволяет встраивать документы в произвольное место страницы. Полезно, если тип документа заранее неизвестен. -
be5.load.css(path)- подгружает CSS динамически, это необходимо во frontend компонентах, которым нужен CSS.path- путь к файлу CSS, напримерcss/menu.css. -
be5.messages- объект с локализованными сообщениями (русский и английский язык).
-
Другой способ определения действий
Вы также можете определить действие неявным способом не вызывая be5.registerAction. Для этого создаётся файл с именем /actions/yourAction.js, который определяет AMD модуль посредством метода define. Объявдяемым элементом в этом модуле является функция, которая используется так же, как и функция, регистрируемая вызовом be5.registerAction, однако при этом подгрузка компонента произойдёт лениво - при первом его использовании.
Компоненты
API React компонентов описывается в соответствующих файлах в propTypes React компонентов.
Компоненты, не указанные ниже, не являются частью API. По соглашениям именования мы сопоставляем имя компонента ComponentName SystemJS модулю component/componentName, который находится в файле component/componentName.js (или component/componentName.jsx, если для вашего проекта настроена компиляция JSX).
Be5Block
Простая таблица внутри Bootstrap 4 Card.
Be5Form
Простая форма внутри Bootstrap 4 Card.
Be5View
Обобщённый компонент для таблиц, форм и статических страниц.
SimpleTable
Простая таблица.
SimpleForm
Простая форма.
Document
Место для любого документа, в т.ч. формы или таблицы.
REST API
Запросы отсылаются с телом application/x-www-form-urlencoded.
document
Пример запроса (здесь указано содержимое тела запроса - на самом деле оно выглядит несколько иначе, поскольку кодируется в application/x-www-form-urlencoded):
category: servers page: All records values:
Пример таблицы:
{
"type": "table",
"value": {
"title": "Servers: All records",
"category": "servers",
"page": "All records",
"operations": [ {
"name": "Edit",
"title": "Edit",
"visibleWhen": "anySelected",
"requiresConfirmation": false,
"isClientSide": false
} ],
"selectable": true,
"columns": [ "Edit", "Provider", "Location", "Name", "Address", "Description", "Products", "Remote address" ],
"rows": [ {
"id": "1",
"cells": [ "html", "html", "html", "html", "", "html", "html", "html", "", "" ]
}, {
"id": "3",
"cells": [ "html", "html", "", "html", "html", "html", "", "", "", "" ]
} ],
"length": 20,
"parameters": {},
"totalNumberOfRows": 20
}
}
document/count
Запрос выглядит так же, как и у document.
Пример ответа:
{ "value": 3 }
form
Пример запроса:
category: groups page: All records action: Insert values: selectedRows: isViewParameters: false
Пример ответа:
{
"type": "form",
"value": {
"category": "groups",
"page": "All records",
"action": "Insert",
"title": "Insert",
"selectedRows": "",
"fields": [ {
"name": "name",
"title": "Name",
"isReadOnly": false,
"canBeNull": false,
"type": "textInput",
"value": ""
}, {
"name": "language",
"title": "Language",
"isReadOnly": false,
"canBeNull": false,
"type": "comboBox",
"options": [ {
"name": "Afar",
"value": "aa"
}, ..., {
"name": "Zulu",
"value": "zu"
} ],
"value": "en"
}, {
"name": "description",
"title": "Description",
"isReadOnly": false,
"canBeNull": false,
"type": "textArea",
"columns": 40,
"rows": 4,
"value": ""
}, {
"name": "maxUsers",
"title": "Max Users",
"isReadOnly": false,
"canBeNull": true,
"type": "textInput",
"value": ""
} ],
"parameters": {},
"isViewParameters": false
}
form/apply
Пример запроса:
category: groups
page: All records
action: Insert
selectedRows:
values: [{"name":"name","value":"a","required":true},{"name":"language","value":"en","required":true},{"name":"description","value":"a","required":true},{"name":"maxUsers","value":"5","required":false}]
isViewParameters: false
Пример ответа:
{
type: "formResult",
value: {
content: "",
redirect: "table/groups/All records"
}
}