Tech and Media Labs
This site uses cookies to improve the user experience.




Vert.x Verticles

Jakob Jenkov
Last update: 2015-04-20

The term verticle is the name of the components you can deploy to Vert.x. A verticle is in some ways similar to a Servlet or a message driven EJB in Java EE. However, verticles work differently, and the concurrency model under which verticles and Servlets and EJBs execute is different. This text will take a closer look at how to create and deploy verticles in Vert.x, and how verticles can communicate with each other over the internal event bus.

Implementing a Verticle

You implement a verticle by creating a class that extends io.vertx.core.AbstractVerticle. Here is an example verticle class:

import io.vertx.core.AbstractVerticle;

public class BasicVerticle extends AbstractVerticle {

}

The class BasicVerticle extends AbstractVerticle but it doesn't have any functionality. We will add that in the following sections.

start()

The AbstractVerticle class contains a start() method which you can override in your verticle class. The start() method is called by Vert.x when the verticle is deployed and ready to start. Here is how implementing the start() method looks:

public class BasicVerticle extends AbstractVerticle {

    @Override
    public void start() throws Exception {
        System.out.println("BasicVerticle started");
    }
}

The start() method is where you initialize your verticle. Inside the start() method you will normally create e.g. HTTP or TCP server, register event handlers on the event bus, deploy other verticles, or whatever else your verticle needs to do its work.

The AbstracVerticle class also contains another version of start() which takes a Future as parameter. This Future can be used to asynchronously tell Vert.x if the Verticle was deployed successfully.

You will see later in this tutorial how to use both versions of the start() method.

stop()

The AbstractVerticle class also contains a stop() method you can override. The stop() method is called when Vert.x shuts down and your verticle needs to stop. Here is an example of overriding the stop() method in your own verticle:

public class BasicVerticle extends AbstractVerticle {

    @Override
    public void start() throws Exception {
        System.out.println("BasicVerticle started");
    }

    @Override
    public void stop() throws Exception {
        System.out.println("BasicVerticle stopped");
    }
}

Deploying a Verticle

Once you have created a Verticle you need to deploy it inside Vert.x in order to execute it. Here is how you deploy a verticle:

public class VertxVerticleMain {

    public static void main(String[] args) throws InterruptedException {
        Vertx vertx = Vertx.vertx();

        vertx.deployVerticle(new BasicVerticle());
    }
}

First a Vertx instance is created. Second, the deployVerticle() method is called on the Vertx instance, with an instance of your verticle (BasicVerticle in this example) as parameter.

Vert.x will now deploy the verticle internally. Once Vert.x deploys the verticle, the verticle's start() method is called.

The verticle will be deployed asynchronously, so the verticle may not be deployed by the time the deployVerticle() method returns. If you need to know exactly when a verticle is fully deployed, you can provide a Handler implementation to the the deployVerticle(). Here is how that looks:

vertx.deployVerticle(new BasicVerticle(), new Handler<AsyncResult<String>>() {
    @Override
    public void handle(AsyncResult<String> stringAsyncResult) {
        System.out.println("BasicVerticle deployment complete");
        }
    });

Or using a Java lambda expression :

vertx.deployVerticle(new BasicVerticle(), stringAsyncResult -> {
        System.out.println("BasicVerticle deployment complete");
});

Deploying a Verticle From Another Verticle

It is possible to deploy one verticle from inside another verticle. Here is an example:

public class BasicVerticle extends AbstractVerticle {

    @Override
    public void start() throws Exception {
        System.out.println("BasicVerticle started");

        vertx.deployVerticle(new SecondVerticle());
    }

    @Override
    public void stop() throws Exception {
        System.out.println("BasicVerticle stopped");
    }
}

Using The Event Bus

It is very common for verticles to either listen for incoming messages from the event bus, or to write messages to other verticles via the event bus. Therefore I will show you how to do both in the following sections.

Listening for Messages

When a verticle wants to listen for messages from the event bus, it listens on a certain address. An address is just a name (a String) which you can choose freely.

Multiple verticles can listen for messages on the same address. This means that an address is not unique to a single verticle. An address is thus more like the name of a channel you can communicate via. Multiple verticles can listen for messages on an address, and multiple verticles can send messages to an address.

A verticle can obtain a reference to the event bus via the vertx instance inherited from AbstractVerticle

Here is how listening for messages on a given address looks:

public class EventBusReceiverVerticle extends AbstractVerticle {

    public void start(Future<Void> startFuture) {

        vertx.eventBus().consumer("anAddress", message -> {
            System.out.println("1 received message.body() = "
                + message.body());
        });
    }
}

This example shows a verticle that registers a consumer (listener) of messages on the Vert.x event bus. The consumer is registered with the address anAddress, meaning it consumes messages sent to this address via the event bus.

The consumer is a handler object which contains a single method. That is why it is implemented above using a lambda expression.

Sending Messages

Sending messages via the event bus can be done via either the send() or publish() method on the event bus.

The publish method sends the message to all verticles listening on a given address.

The send() method sends the message to just one of the listening verticles. Which verticle receives the message is decided by Vert.x. At the time of writing the Vert.x docs says that a verticle is chosen using a "non-strict round robin" algorithm. This basically means that Vert.x will try to distribute the messages evenly among the listening verticles. This is useful for distributing work load over multiple verticles (e.g. threads or CPUs).

Here is an example that deploys two event bus consumers (listeners), and one event bus sender. The sender sends two messages to a given address. The first message is sent via the publish() method, so both consumers receive the message. The second message is sent via the send() method, so only one of the consumers will receive the message.

Vertx vertx = Vertx.vertx();

vertx.deployVerticle(new EventBusReceiverVerticle("R1"));
vertx.deployVerticle(new EventBusReceiverVerticle("R2"));

Thread.sleep(3000);
vertx.deployVerticle(new EventBusSenderVerticle());
public class EventBusSenderVerticle extends AbstractVerticle {

    public void start(Future<Void> startFuture) {
        vertx.eventBus().publish("anAddress", "message 2");
        vertx.eventBus().send   ("anAddress", "message 1");
    }
}
public class EventBusReceiverVerticle extends AbstractVerticle {

    private String name = null;

    public EventBusReceiverVerticle(String name) {
        this.name = name;
    }

    public void start(Future<Void> startFuture) {
        vertx.eventBus().consumer("anAddress", message -> {
            System.out.println(this.name + 
                " received message: " +
                message.body());
        });
    }
}

If you run this code you will see that the first message is received by both consumers (R1 + R2) whereas the second message is only received by one of the consumers.

Jakob Jenkov




Copyright  Jenkov Aps
Close TOC