Vert.x event bus communicating between Verticles

In my previous post on Vert.x, I demonstrated how to create multiple Verticle’s but also how a Verticle needn’t actually be a “service” but in some cases is just a worker process or in the case of the previous post a “main” or startup process.

This leads us to better see how Vert.x is actor-like with regards to Verticles.

In situations where we have multiple Verticles and possible some of those Verticles are simply workers for the other Verticles, we would need some way of communicating across those different parts of the application. Hence Vert.x also comes with an event bus for communicating across Verticles. This is a global event bus across all our Verticles.

Let’s, for sake of simplicity change our previous example so that whenever a service is successfully routed to, an event is sent out of the EventBus to say which services was called.

So, taken the example from my previous post, add the following to the MainVerticle start method

EventBus eventBus = vertx.eventBus();

eventBus.consumer("/svc", m -> {
   System.out.println(m.body());
});

The String /svc is the topic or an address if you prefer that we publish and consume message from. In the example above, we’re listening to the event bus for the anything sent (or published) to the address /svc. How you name you addresses is totally upto you.

Don’t forget to import io.vertx.core.eventbus.EventBus to use the event bus.

Next we’ll add code to the services to send a message on the /svc address when we wish to communicate something. Here’s the code for the HelloVerticle start method with the event bus added.

@Override
public void start() {

   EventBus evBus = vertx.eventBus();

   router.route("/hello").handler(ctx -> {
      evBus.send("/svc", "hello called");

      ctx.response()
         .putHeader("content-type", "text/plain")
         .end("Hello " + ctx.queryParam("name"));
      });

      vertx.createHttpServer()
         .requestHandler(router::accept)
         .listen(8080);

   System.out.println("HTTP server started on port 8080");
}

As you can see from the highlighted lines adding an event bus and sending messages out on it, is very simple. If we updated the WorldVerticle from the previous post also (but sending “world called”) then when run, the MainVerticle will print a line to the console every time the HelloVerticle or WorldVerticle routes are called.

Publish and Send

In the example (above) I used the event buss method send to send messages out on the event bus, but send will only be delivered to at most one of the handlers of the message.

Therefore is we added the following code to each of our service Verticles

evBus.consumer("/svc", m -> {
   System.out.println("Hello " + m.body());
});

After the declaration of the evBus variable.

we’ve now got a requirement that the message on address /svc needs to be handled by multiple consumers. Running up the application as it currently stands would result in only one of the consumers receiving the messages. In my case this was the MainVerticle, however there’s no guarantee which Verticle would receive the messages as this is determined by Vert.x in a round robin fashion.

So here’s the difference between send and publish. If you change the code from send to publish in the service Verticles. Then messages will be routed to all consumers.