Jakarta NoSQL 1.0.0-b5: How To Make Your Life Easier Around Enterprise Java and NoSQL Databases
The Jakarta NoSQL specification was created to increase the developer experience between Java and NoSQL databases. Learn more about it and its newest features.
Join the DZone community and get the full member experience.
Join For FreeNoSQL databases have become part of the know-how of several organizations, even the most conservative ones, such as financial institutions. However, several tools and frameworks still need to be improved for several languages, such as Java. The Jakarta NoSQL specification was created to increase the developer experience between Java and NoSQL databases. This article will cover more details about the Jakarta NoSQL specification and its newest features.
What Is Jakarta NoSQL?
Jakarta NoSQL is a specification designed to easily integrate Java and NoSQL databases. It uses common annotations and specific APIs for each of the NoSQL database types: key-value, column family, document, and graph databases.
Figure 1: Typical behavior among document NoSQL databases simplified in one interface. The same concept may be applied to key-value, column family, and graph database types.
Using this common API and standard API, it is possible to use several database types without vendor lock-in and low cognitive load to learn a new API. For example, on the Document API, you can use MongoDB and switch to ArangoDB.
Figure 2: NoSQL behavior simplified using Jakarta NoSQL
The entity using the same annotation can explore and switch databases without impacting the application. We can explore the JPA/JDBC analogy here.
Jakarta NoSQL has one implementation, Eclipse JNoSQL, that uses the power of the Jakarta Contexts and Dependency Injection (CDI) specification as an engine, making it compatible with both Jakarta EE vendors and Eclipse MicroProfile.
We recently released version 1.0.0-b5, which simplified several points on the API and added more capabilities that we'll explore in the next session.
What Is New on Jakarta NoSQL 1.0.0-b5?
We're proud to announce the latest version of Jakarta NoSQL with the hottest new features: support for Java records and simplification of the start-up configuration.
Starting with the first one, we eventually want to create immutable entities in our application. Beyond the Value Objects, we can explore this capability on the entity in some cases, such as a historical transaction.
Let's think about a Book
entity where we have an id
, name
, author
, and edition
. Once we create a new book
, we don't edit it anymore. But what about a new edition of this same book? It is considered a new book
; thus, it will keep the previous history of the first one.
public class Book {
private final String isbn;
private final String name;
private final String author;
private final Year year;
private final int edition;
Book(String isbn, String name, String author, Year year, int edition) {
this.isbn = isbn;
this.name = name;
this.author = author;
this.year = year;
this.edition = edition;
}
}
So, we can create this instance using a constructor. Using Jakarta NoSQL, we can explore annotations to the constructor on this approach. As you can see, we need the annotations on the constructor to teach how to create an entity. It will work when there is a constructor with an argument or a constructor with either the @Id
or @Column
annotation.
@Entity
public class Book {
@Id
private final String isbn;
@Column
private final String title;
@Column
private final String author;
@Column
private final Year year;
@Column
private final int edition;
Book(@Id String isbn, @Column("title") String title,
@Column("author") String author, @Column("year") Year year,
@Column("edition") int edition) {
this.isbn = isbn;
this.name = name;
this.author = author;
this.year = year;
this.edition = edition;
}
}
This is nice, but it seems like a lot of code. Can we simplify it? The answer is, yes! If you use Java 17, the latest LTS version, Java records streamlines this for us.
You can take advantage of this with the latest version of Jakarta NoSQL to reduce code as shown below:
@Entity
public record Book(@Id String isbn,
@Column("title") String title,
@Column("author") String author,
@Convert(YearConverter.class) @Column("year") Year year,
@Column("edition") int edition) {
}
That is it! Let's execute this piece of code on Jakarta NoSQL exploring this record feature:
@Inject
private Template template;
String id = UUID.randomUUID().toString();
long start = System.currentTimeMillis();
Book book = new Book(id, "Java Concurrency in Practice", " Brian Goetz", Year.of(2006), 1);
template.insert(book);
Optional<Book> optional = template.find(Book.class, id);
System.out.println("The result " + optional);
long end = System.currentTimeMillis() - start;
System.out.println("The total operation is: " + end);
template.delete(Book.class, id);
Done! We're exploring data integration with Jakarta NoSQL. But wait: where is the database information? The Template
interface represents the common class to operate between Java and NoSQL databases. Thus it might be Key-Value, Document, Graph, Column Family, or more database types that the specification might have in the future.
As with any design decision, there is a trade-off of not having particular behavior for each database type. Let's explore the capability of Document
type with MongoDB, where we want to find fields and not only the key. Thus, we can use the DocumentTemplate
interface, a specialization of the Template
interface with more document database capability.
As with any class, we can create methods on records and use them. Let's include a way to create a subsequent edition of a book, such as Effective Java, which is currently in its third edition.
public Book nextEdition(String isbn, Year year) {
return new Book(isbn, this.title, this.author, year, this.edition + 1);
}
As with any new feature, there are several approaches to use and make it easier, such as a builder
method, when there is a need to create more complex immutable entities. However, it won't be the focus of this article. The next step is to code both the Java record and DocumentTemplate
in action, where we'll return all of those book editions ordered by descending order of the year.
@Inject
DocumentTemplate template;
Book first = new Book(randomUUID().toString(), "Effective Java", "Joshua Bloch",
Year.of(2001), 1);
Book second = first.nextEdition(randomUUID().toString(), Year.of(2008));
Book third = second.nextEdition(randomUUID().toString(), Year.of(2018));
template.insert(List.of(first, second, third));
DocumentQuery query = DocumentQuery.select().from("Book")
.where("title").eq("Effective Java")
.orderBy("year").desc().build();
System.out.println("The Effective java editions: ");
template.select(query).forEach(System.out::println);
template.delete(Book.class, first.isbn());
template.delete(Book.class, second.isbn());
template.delete(Book.class, third.isbn());
We integrated MongoDB and Java, but where is the configuration? Jakarta NoSQL 1.0.0-b5 explores the convention over configuration where all the properties will be read in real-time using the same principle of both Jakarta Config (still under development) and Eclipse MicroProfile Config specifications that follow the Twelve-Factor App.
The code shows the properties for running MongoDB locally, where the first property belongs to the database that the application will use. You can see the properties of each NoSQL driver on its repository. It breaks compatibility with the previous version. Please pay attention to the migration:
jnosql.document.database=library
jnosql.mongodb.host=localhost:27017
If you wish, you can programmatically define the configuration. For this, you need to create a class that implements the Supplier
of a database manager and then, as an alternative, with a priority higher than zero. It is natural if you are familiar with CDI.
@Alternative
@Priority(Interceptor.Priority.APPLICATION)
@ApplicationScoped
public class ManagerSupplier implements Supplier<DocumentManager> {
@Produces
public DocumentManager get() {
...
}
}
This is the end of the journey of the newest features of Jakarta NoSQL today. The next step is to work with the Jakarta NoSQL community to support Jakarta Data, a new specification that was launched in 2022.
If you have never heard about Jakarta Data, it is a specification that aims to create an agnostic data pattern on Java. The first release was to make the repository capability and pagination.
As a Java user, we'll handle only a couple of annotations and interfaces where the vendors will implement everything else for us.
Summary
In this article, we explored what’s new on Jakarta NoSQL 1.0.0-b5. It is a vast effort for the Java community to make Java and NoSQL more natural, especially in enterprise applications. Furthermore, there was significant work to improve the documentation and make it a first-class citizen.
As the next step, the Jakarta NoSQL team will work closely with both the Jakarta Data and Jakarta Config specifications to explore the best practices on application and code design at the specification, such as the DDD repository and the twelve-factor app.
You can review, provide feedback, and implement code as an open-source and community-driven project. After all, better than waiting for a new feature is participating in it.
References
Opinions expressed by DZone contributors are their own.
Comments