An Introduction to Eclipse Vert.x
Want to learn more about Eclipse Vert.x? Check out this post on the Eclipse Vert.x toolkit for developing reactive applications on JVM.
Join the DZone community and get the full member experience.
Join For FreeEclipse Vert.x is an event-driven, non-blocking toolkit for developing reactive applications on JVM. It was designed for asynchronous communications.
The most basic benefit of Vert.x is handling a lot of concurrencies using a small number of kernel threads by the event-driven and non-blocking approach. In this way, it lets your app scale with minimal hardware.
As known in the synchronous I/O threading model, a network communication is managed by allocating a thread to each client. This means that a thread assigned to a client deals with the client until it disconnects. However, you can write code as a single thread application with Vert.x, because it provides an event-based programming model.
Vert.x core library defines the basic APIs for writing asynchronous networked applications and also supports polyglot applications. This means that you can include multiple languages in your applications.
In addition, Vert.x contains several components. You can use any component with all the usual libraries if you want. Vert.x will not restrict you in this regard.
Vert.x Core
Vert.x core contains base functionality supporting such as HTTP, TCP, file system access, and various other features, and it’s used by many of the other components of Vert.x. Since the component is just a regular jar library, it can be embedded inside your applications.
To use Vert.x core in a Maven project, you will need to add the following dependency to pom.xml
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>3.5.2</version>
</dependency>
Or, for a Gradle project:
dependencies {
compile 'io.vertx:vertx-core:3.5.2'
}
Core Concepts
Vert.x has core concepts.
- Verticle
- Event Loop
- Event Bus
Verticle
A verticle is a unit of deployment in Vert.x and is executed within the Vert.x instance. Verticles allow you to encapsulate your code for different needs, and they are can be run independently of each other. Every Vert.x instance has N number of the event loop. By default, this number is core * 2.
There are three different types of verticles in Vert.x, these
- Standard Verticles
- Worker Verticles
- Multi-threaded Worker Verticles
Standard Verticles are executed using an event loop thread, and they are the most common and useful type. Worker Verticles run using a thread from the worker pool. It is never executed concurrently by more than one thread. Multi-threaded Worker Verticles run using a thread from the worker pool like Worker Verticles, but they can be executed concurrently by more than one thread differently.
You can have more than one verticle in your application (It will usually). These verticles communicate with each other by sending messages on the event bus.
In addition, Vert.x supports polyglot. Because of this, you can have verticles and can be written in any of the languages that Vert.x supports.
Event Loop
The event loop of Vert.x is similar in the existing asynchronous programming models. In this model, every event will be handled in a reasonable amount of time to not block the event loop. Vert.x has a golden role: don’t block the event loop.
The event loop should not be blocked, because, when this happens, the event loop will not be able to do anything else. This means that your application will grind to a complete halt when you block all of the event loops in Vert.x instance. At this point, Vert.x has a solution(executeBlocking method) for situations where blocking is inevitable, such as a long-lived database operation or complex calculation operations, etc.
Because every event loop is attached to a thread and every regular verticle always processes events on the same thread, there is no need to thread coordination mechanisms in Vert.x.
Event Bus
The event bus is the nervous system of Vert.x. We usually have more than one verticle for different needs, such as managing access to the database and handling HTTP requests, etc, in our applications. In this situation, vertical communication will travel through the asynchronous message passing provided over the event bus. Hence, there is a single event bus instance for every Vert.x instance
The event bus supports the following communication modes.
- point-to-point messaging
- request-response messaging
- publish/subscribe for broadcasting messages
The event bus API performs registering, unregistering handlers, and sending, publishing messages operations.
Let’s Code
A verticle class must implement the verticle interface but to implement it directly isn’t mandatory. Instead, you can extend the abstract class AbstractVerticle
.
public class HelloWorldVerticle extends AbstractVerticle {
@Override
public void start(Future<Void> future) {
vertx.createHttpServer()
.requestHandler(r -> r.response()
.end("Hello from Vert.x application")).listen(8080,
result -> {
if (result.succeeded()) {
future.complete();
} else {
future.fail(result.cause());
}
});
}
}
The HelloWorldVerticle
class extends to the AbstractVerticle
. In this way, the class gets access to the protected vert.x field, and the Vert.x instance on which the verticle is deployed.
The start method will call the Vert.x when the verticle is deployed, and when the method has successfully completed, the verticle will be considered started.
The method receives a Future
object that represents the result of an action that may, or may not, have occurred yet. It lets us notify the Vert.x when the steps in the start method have been completed or report an error.
Inside the method, we created an HTTP server that is bound to the 8080 port and assigned a request handler to it. The request handler is called every time the server receives a request. If everything is good to go, you can see the “Hello from Vert.x application” sentence when the visit to http://localhost:8080 is shown after running the code. But, when anything bad happens, Vert.x calls future.fail
to report an error.
Deploy Verticle
A vertical can be deployed using the deployVerticle
method.
public static void main(String[] args){
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new HelloWorldVerticle(), res -> {
if (res.succeeded()) {
log.info("Deployment id is: " + res.result());
} else {
log.info("Deployment failed!");
}
});
}
At this point, I want to go back to the start method in HelloWorldVerticle
and underline a point.
@Override
public void start(Future<Void> future) {
vertx.createHttpServer()
.requestHandler(r -> r.response()
.end("Hello from Vert.x application")).listen(8080,
result -> {
if (result.succeeded()) {
future.complete();
} else {
future.fail(result.cause());
}
});
}
The future parameter is important in terms of notification of the completion process. Vert.x is asynchronous and non-blocking. This means that when the HelloWorld verticle deployed, it won’t wait until the start method has been completed. If comment line, the future.complete(),
is in the above code, the following output does not occur.
[vert.x-eventloop-thread-1] INFO Starter — Deployment id is: 704a31b4–9de9–41b7–9411–8d5c07a60465
Keep in mind, Vert.x also has a start method version without the Future parameter. When using this method, Vert.x considers the verticle deployed when the start method returns.
Conclusion
Vert.x offers an elegant way to avoid bottlenecks in many concurrent connections used by a solid foundation for the asynchronous paradigm. In this way, ıt lets your app scale with minimal hardware. In addition, it is lightweight and flexible. The code developed in this article is available on this repository.
References
Opinions expressed by DZone contributors are their own.
Comments