diff --git a/README.md b/README.md index ba61eba1..939966d1 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,49 @@ + # jsBeans - Client-server JavaScript Fullstack Web Framework - + ```jsBeans``` — изоморфный клиент-серверный фреймворк класса "full-stack" для создания комплексных программных решений с развитым веб-интерфейсом, объектной иерархией и клиент-серверным взаимодействием. - + Реализован на Java 1.8 с Mozilla Rhino в качестве серверного JavaScript движка, встроенным Web сервером на Eclipse Jetty и сервисной шиной на Akka. - -#### Ключевые особенности jsBeans: - -* Веб-интерфейс и бизнес логика приложений разрабатываются на атомарных объектно-ориентированных классах - бинах (```JavaScript Beans (JSB)``` по аналогии с ```JavaBeans```). -* Дескриптор бина (JSON с функциями) представляет логически законченный функциональный компонент и одновременно содержит как клиентский, так и серверный код. + +### Ключевые особенности jsBeans: + +* Веб-интерфейс и бизнес логика приложений разрабатываются на атомарных объектно-ориентированных JavaScript-объектах - бинах (```JavaScript Beans (JSB)``` по аналогии с ```JavaBeans```). +* Бины - логически законченные функциональные компоненты, которые одновременно содержат как клиентский, так и серверный код. * Прозрачное взаимодействие клиентской и серверной частей бина и автоматическая синхронизация данных на единой RPC шине. * Динамическое разрешение зависимостей бинов. * Обмен сообщениями между бинами в едином клиент-серверном пространстве (Actors). * Встроенная библиотека клиент-серверных веб-компонентов (JSB.Widgets) и возможность подключения компонентов из репозитория. * Возможность использования на серверной стороне любых сторонних Java библиотек. - -#### А также -* Шаблонизатор ``` `#dot ...` ``` (сейчас ```#dot{{...}}```) + +### А также +* Шаблонизатор ``` `#dot ...` ``` * Аннотирование полей и методов ```/** @annotation {...} */``` (не реализовано) -* Публикация методов бина в HTTP API +* Вызов методов бина через HTTP (http://my.server.com/index.jsb) * Расширения бинов (traits), позволяющие навесить на бины дополнительный функционал. * Минификатор и упаковщик с управлением зависимостями * TODO -#### Использование - +### Использование + 1. В виде самостоятельного сервера приложений с развертыванием прикладных приложений "из папки". 2. В виде подключаемой Java библиотеки. Прикладные модули, как правило, также подключаются в общий classpath основного приложения. -## Что такое бины? -В соответствии с концепцией jsBeans вся логика приложений (как серверная, так и клиентская) строится в виде иерархий объектов на языке JavaScript, напоминающих EJB-компоненты в Java EE. Они изоморфны, соответствуют основным принципам ООП, могут порождаться и удаляться, могут вызываться удаленно и мигрировать с одного сервера на другой или в браузер. Такие объекты мы называем - **бинами**. -#### Простейший бин -Бины описываются в виде JSON объектов. Они содержат системные поля, отражающие специфику функционирования бина, а также ряд пользовательских полей и методов для описания бизнес логики. -Все системные поля начинаются на $, например ```$name```, ```$parent```, ```$require``` и т.п. -Декларация бина осуществляется с помощью функции ```JSB(beanDeclarationJson);``` и выглядит следующим образом: + + +## Основные принципы + +### Что такое бины? +В соответствии с концепцией jsBeans вся логика приложений (как серверная, так и клиентская) строится в виде иерархий объектов на языке JavaScript, напоминающих EJB-компоненты в Java EE. Они изоморфны, соответствуют основным принципам ООП, могут порождаться и удаляться, могут вызываться удаленно и мигрировать с одного сервера на другой или в браузер. Такие объекты мы называем - **бинами**. + +Бины описываются в виде JS объектов. Они содержат системные поля, отражающие специфику функционирования бина, а также ряд пользовательских полей и методов для описания бизнес логики. +Все системные поля начинаются на ```$```, например: +```$name``` , ```$parent``` , ```$require``` и т.п. + +Декларация бина осуществляется с помощью функции ```JSB(beanDescriptor);``` и выглядит следующим образом: ```javascript JSB({ $name: 'MyBean', @@ -49,9 +56,9 @@ JSB({ }); ``` -Функция ```JSB(beanDeclarationJson)``` непосредственно формирует сам бин по описанию в ```beanDeclarationJson``` и помещает его в специальный контейнер бинов (JSB-контейнер) с целью дальнейшего управления его жизненным циклом. JSB-контейнер изоморфен и присутствует как на стороне сервера так и на стороне клиента. +Функция ```JSB(beanDescriptor)``` непосредственно формирует сам бин по описанию в ```beanDescriptor``` и помещает его в специальный контейнер бинов (JSB-контейнер) с целью дальнейшего управления его жизненным циклом. JSB-контейнер изоморфен и присутствует как на стороне сервера так и на стороне клиента. -Таким образом вышеприведенный бин может быть одинаково использован как стороне сервера, так и на стороне клиента(ов). +Таким образом вышеприведенный бин может быть одинаково использован как стороне сервера, так и в браузере. ```javascript JSB.lookup('MyBean', function(MyBeanClass){ @@ -59,16 +66,32 @@ JSB.lookup('MyBean', function(MyBeanClass){ myBeanInst.myMethod(); }); ``` +Все бины размещаются в файлах ```*.jsb``` в файловой системе сервера. В момент инициализации сервер рекурсивно сканирует папку с бинами и загружает их в свой репозиторий. +Каждый файл ```*.jsb``` содержит только декларацию бина без функции ```JSB(...)```, например: +Файл ```test.jsb```: +```javascript +{ + $name: 'MyBean', + + myField: 123, + + myMethod: function(){ + return this.myField; + } +} +``` +### Контейнер бинов +Ключевую роль в jsBeans играет JSB-контейнер, который отвечает за жизненный цикл бинов, разрешение зависимостей между ними, обеспечение клиент-серверного взаимодействия и синхронизацию полей у экземпляров бинов на клиентской и серверной сторонах. -#### Клиент-серверный бин +### Клиент-серверное взаимодействие Клиент-серверные бины, как правило, содержат несколько секций (в частности – ```$server``` и ```$client```). В секции ```$client```, в основном, располагаются поля и методы для взаимодействия с DOM моделью браузера, а в секции ```$server``` – серверные поля и методы, отвечающие за бизнес логику, работу с СУБД, файловой системой и другими ресурсами операционной системы. В общем случае при создании экземпляра бина на стороне клиента создается соответствующий ему серверный экземпляр и между ними устанавливается взаимодействие, характер которого (один к одному / много к одному) задается разработчиком при декларации бина. Взаимодействие между кодом из разных секций осуществляется прозрачно для разработчика, путем вызова автоматически генерируемых асинхронных proxy методов. - +Файл ```mybean.jsb```: ```javascript -JSB({ +{ /** пакет и имя бина */ $name: 'my.examples.MyBean', @@ -97,14 +120,17 @@ JSB({ scheduleTimestampMessage: function(){ window.setInterval(function(){ /** вызов метода из "противоположной секции" осуществляется - асинхронно через адаптер, получаемый внутри методов $server() - и вне jsb.$server()*/ - $server().getTimestamp(function(result, error){ - /** в scope всех методов добавляется $this равный this - метода бина, чтобы перед вложенными функциями не декларировать ' - var self = this' */ + асинхронно через адаптер, получаемый путем вызова метода remote() + у бина. + */ + $this.remote().getTimestamp(function(result, error){ /** результат вызова удаленного метода будет возвращен в коллбэк */ + + /** в scope всех методов автоматически добавляется + локальная переменная $this равный this метода бина, + чтобы перед вложенными функциями не декларировать: + var self = this; */ if (!error) { - let data = {timestamp: 0 + result}; + var data = {timestamp: 0 + result}; alert($this.formatMessageText(data)); } }); @@ -114,31 +140,36 @@ JSB({ /** секция серверного кода (исполняется на сервере)*/ $server: { + /** при необходимости могут быть задействованы классы и методы из Java*/ + $require: {System:'java:java.lang.System'}, + /** серверный конструктор вызывается при порождении серверной части - экземпляра бина */ + экземпляра бина */ $constructor: function(){ /** создание экземпляра импортированного бина */ this.myWorld = new MyWorld(); }, /** методы, объявленные в серверной секции могут вызываться с клиента - и наоборот */ + и наоборот */ getTimestamp: function (){ return 0 + this.getSystemTimestamp(); }, - /** В серверной секции так же можно использовать java классы и объекты, - добавив префикс 'Packages.' */ getSystemTimestamp: function() { - return Packages.java.lang.System.currentTimeMillis(); + /** Вызываем метод класса Java из пакета java.lang.System для получения + текущего времени */ + return System.currentTimeMillis(); } } -}); +} ``` -#### Web компонент +## Создание web компонентов +### Web компонент +Файл ```myWebControl.jsb```: ```javascript -JSB({ +{ $name: 'my.examples.MyWebControl', /** Унаследуем наш компонент от бина Control из библиотеки JSB.Widgets */ @@ -149,12 +180,12 @@ JSB({ /** Клиентская секция (код будет выполняться в браузере) */ $client: { - #constructor: function(opts){ + $constructor: function(opts){ $base(opts); // Вызываем родительский конструктор /** Загружаем стили (путь задается относительно места расположения файла с текущим бином) */ - this.loadCss('myWebControl.css'); + $jsb.loadCss('myWebControl.css'); /** Создадим экземпляр бина ComboBox из библиотеки JSB.Widgets */ var cb = new ComboBox({ @@ -198,9 +229,17 @@ JSB({ Первым аргументом передаем значение из комбо, а вторым - колбэк функцию, которая будет вызвана сразу как только серверный метод вернет данные */ - $server().loadMyData(cbVal, function(res){ + this.server().loadMyData(cbVal, function(res){ $this.drawData(res); // отрисуем данные }); + /** Для удаленного вызова серверного кода можно также использовать + функцию remote(), которая осуществляет удаленный вызов на + противоположной стороне. Но если мы знаем, что вызывающий метод + находится на стороне клиента и удаленно вызывает серверную + функцию, то можно явно сразу использовать метод server(). + Аналогична и обратная ситуация - находясь в теле серверного метода + можно удаленно вызвать клиентский метод, путем использования + функции client()*/ }, drawData: function(data){ @@ -231,14 +270,14 @@ JSB({ return this.myDictionary[key]; } } -}); +} ``` -#### Встраивание компонента в HTML при помощи JavaScript +### Встраивание компонента в HTML при помощи JavaScript ```html - +
@@ -256,11 +295,11 @@ JSB({ ``` -#### Автоматическое встраивание компонента в HTML +### Автоматическое встраивание компонента в HTML ```html - +