Skip to main content

Vert.x3 Web easy as Pi

Vert.x Web distinguishes itself from traditional application servers like JavaEE by just being a simple extension toolkit to Vert.x, which makes it quite lightweight and small but nevertheless very powerful.

One can create simple applications targeting small devices such as Raspberry Pi without having to write much code but still very fast as it is expected from any Vert.x application.

Let’s for example think of making a realtime cpu load visualization web app. For this example we need a few things:

To bootstrap this project we start by creating the pom.xml file. A good start is always to consult the examples, and you should end up with something like:

...
<groupId>io.vertx.blog</groupId>
<artifactId>rpi</artifactId>
<version>1.0</version>

<dependencies>
  <dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-core</artifactId>
    <version>3.0.0</version>
  </dependency>

  <dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-web</artifactId>
    <version>3.0.0</version>
  </dependency>
</dependencies>
...

At this moment you can start coding the application using the standard maven source src/main/java and resource src/main/resouces locations. And add a the class io.vertx.blog.RpiVerticle to the project:

public class RPiVerticle extends AbstractVerticle {

  private static final OperatingSystemMXBean osMBean;

  static {
    try {
      osMBean = ManagementFactory.newPlatformMXBeanProxy(ManagementFactory.getPlatformMBeanServer(),
          ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, OperatingSystemMXBean.class);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public void start() {

    Router router = Router.router(vertx);

    router.route("/eventbus/*").handler(SockJSHandler.create(vertx)
        .bridge(new BridgeOptions().addOutboundPermitted(new PermittedOptions().setAddress("load"))));

    router.route().handler(StaticHandler.create());

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

    vertx.setPeriodic(1000, t -> vertx.eventBus().publish("load",
        new JsonObject()
            .put("creatTime", System.currentTimeMillis())
            .put("cpuTime", osMBean.getSystemLoadAverage())));
  }
}

So let’s go through the code, first in the static constructor we initialize the MXBean that will allow us to collect the current System Load Average, then on the start method we create a Vert.x Web Router and define that for all requests starting with /eventbus should be handled by the SockJS server, which we then bridge to the Vert.x EventBus and allow outbound messages addressed to the load address.

Since our application is a web application we will also server some static content with the StaticHandler and we finally start a HTTP server listening on port 8080.

So now all we are missing is a way to push real time data to the client so we end up creating a Periodic task that repeats every 1000 milliseconds and sends some JSON payload to the address "load".

If you run this application right now you won’t see much since there is no frontend yet, so let’s build a very basic index.html:

...
var eb = new vertx.EventBus(window.location + "eventbus");

eb.onopen = function () {
  eb.registerHandler("load", function (msg) {
    if (data.length === 25) {
      // when length of data equal 25 then pop data[0]
      data.shift();
    }
    data.push({
      "creatTime": new Date(msg.creatTime),
      "cpuTime": msg.cpuTime
    });
    render();
  });
};
...

Let’s walk again the code, we start by opening a EventBus bridge over SockJS and register a handler data to consume messages sent to that address. Once such a message arrives we do some house keeping to avoid filling our browser memory and then add the incoming message to the data queue and triger a rendering of the data. There is however one interesting issue here, since the message payload is JSON there is no native support for Date objects so we need to do some parsing from what arrives from the server. In this case the server sends a simple time since epoch number, but one can choose any format he likes.

At this moment you can build and package your app like mvn clean package, then deploy it to your raspberrypi like: scp target/rpi-1.0-fat.jar pi@raspberrypi:~/ and finally run it: java -jar rpi-1.0-fat.jar.

Open a browser to see the realtime graph!

Screenshot