Skip to main content

Vert.x 3.5.0 released !

The Vert.x team is pleased to announce the release of Vert.x 3.5.0.

As usual it delivers an impressive number of high quality features.

Let’s go RxJava2

First and foremost this release delivers the RxJava2 API with support of its full range of types.

In addition of Single, Rxified APIs also expose theCompletable and Maybe types:

// expose Handler<AsyncResult<Void>>
Completable completable = server.rxClose();

completable.subscribe(() -> System.out.println("closed"));

// expose Handler<AsyncResult<String>> where the result can be null
Maybe<String> ipAddress = dnsClient.rxLookup("www.google.com");
ipAddress.subscribe(
  value -> System.out.println("resolved to " + value),
  err -> err.printStackTrace(),
  () -> System.out.println("does not resolve"));

RxJava augments Vert.x streams with a toObservable() method, likewise RxJava2 adds the toFlowable() method:

// Flowable<Buffer> maps to a ReadStream<Buffer>
// back-pressured stream
Flowable<Buffer> flowable = asyncFile.toFlowable();

// but we still can get an Observable<Buffer>
// non back-pressured stream
Observable<Buffer> flowable = asyncFile.toObservable();

What’s so different between Flowable and Observable? the former handles back-pressure, i.e the subscriber can control the flow of items and the later can not!!!

You can read the documentation in the section of the docs or go straight to the examples

Kotlin coroutines

Support for Kotlin Coroutines is one of my favourite 3.5 features (by the way I’ll present a talk about Vert.x and coroutines at KotlinConf).

Coroutines allows you to reason about asynchronous flow the same way you do with traditional sequential flow with the extra bonus to use try/catch/finally super combo:

val movie = ctx.pathParam("id")
val rating = Integer.parseInt(ctx.queryParam("getRating")[0])
val connection = awaitResult<SQLConnection> { client.getConnection(it) }
try {
  val result = awaitResult<ResultSet> { connection.queryWithParams("SELECT TITLE FROM MOVIE WHERE ID=?", json { array(movie) }, it) }
  if (result.rows.size == 1) {
    awaitResult<UpdateResult> { connection.updateWithParams("INSERT INTO RATING (VALUE, MOVIE_ID) VALUES ?, ?", json { array(rating, movie) }, it) }
    ctx.response().setStatusCode(200).end()
  } else {
    ctx.response().setStatusCode(404).end()
  }
} finally {
  connection.close()
}

This example is borrowed from our examples.

NOTE: I’ve used try/finally purposely instead of Kotlin’s use extension method

MQTT Client

In Vert.x 3.4 we added the MQTT server, 3.5 completes the MQTT story with the MQTT client:

MqttClient mqttClient = MqttClient.create(vertx,
   new MqttClientOptions()
     .setPort(BROKER_PORT)
     .setHost(BROKER_HOST)).connect(ar ->
  if (ar.succeeded()) {
    System.out.println("Connected to a server");

    mqttClient.publish(
      MQTT_TOPIC,
      Buffer.buffer(MQTT_MESSAGE),
      MqttQoS.AT_MOST_ONCE,
      false,
      false,
      s -> mqttClient.disconnect(d -> System.out.println("Disconnected from server")));
  } else {
    System.out.println("Failed to connect to a server");
    ar.cause().printStackTrace();
  }
});

You can find MQTT client and server examples here

Web API contracts

With the new OpenAPI router factory we can focus on the API implementation and not on the validation of the input. The usage is quite simple:

OpenAPI3RouterFactory.createRouterFactoryFromFile(vertx, "petstore.yaml", ar -> {
  if (ar.succeeded()) {
    // Spec loaded with success
    OpenAPI3RouterFactory routerFactory = ar.result();

    // add your API and security handlers to the factory

    // add it to a server
    vertx.createHttpServer()
      .requestHandler(routerFactory.getRouter()::accept)
      .listen();
  } else {
    // Something went wrong during router factory initialization
  }
});

Now as a developer you only need to care about the API and not on the validation. The OpenAPI router will ensure that a request to an API will first to the contract before your handler is invoked.

Java 9 support

Java 9 was released a few days ago and the Vert.x stack has been carefully tested on Java 9 and most of our components run on Java 9 (Groovy does not run well on Java 9, please see the support matrix)

As a bonus you can now use HTTP/2 out of the box with JDK SSL!

You can also use Vert.x jars as anonymous modules.

Event driven JSON Parsing

We provide now an event driven JSON Parser emitting parse events that is very handy when you need to handle very large JSON structures and you don’t want to buffer it which introduce extra latency and increase the memory consumption.

The parser allows you to switch between fine grained JSON parse events or full structures, for instance you can parse an array of object very efficiently:

JsonParser parser = JsonParser.newParser();

// The parser will handle JSON objects as values
parser.objectValueMode();

parser.handler(event -> {
  switch (event.type()) {
    case START_ARRAY:
      // Start the array
      break;
    case END_ARRAY:
      // End the array
      break;
    case VALUE:
      // Handle each object
      break;
  }
});

Single SQL operations

Single SQL operations (aka one-shot) have been drastically simplified: most of the SQLOperations operations can now be performed directly on the SQLClient:

client.queryWithParams("SELECT AVG(VALUE) AS VALUE FROM RATING WHERE MOVIE_ID=?", new JsonArray().add(id), ar2 -> {
  if (ar.succeeded()) {
    int value = ar.result().get(0).getInteger("VALUE");
    // Continue
  }
});

Under the hood, the client takes care of the pool acquire/release interaction for you.

Native transport and domain sockets

We now support native transports on Linux (Epoll) and MacOS (KQueue), as well as UNIX domain sockets for NetServer/NetClient (HttpServer/HttpClient should support UNIX domain sockets soon).

Auth handler chaining

There are times when you want to support multiple authN/authZ mechanisms in a single application.

Vert.x Web supports auth handlers chaining

Vert.x config improvements

Vert.x Config allows configuring your application by assembling config chunks from different locations such as file, http, zookeeper…

In this version, we have added the support for Consul and Vault.

With the Consul config store, you can retrieve your configuration from a Consul server - so in other words, distribute the configuration from your orchestration infrastructure.

The Vault config store lets you retrieve secrets avoiding hard coding secrets or distributing credentials using an insecure way. Vault enforces the security of your secrets and only allowed applications can retrieve them. In other words, now you can keep your secrets secret.

ACKs

I want on behalf of the team to thank all the contributors for this release including the Google Summer of Code students (Pavel Drankov, Francesco Guardiani and Yunyu Lin) that delivered an impressive work.

Finally

The release notes

Docker images are also available on the Docker Hub. The Vert.x distribution is also available from SDKMan and HomeBrew.

The event bus client using the SockJS bridge are available from NPM, Bower and as a WebJar:

The artifacts have been deployed to Maven Central and you can get the distribution on Bintray.