How to create a Vertx EventBus js client and…
Recently I came across Vertx toolkit (http://vertx.io/docs/) when I was building an API. What I needed was to build a simple server to connect a javascript app and transfer message in between. So before going into more details lets discuss what Vertx toolkit has to offer and then create a Vertx Eventbus js client.
I learned that it’s not a framework where the way individual functionalities are defined but a toolkit which can be used to pick up different useful modules or functionalities to work in a project as you want. As the book defines (http://vertx.io//docs/guide-for-java-devs), the core concepts they mention are:
- What is a verticle
- How eventbus allows the verticles to communicate.
I think the book is a comprehensive guide and I’ll leave it for you guys to explore the corners of it. But the eventbus which I’m using here is a pub-sub mechanism with a js client and it will communicate with a server.
What my focus now is on how to create a js app client which can communicate with a service in a publish-subsribe manner. This was previously done using CometD client and CometD servlet and I thought of adhering asynchronous single-threaded server to run in a minimal environment.
Server Verticle
First, import the needed maven artefacts to compile the library. Add following dependencies to pom.xml. If you are starting new you can generate the vertx.io arch type as well.
<dependency> <groupId>io.vertx</groupId> <artifactId>vertx-core</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-web</artifactId> <version>${project.version}</version> </dependency>
To make this work we need a server created as a verticle using Vertx.
package com.sandny.vertx.example import io.vertx.core.AbstractVerticle; import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.eventbus.DeliveryOptions; import io.vertx.core.eventbus.EventBus; import io.vertx.core.eventbus.EventBusOptions; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.handler.StaticHandler; import io.vertx.ext.web.handler.sockjs.BridgeOptions; import io.vertx.ext.web.handler.sockjs.PermittedOptions; import io.vertx.ext.web.handler.sockjs.SockJSHandler; import java.io.IOException; import java.text.DateFormat; import java.time.Instant; import java.util.Date; public class ServerVerticle extends AbstractVerticle { public void start(Future<Void> fut) { // add cors allow to localhost:8181 address Router router = Router.router(vertx); router.route().handler(io.vertx.ext.web.handler.CorsHandler.create("http://localhost:8181") .allowedMethod(io.vertx.core.http.HttpMethod.GET) .allowedMethod(io.vertx.core.http.HttpMethod.POST) .allowedMethod(io.vertx.core.http.HttpMethod.PUT) .allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS) .allowCredentials(true) .allowedHeader("Access-Control-Allow-Method") .allowedHeader("Access-Control-Allow-Origin") .allowedHeader("Access-Control-Allow-Credentials") .allowedHeader("Content-Type")); // you will need to allow outbound and inbound to allow eventbus communication. BridgeOptions opts = new BridgeOptions() .addOutboundPermitted(new PermittedOptions().setAddress("feed")); SockJSHandler ebHandler = SockJSHandler.create(vertx).bridge(opts); router.route("/eventbus/*").handler(ebHandler); router.route().handler(StaticHandler.create()); // create the server with 8080 port to bind vertx.createHttpServer().requestHandler(router::accept).listen(8080); // create the eventbus EventBus eb = vertx.eventBus(); // publish messages in 1 sec. interval vertx.setPeriodic(1000l, t -> { String timestamp = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM).format(Date.from(Instant.now())); eb.send("feed", new JsonObject().put("now", timestamp)); }); } }
Here remember to add CORS definitions you want on the server side. Since the app is a browser app(I used google chrome) it will most probably block you from fulfilling the requests. Unless it will show No 'Access-Control-Allow-Origin' header is present on the requested resource
404 error.
You need to deploy and run this verticle from the main method. So need to create a main file and deploy the verticle.
public class Main { public static void main(String[] args) { VertxOptions options = new VertxOptions(); // add additional options you need Vertx vertx = Vertx.vertx(options); vertx.deployVerticle(ServerVerticle.class.getName()); } }
Create a Vertx EventBus js client
Install vertx3-eventbus-client
npm package to get the event bus javascript client. Don’t misunderstand this with the javascript eventbus which is mentioned in the documentation. You will see nothing like that in this package. That eventbus is to be deployed as verticles and it is not intended to use in a browser engine. It is used to run with a node.js instance. Use the following code in an es6 project to connect with the evenbus server you have created before.
import EventBus from 'vertx3-eventbus-client'; const eb = new EventBus("http://localhost:8080/eventbus"); eb.onopen = () => { eb.registerHandler('feed', function(error, message) { console.log('received a message: ' + JSON.stringify(message)); }); } eb.onclose = (param) => { console.log('closed', param) } export default eb;
That’s it. You will need to modify the onclose and concentrate more on reconnection if you want to make it more reliable. I’ll give an update on a next blog.