The divide-and-conquer strategy decreases the complexity of systems within modules or structures. These structure levels split responsibility and make maintenance and replaceability more clear. The new Jakarta NoSQL API proposal is going to be a bridge between the logic tier and the data tier. To do this, we need to create two APIs: one to communicate to a database and another one to be a high abstraction to the Java application. This post explains why Jakarta NoSQL would use this strategy as an initial step.
In software, there are structures: tiers, physical structures, and layers. The multi-tier application has three levels:
- Presentation tier : Has a primary duty to translate results so the user can understand.
- Logic tier : Has all business rules, processes, conditions, saved information, etc. This level moves and processes information between other levels.
- Data tier : Retrieves and stores information in either a database or a system file.
Talking more precisely about the physical layer and the logic to separate responsibilities, there are other layers.
The logic tier, where the application and the business rules stay, has additional layers:
- Application layer : The bridge between the view tier and logic tier, e.g. convert an object into either JSON or HTML.
- Service layer : The service layer; this can be either a Controller or a Resource.
- Business Layer : This is the part of the program that encodes the real-world business or domain rules that determine how data will be created, stored, and changed.
- Persistence Layer : This is a layer that provides simplified access to data stored in persistent storage of some kind.
Within a persistence layer, there are more layers: A Data Access Object, DAO , is a structure that connects the business layer and persistence layer. Inside, it has an API. Currently, there is a difference between a SQL and a NoSQL database:
In the relational database, there are two mechanisms under DAO, JDBC, and JPA:
- JDBC : a deep layer with a database that has communications, underlying transactions, and is basically a driver to a particular database.
- JPA : A high layer that has communication with either JDBC or JPA. This layer has a high mapping to Java; this place has annotations and an EntityManager. In general, a JPA has integrations with other specifications, such as CDI and Bean Validation.
A considerable advantage of this strategy is that one change, either JDBC or JPA, can happen quickly. When you change a database, you need to supersede to a respective driver by a database, and then you’re done! The code is ready for a new database change.
In a NoSQL database, there isn’t a strategy to save code, and there is little impact for change. All APIs are different and don’t follow any one standard, so one change to a new database can result in a lot of work.
- The database vendor needs to be worried about the high-level mapping to Java world, and the solution provider needs to be concerned about the low level of communication with a particular database.
- The database vendor needs to “copy” these communication solutions to all Java vendors.
- To a Java developer, there are two lock-in types: If a developer uses an API directly for a change, it loses code. If a developer uses high-level mapping, they lock-in a Java solution because if this high level doesn’t have the support to a particular NoSQL database, the developer needs to change to either a Java solution or use a NoSQL API directly.
A wise recommendation might be to use the JPA because once the developer already knows this standard SQL API, they can use the same API for a relational database and apply it to a NoSQL database. Using an API with SQL concepts in NoSQL is the same as using a knife as a spoon; the result is a disaster! Furthermore, the NoSQL world has diversity with several data structures and particular behavior to each provider, and both matter in a software solution. Indeed, the merge strategy to use just one API is still a discussion nowadays .
A good point about using NoSQL as a consequence polyglot persistence is that data storage is about choice. When a database offers gains, it sacrifices other aspects; it is the CAP theorem slamming the door. Hence, an API generic enough to encapsulate all kinds of databases might be useless.
The history between Java and NoSQL has several solutions that can be split by two:
- NoSQL Drivers
- Mapper Agnostic
- Mapper Specific
The first one is the driver API; this API has a low communication level, such as JDBC to NoSQL. It guarantees full power over the NoSQL database, a semantic closer to a database. However, it requires more code to move it forward to the entity domain the portability is pretty down; therefore, the learning curve.
The Object Mapper lets the developer work in terms of domains, thus it can help a developer follow ethical practices. A mapper may be specific, which means that a mapper is made for a particular database, so the mapper will support all the database features but with the price of a lock-in API. On the other hand, there is the agnostic mapper that uses a generic API to encapsulate the database API, which allows a developer with an API to connect several databases; however, it tends to either not cover numerous features in a database or many databases.
The rapid adoption of NoSQL combined with the vast assortment of implementations has driven a desire to create a set of standardized APIs. In the Java world, this was initially proposed in an effort by Oracle to define a NoSQL API for Java EE 9. The justification for the definition of a new API, separate form JDBC and JPA, was the following:
- JPA was not designed with NoSQL in mind
- A single set of APIs or annotations isn’t adequate for all database types
- JPA over NoSQL implies the inconsistent use of annotations
- The diversity in the NoSQL world matters
Unfortunately, what Oracle proposed for Java EE 9 was not completed when Java EE was donated to the Eclipse Foundation.
To bring innovation under the Jakarta EE umbrella, Jakarta NoSQL was born. The goal of this specification is to ease integration between Java applications and NoSQL databases, with a standard API to work with different types and vendors of NoSQL databases. To achieve this, the spec has two APIs that work like layers, and each layer has a specific goal that can integrate between each and use in isolation:
- Communication API : Exactly what JDBC is to SQL. This API has four specializations, one for each type of database (column, document, key-value and graph). The specialties are independent of each other, optional from the point of the database vendor and have their specific TCKs.
- Mapping API : This layer is based on Annotations, analogous to JPA and CDI, and preserves integration with other Jakarta EE technologies like Bean Validation and so on.
Jakarta EE NoSQL is the first specification in the Java enterprise . As any Java specification, it analyzes solutions that already exist, checks the history with both success and failure cases, and then goes in a direction that has a lesser number of trade-offs in an API architecture. The divide and conquer method fits well in the layer, communication, mapping, and NoSQL types. Thus, it will provide a straightforward specification, light maintenance; it will define the scope of each API; and it will work better in extensibility once the particular features matter to a NoSQL database.
Jakarta EE has a bright future with a significant integration with the community and open source. More transparency, after all, is the most meaningful power of Jakarta. It’s not the technology itself, but the heart of the community, therefore, the success is in the hand of each developer.