- Web application engine
- Integrated web continuations
- IoC support
- Out of container testing
- Content management framework
- Bidirectional multi-format template engine
- Template content transformation
- Centralized meta-data facility
- Authentication framework
- JDBC abstraction layer
- Database query builders
- Persistence layer
- Configuration framework
- Central application life-cycle management
- Cron-like scheduler
- Asynchronous mail queue
- Content syndication framework
- Resource abstraction
- Web services
RIFE's web engine provides you with a solution that values maintainability above everything else, but without compromising on productivity. Its design enforces the creation of clearly structured applications without laying a significant burden on the developer. Actually, thanks to the declaration of all state transitions in a site structure, the web engine, and incidently every developer, has complete knowledge of the entire logic and data flow of your application. This provides you with unique features, for example:
- build modular applications that can be reused as binary libraries to quickly build new solutions
- make areas of a page behave as isolated, independent and embedded elements
- work in a team without having to document the global behaviour of your web application in detail
- insert new steps into an existing application without changing the existing source code
- change or localize URLs without having to adapt them all through your source code
- layer several complex application flows on top of each-other
- use different JVM languages together in the same application
- and much more ...
RIFE's site-structure drives its web engine and any modifications will cause the appropriate parts of the application to adapt, without restarting the application. By making it easy for a developer to rely on the information in the site-structure without duplicating it, we ensure that everything is centralized in one location.
RIFE's web engine respects the limitations of HTTP as much as possible and provides features that assist you when preserving state through the client-side. Thanks to the site structure, the engine is able to intelligently use a combination of query string parameters, cookies, continuations and sessions for state preservation, depending on the context and the purpose.
Continuations are constructs that are inspired from Scheme. Basically, they contain all information about a specific program location and the local method variables. This enables the application to create an interruption in program execution and continue later at the exact same location as if nothing happened.
Java's virtual machine doesn't have native support for continuations. RIFE however modifies your classes on-the-fly and inserts the required logic in an invisible manner. All regular tools such as debuggers continue to work, but you are now able to use Java language constructs to describe the flow of your web application logic.
Continuations can be hard to grasp, we've made a quicktime presentation (1.9MB) that explains the concept clearly.
RIFE focuses on the retrieval of the references and the injection of objects into the web engine elements.
The instantiation or management of your object references has to be done in participants. These can contain your own personal Java code where you create new objects for the reference keys that are requested, or you can setup existing IoC containers like Spring, Pico, ... and delegate the management to them in dedicated participants.
RIFE web applications can be fully tested outside of a servlet container. This offers much more flexibility and makes it possible to assert conditions based on the site structure and the templates that have been used.
RIFE provides a Content Management Framework that is geared towards the process of storing, loading, validating, formatting, transforming, versioning, retrieving and streaming of various content types. The emphasis has been placed on providing features that are needed when putting content data into a back-end repository and getting the data back out. The actual management of the content once it is stored has not yet been implemented in an elaborate manner. This will however be done in a future version together with the integration and implementation of a JSR-170 query language to search for particular content.
Many template engines start out with a desire to separate presentation from logic. They allow users to push or pull values into the template and then they get stuck. Design is far more complex than setting a couple of values. Users need simple logical constructs and loops, maybe even variables, blocks and scopes, functions to reuse code, and so on ... In the end run, the template engine incorporates an entire language (JSP) or creates a new one (PHP). All this is based on the assumption that the logic provides data which is then decorated and rendered from within the template. However, a fundamental step is missing in the engine design, resulting in an overly complex model that doesn't separate presentation from logic anymore.
When data has been injected into a design, a template engine should allow external logic to retrieve the result and use the concrete version of the layed-out data for output and manipulation. This means that together with incorporating data, a template engine should also provide results and be able to work in a bidirectional fashion instead of the limited common unidirectional approach.
Now the template engine has become extremely simple, no need to integrate any kind of logical constructs or loops. The same logic that provided the data is able to select or repeat results easily. It can extract and combine them and if the template engine is powerful enough, use it as a scratchpad to assemble all the pieces of the layout in an efficient manner. All the required information is already available in the logic. There's also no need to worry anymore about how much logic can bleed into a template and how much has to stay out of it. The entire template becomes totally language independent and designer-friendly.
The content of each template can be transformed at instantiation. This is used to dynamically generate template source code from blueprints before it is parsed by the engine, for example to create themable interfaces or to generate templates at run-time according to class file signatures. One of the standard template transformers that RIFE provides is an XSLT transformer that is able to process XML, XHTML and HTML template types.
The main purpose of constraints is to alter the default behavior of a data type and to clearly set the accepted limits and behavioral directions. The meta-data that's provided through constraints can be used elsewhere to gather more information about how to correctly integrate the additional information.
For example, a constraint specifies that a certain text's length is limited to 30 characters, parts of the system can query this information and act accordingly:
- a HTML form builder can create a field that doesn't allow the entry of longer text,
- a SQL query builder can limit the size of the column in which the text will stored when the table creation SQL is generated,
- a validation system can check if the text isn't longer than 30 characters and provide appropriate information when the length is exceeded.
A large collection of constraints are available and are thoroughly integrated throughout the entire framework.
RIFE provides its own framework for the authentication of web applications. It includes authentication session management, remember-me support and credentials management and validation. The authentication features uniformly support XML, memory and database back-ends. Securing web application parts is done in an AOP-like manner without intervening with the underlying logic. Data that is submitted to pages that are secured will be remembered and automatically resent after successful authentication.
Using raw JDBC directly requires a lot of discipline and boilerplate code. RIFE has wrapped most of the JDBC classes to ensure safe statement execution and proper cleanup. Many common execution patterns have been isolated and abstracted into code templates that can be used to safely perform most database functionalities in only one line of code.
RIFE has a layered approach to database interaction and persistence. We firmly believe that you need to know SQL and your target database before being able to make your applications perform as fast as possible. However, there are many basic operations that are totally analogue amongst database back-ends but differ in syntax. This is why we created the database query builders, which allow you to build your queries through a uniform API and rely on the engine to translate the queries into the appropriate syntax for your target database.
The JDBC abstraction layer and database query builders offer everything to create a generic database persistence engine. It bases itself on the signature of bean classes and uses automatic type and column name mappings. Retrieving, querying and storing bean often only takes a single line of code. Through the support of constraints and callbacks, it's possible to fully customize the persistence behaviour.
The configuration of your applications can be isolated into dedicated XML files. These can optionally be selected dynamically according to the hostname, the user, the operation system, ... This makes it easy to support different configurations for production and development, for different operating systems or for each developer.
Each application is a collection of optionally dependent participants that are responsible for initializing and cleaning up the required context and features. Inter-participant dependencies are resolved automatically and their initialization order is determined correctly without developer intervention. These participants are for example: the web engine, the datasource setups, an IoC reference factory, the scheduler, ...
RIFE provides an asynchronous scheduler as an application participant that can be set up to run tasks at specific moments. The selection of the execution moments are specified in a cron-like format. The definition of the tasks can optionally be stored in a database, so that they still are present after application restarts.
Sending mails in real-time can become a huge bottleneck in popular web sites. RIFE provides a database-backed queue that can be used to store mails immediately. Plain text mails and HTML mails are supported, including attachments. A scheduler task is responsible for sending the queued mails in the background.
RSS 2.0 and Atom 0.3 are natively supported and can be generated in real-time. The data can be provided in a streaming fashion, which makes the memory footprint very low. Elements are available to make the content syndication easy to integrate into a site.
Retrieving and writing resources is completely abstracted. By default, RIFE looks them up through the classpath and provides alternative implementations for filesystem and database back-ends. Clearly defined interfaces make it easy to integrate custom back-ends.