Solvent is a modern web-based web application development platform. It combines traditional IDE features with an innovative middle-ware layer that makes building web applications simple and fun. Solvent is built atop the Java platform and the diagram below shows how it fits into the Java stack.
The Solvent middle-ware layer is a light-weight execution engine that executes the artifacts created via the Solvent developer environment application. Foundamentally, an executable represents an encapsulation of concerns usually associated with running web applications. In the stack diagram above, the Solvent middle-ware is the execution engine instance hosted inside a Java web application, this instance is a POJO singleton. Specifically an executable has the following structure.
An executable construct is made of the the following components:
Pre Execution handlers
Post Execution handlers
This basic construct completely describes an executable and how to execute a particular executable. For instance assuming an executable represents a script in some programming language to perform a certain database action.
The executable is able to describe security restrictions associated with this action.
The executable is able to describe all parameters associated with this action (for instance say account number)
The executable is able to specify which actions must be completed before this action (these would be invoking references to other executables).
The executable should describe the primary action in the form of an executable logic (run script, db action, upload file, send email..etc).
The executable should specify any ex-post actions that must be completed after the primary action
Executables exist in two forms, definition form and executable form. Executable definitions are basically the source form of an executable, you “compile” an executable definition to make it into the JSON formatted executable file. These executables are then executed by the engine. When you deploy applications on the Solvent platform, executable files along with other assets are what you'll deploy as your application.
From Solvent application tab, you can refresh an executable to update it with the latest changes to its definition. In general whenever you alter an executable definition, an alert shows up with a list of all executables derived from this definition that may have become staled as a result of the update.
Executable definitions are stored in a database called the Execbase. The ExecBase mirrors the design concerns outlined in the executable structure/design principle section. The following tables are present in the execbase:
In addition to the executable definition tables, there are the following:
Note that the execbase is only to support application development. This database isn’t useful for executing executables. In other words when an application is deployed to production, the execbase is not a part of the application.
The Solvent environment has a taxonomy structure around the execbase. This taxonomy allows for browsing the execbase in a manner similar to browsing a file system. The taxonomy has two types of nodes, category nodes and executable nodes. Category nodes can contain other category nodes and executable nodes.
The Solvent middle-ware engine has an argument map that is used for propagating arguments across executable calls. Think of the argument map as similar to the HTTP_POST/GET maps in languages such as php. There are various modes of argument propagation :
The argument map is available to ScriptExecutor executables as an object named arguments, it is natively an instance of java.util.HashMap.
"Final" parameters are parameters whose values cannot be overwritten by incoming argument maps.
solvent_empty_string is available for initializing parameter values with empty string, otherwise the value is null. The usage syntax for this parameter is
Additionally, an existing variable on the argument map can be referenced as the value for a subsequent parameter by using
[@|:]<variable-name> syntax as the default value for the parameter you want to assign the value to.
Solvent applications are plain Java web applications. This means your application would be deployed into your environment just like any other application. There is absolutely nothing different about how you deploy a regular Java web application and how you deploy a Solvent application on an app-server. Ok, now you are wondering, so I have to redeploy my apps everytime I make a tiny change? No!!!
What the Solvent platform allows, is for the application deployment to be further abstracted. Similar to how you can drop jsp files into a running application (war file), you can drop executable into your application directory without actually re-deploying your war file. The war file only needs to be redeployed when a jar component changes, or you need to change your application directory. Both of these activities occur sparingly during the development of a web application, the hassle of re-deploying war files is significantly minimized.
The applications you build on Solvent are POJWAs (Plain Old Java Web Applications)
You need to specify the base directory of your application assets including executables. There are varous directories that can be set. By Default these are set to the asset directory sub-directory that your application is created in. You should only need to set most of these for production deployment, not during development.
The developer studio application, which is the application that you use to build your Solvent applications, is destributed as an integration of jetty container and the derby embeded database, it contains the following important directories:
The developer studio's asset directory is solvent-apps/crudzilla, this directory is the developer workspace that holds all applications. The developer studio application's base executable resource directory is solvent-apps/solvent/com/codesolvent/Solvent, in other words, the platform parameters
all point to this directory.
Note: The app-home servlet init parameter can be set as an absolute path or as a path relative to the solvent-apps directory.
There are six types of executables available on the Solvent platform. Below you'll find a detailed explanation of all of them.
ScriptExecutor executables have a number of native objects available to scripts.
Solvent supports html templating via the Velocity engine. Templates are a type of ScriptExecutor. Templates support a number platform parameters:
These parameters can be set globally at the engine level or individually on a template executable.
DataStatement executable type is responsible for supporting all sql based database interactions. It is what would be used for doing C.R.U.D operations in a web application. The DataStatement executable type is a vastly superior approach for doing C.R.U.D than existing approaches including ORM. DataStatements facilitate ease of use that exceeds that of the ORM approach while effortlessly granting a developer the full power of SQL.
DataStatements are not only the easiest way to do C.R.U.D operations, they are also robust and support safe database interactions. Some points of note about DataStatements include:
A reference can be set to a ScriptExecutor which can serve as a custom resultset processor. This is an advanced capability which gives the developer full control over the processing of the resultset from an executed query. The resultset is available as a variable called solvent_datastatement_resultset. This is a JDBC result object type.
DataStatements also support the platform parameter solvent_javalang_class. Set this to the fully qualified Java class name if you want the resulting data to be converted to a Java bean of the specified class type.
The platform parameter solvent_default_datasource should be set as part of solvent/solvent-app-settings/system-settings to specify a default data source for newly created DataStatements. This would be automatically filled in when ever a new DataStatement executable is created. Most business applications only have a single data source, so this would save the developer a few extra clicks.
The platform parameter solvent_resultset_format is available for use with DataStatements. The value can be one of the following:
DataStatements support type hinting, this is useful for RDMSs that have strict type requirements for prepared statement parameters. To specify a type simply enclose the type in parenthesis following the parameter name. The syntax is as follows:
When a type hint is supplied with a specified parameter, the following additional parameters may be supplied.
For types: BINARY, VARBINARY, LONGVARBINARY,CLOB,BLOB
you may also upload files in place of data for these types, so for instance you may call a datastament in a multipart http request that includes an image file to be stored in a blob.
The types supported are either Java types or SQL types, in other words JDBC types.
Instantiators are easily one of the most useful executable types on the Solvent platform. The Instantiator exposes the NVP Processing mechanism for general use by applications. Instead of the parameterization mechanism only serving executables, it is exposed as a executable type of its own with Instantiators. What this facilitates is an incredibly flexible and versatile facility for creating data structures. Data structures constructed via an Instantiator can get their data from any number of sources including from other executable types such as DataStatements or HttpConnectors.
You may now be wondering, well what can I use an Instantiator for, well the simple answer is: almost anything!
Instantiator executable types support the platform parameter solvent_javalang_class, the value can be the fully qualified class name for the resulting bean. It can also take the special values map for HashMap or list for ArrayList.
The default return value is a generic classless Java bean, however if the name is missing for all parameters, then the Instantiator return type is assumed to be a list. In all other ways, the Instantiator uses the parameterization mechanism as with the other executable types.
This executable type supports file uploads. It supports automated file naming and file unzipping, specifying upload directory. It relies on the apache commons fileupload component. Again you write no code, just create a FileUploader executable type, configure it and you can do file uploads. The file uploader relies on the solvent_temp_upload_directory platform parameter. This parameter should be set as part of the solvent-app-settings/system-settings.
This executable type implements the apache smtp component. You can use it to connect to an stmp server and send emails. The email text itself needs to be generated from a velocity template. If you’ve ever had to configure your emails in text files or awkward database entries, you’ll smile when you have to send emails on Solvent.
Even a platform such as rails which prides itself on making such task simple is simply no match for what Solvent offers. To put simply, sending emails in a Solvent application simply makes sense. Your email templates can be edited and previewed, so you know exactly what it looks like.
Because emails are velocity templates, you can incorporate logic and data into your emails easily, sending reports and customer account information becomes a trivial task.
Did I mention, no writing code?
This executable type supports connecting to external systems via http. Excellent for doing RESTful operations. You can use this to consume webservices and other types of integration. This executable type uses the apache commons http client components and supports all the options supported by that component. The component has several parameters with predefined values. This executable type depends on the platform parameter solvent_temp_upload_dir when request includes file upload.
Solvent provides a simple way to run tests of your application. You can run numerous tests for different test cases.
The CEE maintains a cache for executables at runtime. When an executable is requested for the first time, if there is a cache miss in the executable cache then that executable is loaded from disked and cached. Subsequent requests for that executable will not reload the executable from disk but rather use the cached executable.
The Solvent monitors the application directory for any changes to executables and invalidates the currently cached version of an altered executable.
Solvent needs to be configured via an Instantiator. Solvent would look for a servlet init property called app-home that is assumed to point to the relative path of the application base directory, settings are stored in the instantiator solvent-app-settings/system-settings.ins. This would be executed and the data used to start the engine.
Database Table and Column pooling is an experimental technology introduced in Solvent that allows for further abstraction of the database. The basic idea is to view database tables and columns as storage constructs as opposed to modeling constructs. Modeling is then facilitated in Solvent via Instantiators. This technique allows for numerous data models to be mapped to a small pool of database tables and columns, as opposed to creating a table for every model.
This technique would be particularly useful for developing products that have third-party extensions/plugins. By using an approach where component developers know beforehand that there is a pool of database table and columns, data aware third-party components can be built and integrated with ease.
Column pooling works by assuming a database table exists with a pool of columns of various types. A flexible data model can then be constructed to map fields to available columns of appropriate type. The DataStatement executable type is capable of recognizing a data model reference and substituting the corresponding database table column in the compiled sql query.
There are of course obvious weaknesses associated with this approach, it should be used only where the benefits significantly exceeds the shortcomings.
Every executable definition can specify access restriction based on a user's identity. The identity is specificied by user-name and role. This approach to application security is transparent and makes security audit and enforcement a trivial task.