The applications generated by Livebase are complete systems capable to run a query and managing relational databases. The operations allowed range from the simple manipulation of individual objects/class rows/tables (insertion, modification, deletion), to the processing of very complex queries involving hundreds of classes and exploiting all the power offered by the Designer: in addition to the static structure of the domain, our development environment allows us to define directly in the application model also the application logic in terms of expressions, filters, aggregation operators.
The purpose of Livebase is to implement applications quickly and in a intuitive way following a declarative and low code approach.
Our philosophy also embraces the evolution of systems. A system that evolves not only must be able to scale up (increasing the volume of interactions, data, users) or offer new services and functionalities: indeed, it is important that the possible evolution scenarios are varied and diverse. For this purpose, the evolution maintenance tools we provide support modellers/developers in this critical activity.
Complex requirements #
What happens when, during the evolution of the system, the necessity to implement complex requirements arises?
First of all: what is a complex requirement? It is, in most cases, some functionality that is simple to describe or imagine at conceptual level, but whose realisation may be difficult, or even impossible, when a convenient tool is not used or the appropriate approach is not applied.
Suppose we have built a Cloudlet to manage an e-commerce system to which end users interact via a dedicated front-end, while administrators use the GUI configured in the model to manage the back-office. For example, some interactions could be the following:
- An administrator logs in to the generated application;
- An administrator uploads a .pdf file on a form;
- A user confirms a purchase: the application receives from the front-end a “create confirmation” (save) request of an object of class Order.
Now imagine that we define, in our application, a behavior in response to each interaction:
- The application runs additional security checks before authenticating the Cloudlet member;
- The application accesses the file, processes its contents and creates one or more objects populated with the information it contains;
- The application traces the Customer associated with the Order and sends an email to them containing a summary of the details of the purchase, accompanied by a receipt in a .pdf file.
We have therefore described three requirements concerning event management, file processing and interaction with external services.
Is it possible to code these actions in the model, using exclusively the low-code tools offered by Livebase? As of today, the answer is probably not; however, even if we could re-imagine the requirement to be able to declare queries, filters, expressions that can accomplish it, the solution would be unnecessarily complicated. Moreover, the resulting model would be fouled by intermediate elements that, taken individually, would not be reusable and would therefore not add any value to the application.
Extending the application with plugins #
An effective solution is to modify the source code of the application and implement the desired behaviour directly using a high-level programming language. This is where the Livebase plugins come into play.
As we will see in this guide, plugins are a simple but extremely flexible tool, designed to both extend the basic functionality of the application and to define entire automated processes and implement integrations with external services.
Modeling + Coding = Profit! #
We have highlighted the relationship that links the complexity of requirements to the expressive power of low code tools; on the other hand, the purpose of the tool is to help the designer to realise, in the shortest possible time, most of the system requirements.
Taking any sufficiently specialised system as an example, and considering the tools currently offered by Livebase, we can assume that this set represents 80/85% of the total requirements (the part in green); in particular, it includes all the basic functions of the application up to a sufficiently complex level (queries, filters, reports, etc.).
The plugins aim to facilitate the implementation of the remaining 15/20%. In this regard, their role is crucial for two reasons:
- make the evolution of the system independent of that of the development tool: the development of Livebase and plugins goes hand in hand, and future versions of Livebase may open up support for scenarios previously only manageable by plugins (the bit in yellow);
- supporting the most complex requirements: no low-code tool, no matter how powerful, can ever be universal; every system will always have requirements that will require ad hoc code (the red bit), and it is because of these that we encourage plugin development.
Service Handler #
The mechanism behind a Livebase Plugin is the Service Handler: in the model it is possible to declare entities, called Handlers, responsible for managing some services of the generated application.
In the engine model, a Handler is an element of a class identified by a name and a type; each different type is designed to inject custom logic at a specific point in the generated application.
When generating the application, Livebase then checks for the presence of Handlers in the model and generates for each one a Java SPI (Service Provider Interface). These are then collected in the jar SPI, a library that can be used to implement Service Handlers.
Here is an example of a plugin working:
In the model in figure there is the declaration of a FormActionHandler on Class1, which will correspond to a Handler interface in the SPI. When the user clicks on the myAction button on the Class1 form during edit, the corresponding service will be triggered: its Handler implementation will have access to the filled fields of the three attributes and will be able to change the displayed value or use them for any other purpose (a generic action).
Our goal is then to provide the code to handle the call to the specific Service Handler; the resulting plugin will contain the Java classes implementing the Handler Interface plus all supporting packages and runtime dependencies.
Services and execution environment #
The runtime interconnection between the Cloudlet and the respective plugins is provided by the OSGi based execution environment. In this environment, Cloudlet and plugins are bundles that cooperate by publishing and searching services on a dedicated registry of the framework.
For further reading, please refer to the article Plugin: Execution environment.
Developing Livebase Plugins #
In this article we have introduced the fundamental concepts related to Livebase Plugins: the Handlers, the SPI and the services. Then we will illustrate how to develop a generic plugin and we will deepen the available tools, methodologies and best practices.
Read more: Development cycle.