BeanExplorer5 API — различия между версиями

Материал из DevelopmenOnTheEdge
Перейти к: навигация, поиск
(Новая страница: «== Backend == <big>BeanExplorer5 проект - это OSGi бандл, поддерживающий расширения через <code>plugin.xml</code>.</big…»)
 
(Основные интерфейсы и классы API)
 
(не показано 9 промежуточных версии этого же участника)
Строка 22: Строка 22:
 
  }
 
  }
  
<code>com.beanexplorer.be5.component</code> - это единственная точка расширения BeanExplorer5, она позволяет регистрировать свои backend компоненты, которые будут доступны следующим URL:
+
<code>com.beanexplorer.be5.component</code> - это единственная точка расширения BeanExplorer5, она позволяет регистрировать свои backend компоненты, которые будут доступны по следующим URL:
  
 
  //domain/app/main/:componentId
 
  //domain/app/main/:componentId
Строка 39: Строка 39:
 
** <code>JsonComponent</code> - при наследовании этого класса необходимо только реализовать один метод, возвращающий строку, представляющую собой JSON.
 
** <code>JsonComponent</code> - при наследовании этого класса необходимо только реализовать один метод, возвращающий строку, представляющую собой JSON.
 
** <code>NetSfJsonComponent</code> - при наследовании этого класса необходимо только реализовать один метод, возвращающий <code>net.sf.json.JSONObject</code>.
 
** <code>NetSfJsonComponent</code> - при наследовании этого класса необходимо только реализовать один метод, возвращающий <code>net.sf.json.JSONObject</code>.
* <code>ComponentParameters</code> - всё, что необходимо компоненту. Если необходимо что-то ещё, то либо мы что-то забыли или не предусмотрели, либо вы неправильно используете API BeanExplorer5. К чему возможно доступиться из этого компонента:
+
* <code>ComponentParameters</code> - всё, что необходимо компоненту. Если необходимо что-то ещё, то либо мы что-то забыли или не предусмотрели (и об этом непременно стоит сообщить нам), либо вы неправильно используете API BeanExplorer5. К чему возможно доступиться из этого компонента:
 
** <code>Project</code> - BE4 проект.
 
** <code>Project</code> - BE4 проект.
 
** <code>Meta</code> - полезные методы для работы с BE4 проектом.
 
** <code>Meta</code> - полезные методы для работы с BE4 проектом.
Строка 47: Строка 47:
  
 
<big>Обратите внимание на то, что другие классы не являются частью API, в т.ч. класс Be5 и классы, связанные с реализацией конкретных компонентов.</big>
 
<big>Обратите внимание на то, что другие классы не являются частью API, в т.ч. класс Be5 и классы, связанные с реализацией конкретных компонентов.</big>
 +
 +
