Four steps to move from Spring to Vertx

During last two years, when I publicly established myself as a Vertx freelance consultant, I received a number of messages, both from developers and managers, that asked me something like “I am interested in using Vertx in production instead of Spring, yet I don’t understand how I could migrate”. As Spring developers we learned a number of design patterns and tools (yet, it is disputable, how good are they) and when we move into the Vertx realm we are overwhelmed by its “freedom”. It does not mean, that Eclipse Vertx is something totally different – at the end of the day it is a Java framework! In this post I would like to talk about four most common pitfalls, where Spring developers are struggled when they move to Vertx.

Step 1. Understand architectural patterns

The Spring ecosystem brought a number of design techniques (many of them are originated from EE), that are familiar for any Java developer who builds web applications. To name the few: Model-View-Controller paradigm, package organizations by layer or business domain, repositories, business services etc. From the other hand, Vertx makes it completely optional to developers how to organize a code. I have seen codebases, where code was messed like in microframeworks.

Such power, of course, means a higher degree of responsibility! Hopefully, you can migrate familiar design patterns to Vertx land. A common unit of code in Vertx is called a verticle. It is common to define it as something close to Akka actors (and I also like this definition). But, you can utilize verticles in order to define an app architecture in Spring terms. For example, in my book “Principles of Vertx” I name two common approaches:

  • Use verticles as Spring services and therefore you can define a single verticle per business domain (like you do in packaging by domain)
  • Use verticles as levels: this technique is more suitable for small apps. You can use a verticle for database operations (repository), a verticle for HTTP handling (controller), a verticle to connect with external integrations (client) etc.

To sum that up, it does not mean that moving from Spring to Vertx should be a complete code anarchy. Opposite! You can bring familiar architectural techniques as Vertx is a completely flexible framework.

Step 2. Survive in a callback hell

Another pain point that rises from a reactive nature of Vertx is called callback hell. The framework relies on async callbacks, that instead of returning of a result, define handlers, to obtain a result after some time. Non-blocking execution is a great feature and it ensures resiliency, but it is hard to understand. Compare these two snippets. The first code block demonstrates blocking code from Spring:

Option<Invoice> invoice = invoiceRepository.findById(id);
if (invoice.isPresent()){
    SendingResult result = emailClient.sendInvoice(email, invoice.get());
    if (result.isSuccessful()){
        return true;
    } else {
        return false;
    }
}
return false;

This is a fictional code, that retrieves an invoice from a database, and if it exists, send it to a customer by email. It is easy to understand as we complete steps sequentially:

  1. Retrieve an invoice
  2. Send an invoice
  3. Assert results

The Vertx programming model ties with callbacks, so the same code will look totally different:

repository.findInvoice(id, invoiceResult ->{
    if (invoiceResult.succeded()){
        Invoice invoice = invoiceResult.result();
        client.sendInvoice(email, invoice, sendResult ->{
            if (sendResult.succeded()){
                SendingResult result = sendResult.result();
                future.complete(result);
            } else {
                future.fail(new SendingException());
            }
        });
    } else {
        future.fail(new DatabaseException());
    }
});

Instead of returning results, functions rely on handlers (invoiceResult, sendResult) and uses a concept of futures (which represents a future result of an asynchronous computation). By the way, Spring Webflux uses same idea, so it also will bring you into a callback hell.

The biggest problem with callbacks (and not only Vertx) for developers is to understand an order of things are done. You also need to remember that a next callback in a sequence will not be involved, until a previous function will execute and will call a result handler. I can recommend here following:

  • Remember about a single responsibility principle, e.g. create functions that do only one thing and don’t put many steps in a single function
  • Handle erros. Vertx handlers allow you to pass a Throwable instance as a reason of an error. You can use various exceptions in order to distinguish a failed step

Step 3. Use familiar tools

The Spring [Boot] framework is basically a collection of mainstream Java libraries. Jackson, Commons, Vavr, Lombok, Thymeleaf, Eclipse, JUnit – you name them. Vertx is also a Java-based technology, so who says you can’t use familiar libraries with Vertx? Moreover, many of them are already included. For example, Vertx uses Jackson to handle JSON operations. There is a Thymeleaf integration to handle template rendering in Vertx.

To sum this point up, I want to say you, that if a library works with Spring it will work with Vertx too. Of course, you may need to wrap it inside asynchronous callbacks – in a such case, go to the step 2.

Step 4. Do you need ORM? Really? You can use it!

This step is in a some way an extension of the previous one. Many developers who ask me about using their familiar Spring tools with Vertx – almost 85-90% – mean Hibernate. To be honest, I am not the person who thinks that Hibernate is an example of good architectural practices. In a contrary, I am the person who thinks that Hibernate is an example of bad architectural practices, but it does it job as an ORM and working with relational databases in a manual way is even worse thing.

Please note, that when I use a word “ORM”, I really mean not only Hibernate, but also other Java ORM libraries, like Apache Cayenne, EBean, JOOQ etc. So, in their foundation, ORM libraries rely on JDBC, which is a blocking technology and therefore should be avoided when developing reactive apps (yet it does not mean that it is not compatible with Vertx – see step 3). In this regard, you can choose one of two approaches:

  • Use JDBC-based tools, but wrap them in worker threads, so they will not block a main execution flow of your application
  • Use reactive counterparts – some of popular ORM tools, like Hibernate and JOOQ have reactive versions, yet for the time of writing this post they are still very raw and may not be suitable for production

Conclusion

As you can observe, the migration from Spring to Vertx is not painful. Many developers and managers stuck, because they are overwhelmed by the degree of freedom that Vertx brings up. As a result, it leads to messy codebases and abandoned projects. That is sad, because Vertx is a great technology, which makes your systems run faster and in a more reliable way, than Spring. During last two years, when I established myself publicly as a Vertx freelancer, I had an experience with various projects in different industries. Therefore, if you plan to migrate an existing Spring monolith app to Vertx – don’t hesitate to contact me and I would help you with that.

admin Written by: