An introduction to asynchronous and reactive programming with Eclipse Vert.x

Building asynchronous and reactive applications with Eclipse Vertx

Content

Forewords

1. What is Eclipse Vert.x

2. Demonstrating the core concepts

3. Going reactive: integration with RxJava

4. Concurrent execution of authorization queries

5. Bridging the gap between callbacks and RxJava

6. Rxified reactive wiki.

7. Going further

Forewords

I took part in the last 24 hours sprint and this time I found myself greatly interested in Eclipse Vert.x, especially as to what was under the hood, what makes it great and different and if it could possibly find within the communities an audience comparable to the giants of the java ecosystem such as Java EE or Spring.

1. What is Eclipse Vert.x?

Eclipse Vert.x is a tool-kit for building reactive applications on the JVM.
Vert.x is not a framework but a tool-kit. That means frameworks that meet more specific needs can be built on top of it. Vert.x core libraries define the fundamental APIs to write asynchronous networked applications.

Vert.x offers lots of useful software development bricks and lets you decide how you wish to combine them in building your next awesome software.

Vert.x is based on the Netty project.

1.1 What Build environnement or IDE to use?

You can use your favorite IDE or dev environnement: Vert.x core is a simple jar, it can be embedded inside apps packaged as a set of jars or it can be deployed inside popular components and application containers.

1.2 Why use Vert.x?

In what ways does Vert.x makes the difference with whatever else is out there?

Vert.x is designed for asynchronous communication. It can deal with more concurrent network communications with less threads than synchronous APIs such as java servlet or java.net socket classes.

Vert.x is useful for a wide range of applications such as:

  • High volume message/event processing
  • Micro services
  • API Gateways
  • Http APIs for mobile applications

Vert.x is however not limited to the heavy/complex or high demanding type of applications, more traditional applications can also benefit from it.

A seasoned developer might be apprehensive as to how complex an asynchronous toolkit can be. He might be worried about the learning curve for example. But it turns out Vert.x is really not so complex as it seems to sound, there are actually two cardinal concepts to understand and everything else will smoothly get in, these concepts are: the verticle and the event bus.

When we build a software with asynchronicity in mind, a sudden peak of traffic would not be a surprising unbearable thing as our software is already written with the essential ingredient for scaling up.

1.3 What programming language does it understand?

Vert.x is polyglot. It comes with support for Java, Groovy, Scala, Kotlin, Javascript, Ruby and Celon.
Vert.x adds something very cool: the specific APIs are idiomatic, for example when using scala we can use the Scala Future in place of Vert.x Future.

1.4 Core concepts
1.4.1 traditional threading and programming models

The traditional approach to threads does not do very well with scalability.
The reason is that it goes by assigning one thread per network client (generaly while establishing the connection). This is the case for exemple with the servlets model or network coding written with java.io and java networking APIs.

This model is a kind of synchronous IO threading model. It looks simple though as a programming model however it does not scale very well: threads are not cheap and when too many concurrent connections are launched that old approach does not scale well. It was though an improvement compared to the paleothical age of CGI and other prehistoric technologies.

Another point is that, under heavy load, thread management and scheduling becomes itself heavy on the Operating System.

Thus we need asynchronous IO and Vert.x is here at the right time for it.

1.4.2 Verticle: the unit of deployment in Eclipse Vert.x

The unit of deployment for Eclipse Vert.x is called a verticle. A verticle processes incoming events over an event loop.

Events can be anything such as:

  • Receiving network buffers
  • timing Events
  • messages sent by other Verticles
1.4.3 The politicaly correct event handling with Verticles
  • Each event shall be processed in a reasonnable amount of time to not block the event loop

  • Therefore no thread blocking operation shall be performed while executed on an event loop

  • Exactly like processing events in a game event loop or in a graphical user interface (imagine for example freezing a swing interface by executing a slow network operation)

  • Vert.x provides also mechanisms to deal with blocking operations outside of the event loop

1.4.4 Main characteristics of verticles

Every event loop is attached to a thread

  • By default Vert.x attaches two event loop per Core cpu thread
    • As a consequence a regular verticle always process events on the same thread
    • So there is no need for a thread cop
    • A verticle can be passed some configurations: credentials, network adresse, etc
    • A verticle can be deployed several times

Verticle-config-and-deployment-1

• Incoming network datas are being received from accepting threads and then passed as events to the corresponding verticles

• When a verticle opens a network server and is deployed more than once, then the events are being distributed to the verticle instances in a round- robin fashion which is very useful for maximizing CPU usage with lots of concurrent networked requests

• Verticles have a simple start/stop lifecycle

• Verticles can deploy other verticles

1.4.5 Message exchange through the event bus

Event-Bus-Communication

1.4.6 characteristics of the event bus

• All kinds of datas can transition between verticles through the event Bus
• Json is the preferred format because it is cross language.
• Messages can be sent to destinations which are free form strings
• The event bus supports the following communication patterns:

  - Point to point messaging
  - Request-response messaging
  - Publish/Subscribe for broadcasting messages

• Via the Event Bus, verticles can transparently communicate accros the same JVM or accross different JVMs
• when network clustering is activated, the event bus is distributed so that messages can be sent to verticles running on other application nodes,
• Third party apps can communicate with each others via the Event Bus using a simple TCP protocol
• The event bus can also be exposed over general purposes message bridge (example: AMQP, Stomp...)
• a SockJS bridge allows web applications to seamlessly communicate over the event bus from JavaScript running in the browser by receiving and publishing messages just like any verticle would do.

