Platypus.js

Client-Server JavaScript RAD platform.


Desktop and web apps

Module system

Role based security

Parallel JavaScript

Universal UI forms and widgets

Data is on your fingertips

Develop desktop and web apps using JS

Sometimes a browser is just not enough for your application as a client.
Maybe you do not need an application server at all.
In this case use the desktop Java SE client to run the same UI forms as a HTML5 browser.

Module system

Modules are Plain JavaScript Objects with some extra features:

  • AMD modules loader,
  • automatic dependencies resolving of global modules,
  • security system,
  • data model. It provides access to the data obtained from a data source (relational database, NoSQL database, etc).
Modules can run on a client as well as on a server.
The code snippet below shows a simple module example:

                            
/**
 *
 * @module Documents
 */
define(['logger', 'orm'], function(Logger, Orm, ModuleName){
    return function () {
        var model = Orm.loadModel(ModuleName);
        this.logDocuments = function(categoryId) {
            model.documents.params.catId = categoryId;
            model.requery(function(){
                model.documents.forEach(function(doc) {
                    Logger.info("Document name: " + doc.Name);
                });
            });
        };
    }
});
                            
                                

Security

Security support comes out-of-the-box in Platypus.js. Every resource like module or SQL query can be protected on the base of a currently logged-in user's roles. Platypus.js security subsystem is based on the Java EE security model and provides a very configurable mechanism for restricting access.
Various user information storages are supported. Use database user information storage or any external provider like Microsoft Active Directory or an OpenLDAP server.

Security annotations in JS modules

                                
    /**
     * In general, Platypus module starts with the JsDoc annotation
     * @author athorName
     * To allow usage from the client:
     * @public 
     * To set user roles allowed to use this module:
     * @rolesAllowed admin, user0
     * To assign a short name to this module:
     * @module MySuperModule
     */
    define(['security'], function(Security){
        return function () {
            var self = this;

            /**
             * You can define allowed roles for each function
             * @rolesAllowed admin
             */
            function isAdminGreat() {
                Logger.info('Is admin great?');
                Security.principal(function(aPrincipal){
                    if(aPrincipal.hasRole('developer'))){
                        Logger.info('Ah, you are God!');
                    }
                });
            }
        }
    });

                                    

Useful annotations in SQL queries

                                
    /**
     * @author authorName
     * @name myQuery
     * @public - to allow usage from the client side
     * @rolesAllowed user0, maintain, admin
     * @rolesAllowedRead guestUser
     * @rolesAllowedWrite ghostUser
     */
     Select * From someTable t1
     Where t1.someColumn = :myParam
                                
                                    

Parallel JavaScript and IO models

Platypus.js server JavaScript works in multi-threaded environment with a few threads (in general cores + 1 threads if async IO is used).
Platypus gives you a chance to choose the IO model for the specific situation and allowes to use both AsyncIO or Blocking IO models. providing performance that is good enough for the most types of applications (don't forget all UI logic runs on the client side).

Here is an example of parallel executed modules:

                            
/**
 * @constructor
 * @stateless
 * @module Worker
 */
define(function Worker(){
    var self = this;

    this.calc = function (aAngle) {
      return Math.tan(aAngle);// one of parallel operations here
    }
});

// Now let's create session statefull module, serving user's request and performing all calculations:

/**
 * @constructor
 * @module Processor
 */
define('rpc', function(Lpc){
    return function (){
        var self = this;
        this.process = function(aAngles, aOnSuccess){
            var results = [];
            var w = new Lpc.Proxy('Worker');
            var calced = 0;
            aAngles.forEach(function(aAngle){
                w.calc(aAngle, function(aTan){// Call to LPC stub. Actual calc
                                              // function will be called by 
                                              // Platypus.js runtime probably in
                                              // several concurrent threads.
                    results.push(aTan);
                    if(results.length === aAngles.length){
                        aOnSuccess(results);
                    }
                });
            });
        }
    };
});
        
                                

And here is an example of the asynchronous data-query execution:

                        
        //Let's query data from a database and execute function "doItInCallback" after recieving data
        //The first param used as the succesfull callback function and the second as the failure callback;
        model.myData.requery(function () {
            //some code here
        },function(){
            Logger.warning("Couldn't load data!");
        });
        
        doSomeMoreWork(); //it will be executed immideatly after calling the above requery function without waiting for it's result.
        //there are a lot of functions that could work asynchronius to learn more have a look at the documentation.
                                

Universal UI forms

A form is a kind of a module with UI layout definition in a XML file.
Single-page web application or Java SE desktop application share the same forms. A library of widgets includes a bunch of simple controls, panels and menus as well as smart model widgets which work directly with the model. With visual form editor you can create your application user interface without any coding and knowing about HTML and CSS.

Data is on your fingertips

Use databases native language SQL. You can say exactly what you want from a database: how query data, insert or update. In our platform we go further: Platypus.js can formulate data change commands on the base of SELECT data queries. You can write database-specific queries if you want. ORM subsystem transforms relational data into JavaScript objects.

For example you have an SQL query:


    /**
     * @author greatMan
     * @name testQuery
     * @public
     * @writable employees - this annotation tells Platypus what table could be modified
     */
     
     select t1.employee_id, t1.employee_name, t2.city_name
     from employees t1
     inner join cities t2 on t1.city_id = t2.city_id
                                

This query is connected with module data model. And it became a new JS object. It's time to do a lot of great things with it.


    /**
     * @author oneGreatMan
     * @public
     * @module employeeUtils
     */
    define(['logger', 'orm'], function(Logger, Orm, ModuleName){
        return function () {
            var self = this, model = Orm.loadModel(ModuleName); //this line was automaticly generated on module creation

            this.processEmployees = function () {
                //Model's data sets are regular javascript arrays.
                model.testQuery.forEach(function(aItem){
                    aItem.employeeName = 'Some funny name :)';
                });
                //It will save all data changes at exactly same sequence that they were made.
                model.save(function(){
                    Logger.info('Data have been saved successfully');
                });
            };
        }
    });

Complete IDE for platypus projects based on Netbeans

It's all that you need to whole developing process.


Database structure

SQL queries

Source code

Data model

User interface

Reports