Частью API также '''не''' являются соглашения о том, какие данные возвращают компоненты, поскольку эти соглашения используются обмена сообщениями между frontend и backend частями компонентов. Исключением являются соглашения о том, какие данные возвращают компоненты, описанные в разделе [[#REST API|REST API]].
 +
 +
== Frontend ==
 +
<big>Компоненты BE5 на frontend - это React.js компоненты.</big>
 +
 +
Компоненты подключаются через SystemJS, при этом используется синтаксис ES2015 или метод <code>define</code>.
 +
 +
import Component from 'components/component';
 +
 +
define([ 'components/component' ], function(Component) {
 +
  // use(Component)
 +
  // ...
 +
  return {};
 +
});
 +
 +
Кнопки и ссылки на компоненты (в частности запросы и формы) в BE5 не должны писаться вручную.
 +
 +
Не всё, что находится в проекте be5-frontend, является частью API.
 +
 +
=== Основные части API ===
 +
 +
* <code>be5</code> - ядро frontend. Функции, являющиеся частью API:
 +
** <code>be5.net.request: function(path, params, success, failure)</code> - делает асинхронный POST запрос к ''вашему'' backend компоненту (<code>path</code> - <code>componentId/any/path</code>).
 +
** <code>be5.registerAction: function(actionName, fn)</code> - регистрирует действие, которое будет вызвано при клике по кнопке или ссылке. Вызов действия является следствием смены hash url, при этом адрес разбирается на позиционные и именованные параметры. В зарегистрированную функцию передаются все позиционные параметры, за которыми идёт объект с именованными параметрами. Именованными параметрами считаются части URL, которые содержат символ '=', а позиционными считаются все остальные.
 +
** <code>be5.ui.registerDocumentType: function(type, creator)</code> - регистрирует новый вид документа. Функция, переданная вторым параметром в <code>registerDocumentType</code> обычно вызывает <code>React.createElement</code> и возвращает результат вызова. Результат будет помещён в стандартное для проекта место отображения документа. На данный момент на backend невозможно добавлять свои виды документов, но документ возможно создать посредством вызова <code>be5.ui.recreateDocument</code>.
 +
** <code>be5.ui.recreateDocument</code> - пересоздаёт документ. В качестве аргумента передаётся объект с двумя полями: <code>type</code> и <code>value</code>. Первое указывает тип документа, второе - значение документа, которое интерпретируется обработчиком документа, зарегистрированным посредством вызова <code>be5.ui.registerDocumentType</code>.
 +
** <code>be5.ui.createDocument</code> - похож на <code>be5.ui.recreateDocument</code>, однако позволяет встраивать документы в произвольное место страницы. Полезно, если тип документа заранее неизвестен.
 +
** <code>be5.load.css(path)</code> - подгружает CSS динамически, это необходимо во frontend компонентах, которым нужен CSS. <code>path</code> - путь к файлу CSS, например <code>css/menu.css</code>.
 +
** <code>be5.messages</code> - объект с локализованными сообщениями (русский и английский язык).
 +
 +
==== Другой способ определения действий ====
 +
Вы также можете определить действие неявным способом не вызывая <code>be5.registerAction</code>. Для этого создаётся файл с именем <code>/actions/yourAction.js</code>, который определяет AMD модуль посредством метода <code>define</code>. Объявдяемым элементом в этом модуле является функция, которая используется так же, как и функция, регистрируемая вызовом <code>be5.registerAction</code>, однако при этом подгрузка компонента произойдёт лениво - при первом его использовании.
 +
 +
=== Компоненты ===
 +
<big>API React компонентов описывается в соответствующих файлах в <code>propTypes</code> React компонентов.</big>
 +
 +
Компоненты, не указанные ниже, не являются частью API. По соглашениям именования мы сопоставляем имя компонента <code>ComponentName</code> SystemJS модулю <code>component/componentName</code>, который находится в файле <code>component/componentName.js</code> (или <code>component/componentName.jsx</code>, если для вашего проекта настроена компиляция JSX).
 +
 +
==== Be5Block ====
 +
Простая таблица внутри Bootstrap 4 Card.
 +
 +
==== Be5Form ====
 +
Простая форма внутри Bootstrap 4 Card.
 +
 +
==== Be5View ====
 +
Обобщённый компонент для таблиц, форм и статических страниц.
 +
 +
==== SimpleTable ====
 +
Простая таблица.
 +
 +
==== SimpleForm ====
 +
Простая форма.
 +
 +
==== Document ====
 +
Место для любого документа, в т.ч. формы или таблицы.
 +
 +
== REST API ==
 +
Запросы отсылаются с телом <code>application/x-www-form-urlencoded</code>.
 +
 +
=== document ===
 +
Пример запроса (здесь указано содержимое тела запроса - на самом деле оно выглядит несколько иначе, поскольку кодируется в <code>application/x-www-form-urlencoded</code>):
 +
 +
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 ===
 +
Запрос выглядит так же, как и у <code>document</code>.
 +
 +
Пример ответа:
 +
 +
{ "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"
 +
  }
 +
}
  
 
<code></code>
 
<code></code>
  
 
[[Category:BeanExplorer5]]
 
[[Category:BeanExplorer5]]

Текущая версия на 16:49, 25 ноября 2015

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"
  }
}