Skip to content
Jan Wiemer edited this page Dec 30, 2020 · 20 revisions

Java ACI Store

A transient and transactional store for Java objects. The name JACIS is derived from the acronym ACID (Atomicity, Consistency, Isolation, Durability) describing the properties of transactions (see e.g. Wikipedia). The store is designed to fulfill the first three of these properties. The Durability is not a core feature of the store but it is possible achive it using an extension.

The first chapter of this document describes the motivation behind the project and the basic design principles behind it. If you like to start hacking immediately you can skip this chapter and directly jump to the Installation chapter.

Motivation

In the last decades Java became more and more popular, specially for classical enterprise applications. The setting is often quite similar: a set of business objects is stored in a database, a server application accesses the data, implements the use cases and provides an interface (often REST) that a client (often WEB) can use to preset the business logic to the user. Most use cases provided by the system follow a similar pattern: first fetch the needed data from a database, then do the required operations on the data and finally update the changes in the database. Specially for this type of applications enterprise Java frameworks (JEE / Jakarta EE) are very strong. Matters of concurrency, consistency and visibility of the data are mostly delegated to the database. The application is only responsible for the proper demarcation of the transaction boundaries. In JEE / Jakarta EE this can usually be done using annotations so the actual code can focus on the business logic. The approach works very well for the described application type and developers can become very productive using the JEE programming model. In the recent years another type of application became more and more popular: cloud applications. Here concepts like reactive programming and frameworks implementing the MicroProfile standard become important.

A little less common are algorithmic applications requiring a lot more computation on the data. Sometimes these computations include quite complex optimization algorithms that are often critical to the performance of the overall system. An additional challenge can be the need to process high frequent events incoming e.g. from technical devices. These events usually have to be handled using multiple threads. A typical example is a system steering an automated warehouse with many different transport devices. The goal is to optimize the overall material flow which often includes the need to solve different optimization problems. In scenarios like this the typical pattern used for enterprise application often reaches its limit. The algorithms usually have to work on a transient (in memory) representation of the relevant data to guarantee the required performance. It would be too slow to fetch the neded data from the database again and again. During operation parts of the transient data change and some of these changes have to be persisted in the database to be durable (and sometimes to be visible to other applications).

As soon as we are working concurrently with transient data, we have to care about synchronizing the accesses. Furthermore we usually need a concept of transactions (see chapter Transactions) as well, otherwise we would have to solve several subtile problems on our own (and probably in the end come to a similar concept).

Design Principles

The idea of the JACIS project is to provide a solution to the problems described above and enable transactional access to transient data. A main goal is to keep the solution as simple as possible. This refers to the concepts, the internal structure of the code, the amount of external libraries and the usage (API) of the system. Even the selection of the features implemented for the JACIS project was guided by this principle. It is not enough that a feature is desirable for the user, it also has to fit to the general concept and must not increase the complexity too much (an example of a feature that was excluded for this reasons is the serializable isolation level). Furthermore any kind of byte-code manipulation, code generation or other concepts introducing "magic" behavior should not be used. Neither the applications using JACIS should be forced to do so. In summary the most important design principles for the JACIS project are:

  • Keep it simple and stupid (KISS).

  • Focus on core features with the possibility to extend them.

  • Keep dependencies on external libraries to a minimum (core functionality only uses standard Java and SLF4J logging API).

  • Avoid code generation, byte-code manipulation.

  • Verify functionality by automated unit tests (JUnit) executed in a continuous integration (CI) build (see Jacis-CI-Build).

  • Stay near to the standard Java code formatting guidelines (standard Eclipse settings, only tab-width and line-wrapping changed).

  • Avoid all warnings detected by Eclipse (Zero-Warning-Policy).

Semantic Versioning

Starting with version 2.0.0 the JACIS project follows the semantic versioning policy. In short a JACIS version number has three components: MAJOR.MINOR.PATCH. Depending on the changes the component version numbers are incremented as follows:

  • MAJOR version when you make incompatible API changes;

  • MINOR version when you add functionality in a backwards compatible manner;

  • PATCH version when you make backwards compatible bug fixes.

Intermediate (not released) versions get the suffix -SNAPSHOT.

The API of the JACIS consists on

  • the public API of all classes that can be reached (via public API) from the JacisContainer class;

  • the interfaces / abstract classes that have to be implemented / extended to provide extensions;

  • the exceptions that may be thrown by the store.

To simplify it all classes belonging to the API are annotated with the @JacisApi annotation.

Next Chapter: Transactions