2 Demonstrating the core concepts

In this section we are demonstrating the concepts mentionned above through a simple and quick prototyping of a wiki app using Vert.x. The code and the samples can be found in the feature/wikipeaks-core branch of the github repository. The wiki is basically operationnal and has the following features:

• Server-side rendering of Html pages

• Data access through a JDBC connection

• Using the following librairies

• Vert.x web : provides elegant API to deal with routing, handling of request payloads, etc....

• Vert.x JDBC Client: provides an asynchronous API over JDBC

• Apache Free Marker: templating engine

• TxtMark: render markdown text as html allowing edition of wiki pages with markdown

• Bootstrapped maven project using: https://github.com/vert-x3/vertx-maven-starter

• Creating a fat jar with the help of Maven Shade Plugin

2.1 Our initial verticle

We start with a single verticle called MainVerticle as a java class that extends the io.vertx.core.AbstractVerticle. This base class provides:

  • Two life-cycle methods: start and stop to be overriden by descendant classes
  • The vertx protected field: it references the Vert.x environnement where the verticle is being deployed,
  • An accessor to some configuration object through which external configuration can be passed to a verticle
@Override
public void start(Future<Void> startFuture) throws Exception {
  Future<Void> steps = prepareDatabase().compose(v -> startHttpServer());
  steps.setHandler(startFuture.completer());
}

public void otherPossibleStart(Future<Void> startFuture) throws Exception {
  Future<Void> steps = prepareDatabase().compose(v -> startHttpServer());
  steps.setHandler(ar -> {
    if (ar.succeeded()) {
      startFuture.complete();
    } else {
      startFuture.fail(ar.cause());
    }
  });
}

2.2 What happened in the start method.

• When the future of prepareDatabase completes successfully, then startHttpServer is called and the steps future completes depending on the outcome of the future returned by startHttpServer

• startHttpServer is never called if prepareDatabase encounters an error, in which case the steps future is in a failed state and becomes completed with the exceptions describing the error

• Eventually steps completes: setHandler defines a handler to be called upon completion. In our case we simply want to complete startFuture with steps and use the completer method to obtain a handler: the two start methods shown above are equivalent

2.3 Running the demo.
  • Build the module, for example with mvn clean install
  • launch the module with mvn java -jar target/{module-artifact-id-here}-fat.jar
    If everthing goes fine the terminal will display a start log indicating the running port also
  • Launch your favorite browser and go to http://localhost:{the-port}

From there it is just as easy to create a page as it is on any cool wiki.

basic_wikipeaks_page

3. Going reactive: integration with RxJava

Vert.x integrates seamlessly with RxJava via the vertx-rx-java2 dependency. When using maven the dependency can be included the following way:

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-rx-java2</artifactId>
</dependency>

Again the idiomatic abilities of Vert.x quicks in here, because in order to create a Verticle we do not extend the io.vertx.core.AbstractVerticle anymore but:
io.vertx.reactivex.core.Vertx.

We could also go reactive without the integration of RxJava: the callback based API of Vert.xstack works well but it can become a bit tedious when the data flows become very complex and we are dealing with a lot of source of events. That's where RxJava shines and its integration proves efficient.

3.1 Changes in the deployment approach

• The rxDeploy method does not take a Handler<AsyncResult<String>>
• As a final Parameter, instead it returns a Single<String>
• Besides, the operation does not start when the method is called.
• It starts when you subscribe to the Single. When the operation completes,
• it emits the deployment id or signals the cause of the problem with a Throwable.

4. Concurrent execution of authorization queries

• In the previous example, we saw how to use RxJava operators and the Rxified Vert.x API to execute asynchronous operations in order.
• But sometimes this guarantee is not required, or you simply want them to run concurrently for performance reasons.
• The JWT token generation process in the HttpServerVerticle is a good example of such a situation.
• To create a token, we need all authorization queries to complete, but queries are independent from each other:

5. Bridging the gap between callbacks and RxJava

There might be cases where you may need to integrate RxJava with the callback API. In the case of the service proxy interface, it can only be defined with the callback api, but its implementation uses the Rxfied Vertx API.

In this case the io.vertx.reactivex.SingleHelper.toObserverclass can adapt a Handler<AsyncResult<T>> to an RxJava SingleObserver<T>

6. Rxified reactive wiki.

After integrating RxJava along with the neat features in Vert.x toolkit, we are able to build a reactive wiki.
This time when we edit any page, all instances of the wiki that are editing the same page are automatically notified of the changes.

reactive-wiki-sample-page

7. Going further

The code modules and samples can be found here

For a deep diving into the Reactive architectures you may read the Reaktive Architekturen mit RxJava serie by Michael Menzel.

Exploring Eclipse Vert.x has been a very enriching experience. It would be worthwhile to compare its possibilities with those of equivalent libraries. Spring Webflux is a non blocking web framework also built with asynchronicity in mind. While webflux is specific to web applications, Vert.x is more generic and can target a more versatile set of application types. It would be a very exciting experience to build D.S.F (Domain Specific Frameworks) on top of Eclipse Vert.x