Microservice Development using Vert.X

Lalitha
3 min readAug 29, 2019

The rise in Microservice architecture across the industry has given rise to requiring to do lot of async processing. Non-blocking event processing provides solution to lot of async processing requirements.

Vertx framework comes handy in developing reactive applications on JVM with simple async communication. Vert.x supports multiple languages - Java, JavaScript, Groovy, Ruby, Ceylon and Kotlin. Verticles are the basic blocks of Vert.x application.

Verticles are basic components of functional processing. Each of the verticles are components that act on technical unit independently. Verticle and its environment is as illustrated in below diagram, consists of vertx instance and the context which can be spanned across multiple event threads. This means, single verticle can perform multiple processing based on the event handler. Verticle lifecycle involves simple start/stop stages.

A verticle object is essentially the combination of 2 objects:
1. a vertx instance
2. a context for processing events

Verticle and its environment

Implementing a Verticle

Its easier to work with vertx if you are using Maven or Gradle by just including dependencies. Gradle dependency example:

dependencies {
compile "io.vertx:vertx-core:3.5.1"
compile "io.vertx:vertx-web:3.5.1"
}

Creating simple vertx application. The main method creates a verticle and deploys using the deployment options specified.

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

DeploymentOptions options = new DeploymentOptions()
.setConfig(new JsonObject()
.put("http.port", 8081)
.put("http.host", "localhost")
);

vertx.deployVerticle(StatesRestAPI.class.getName(), options);

}

When deploying a verticle using a verticle name, you can specify the number of verticle instances that you want to deploy. This is useful while you want to scale the verticles across multiple cores on your machine, to ensure distribution across the cores. Default deployment instances are set to 2, if no value is specified.

DeploymentOptions options = new DeploymentOptions().setInstances(4);

Working with vertx configurations

By default, the Config Retriever is configured with the following stores:

  • The Vert.x verticle config()
  • The system properties
  • The environment variables
  • A conf/config.json file. This path can be overridden using the vertx-config-path system property or VERTX_CONFIG_PATH environment variable.

RESTful API using Verticle

Creating RESTful services in vertx is as simple as defining the routes. Router lets you expose the endpoints for clients to consume. Here’s an example router implementation:

public class StatesRestAPI extends AbstractVerticle {

@Override
public void start(Future<Void> startFuture) {
//create a router
Router router = Router.router(vertx);
//defining the endpoints
router.route().handler(BodyHandler.create());
router.post(STATES_API_ENDPOINT).handler(this::addState);
router.get(STATES_API_ENDPOINT).handler(this::listStates);
router.get(STATES_API_ENDPOINT + "/:id").handler(this::getStateById);
//create http server
vertx.createHttpServer()
.requestHandler(router::accept)
.listen(config().getInteger("http.port", 8080), ar -> {
if (ar.failed()) {
startFuture.cause().printStackTrace();
}
});
}
}

Create verticle by overriding start method of AbstractVerticle. There are 2 ways of creating verticle, one using start method with no Future parameter and the second one using Future parameter. The latter option creates asynchronous verticle with handler listing on the server create response. Here’s the differentiation of 2 options:

Verticle with no Future parameter in start method while creating HTTP server
Verticle with Future parameter in start method while creating HTTP server

Adding healthcheck to endpoint to service:

//basic ping
router.get("/").handler(rc -> {
rc.response()
.putHeader("content-type", "text/html")
.end("Here's StatesListing API");
});
//ping with API details
router.get(API_ENDPOINT).handler(rc -> {
rc.response().putHeader("content-type", "application/json")
.end(new JsonObject().put("name", "statelist").put("version", 1).encode());
});

Conclusion

Vertx provides reactive and async implementation solution to modern day development. Unlike nodejs, where a single thread process the events, verticles can process events across multiple non-blocking threads providing maximum throughput.

References: vertx.io, vertx-in-action (MEAP) book, github ref

--

--