In this post, we will look at an implementation of the common “Bookstore” application as a single Microservice. We’ll discuss the architectural benefits & performance the Microservice coded in Baratine presents compared to a JAX-RS implementation.
In doing so, we put forth the idea that a single-threaded asynchronous architecture has a faster and safer path to production & scaling over the inherently flawed traditional multithreaded models.
Part 1: The Service
Our Baratine Bookstore is only 40 lines of code in its entirety, so let’s take a look at the entire application:
- @Service creates a single-threaded service. Because it is single-threaded, we do not need synchronization and can use a simple HashMap.
- @Get(“/books”) maps the method to a GET request at the URL “/books”.
- Then result.ok() completes the asynchronous request.
That’s all there is to it. The service is fully self-contained, and because we used Baratine’s Result, all of our methods are nonblocking (do not tie up threads in the background) and can be called concurrently. It’s also worthwhile to point out this API can be consumed by a client of any language that can understand JSON.
Now Let’s Take a Look at JAX-RS
- JAX-RS requires three files: an application class, a path class, and an empty web.xml.
- It must use a ConcurrentHashMap because the application is multi-threaded.
- It must be deployed in a container like Tomcat or JBoss.
In terms of complexity, JAX-RS is more complicated than Baratine (albeit more configurable). It requires at least 3 files, a servlet container, and the developer needs to mind concurrency issues.
Even though Baratine is single-threaded, it easily outperforms JAX-RS (RESTEasy) by over 2x. You can scale out Baratine to take advantage of all the CPU cores on your machine and Baratine will scale up linearly – something that you cannot do with JAX-RS.
Our bookstore example stores the data in memory. What about saving it to a database? Persistence is out of the scope of JAX-RS and it forces you to use another library like JPA. With Baratine, it comes with a document-style persistence layer. No additional libraries and only a trivial change to our bookstore:
There are only two changes to our bookstore:
- @Data added to the class, to tell Baratine to save this object into its internal reactive database.
- @Modify on addBook() to tell Baratine that this object has been modified and that Baratine should add it to the save queue.
Even though the new bookstore is persistent, we still get the same high performance as before because the persistence is asynchronous and bookstore operates mostly in-memory. That is the beauty of Baratine and only possible because Baratine is reactive. There are no comparable platforms out there.
If you would like to expand this application, take note of the following Baratine maven dependency that was used: