Vert.x 3 Web easy as Pi

Vert.x Web dis­tin­guishes it­self from tra­di­tional ap­pli­ca­tion servers like JavaEE by just being a sim­ple ex­ten­sion toolkit to Vert.x, which makes it quite light­weight and small but nev­er­the­less very pow­er­ful.

One can cre­ate sim­ple ap­pli­ca­tions tar­get­ing small de­vices such as Rasp­berry Pi with­out hav­ing to write much code but still very fast as it is ex­pected from any Vert.x ap­pli­ca­tion.

Let’s for ex­am­ple think of mak­ing a re­al­time cpu load vi­su­al­iza­tion web app. For this ex­am­ple we need a few things:

To boot­strap this project we start by cre­at­ing the pom.xml file. A good start is al­ways to con­sult the ex­am­ples, and you should end up with some­thing 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 mo­ment you can start cod­ing the ap­pli­ca­tion using the stan­dard maven source src/main/java and re­source src/main/resouces lo­ca­tions. And add a the class io.vertx.blog.RpiVer­ti­cle 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 sta­tic con­struc­tor we ini­tial­ize the MXBean that will allow us to col­lect the cur­rent System Load Average, then on the start method we cre­ate a Vert.x Web Router and de­fine that for all re­quests start­ing with /eventbus should be han­dled by the SockJS server, which we then bridge to the Vert.x EventBus and allow out­bound mes­sages ad­dressed to the load ad­dress.

Since our ap­pli­ca­tion is a web ap­pli­ca­tion we will also server some sta­tic con­tent with the StaticHandler and we fi­nally start a HTTP server lis­ten­ing on port 8080.

So now all we are miss­ing is a way to push real time data to the client so we end up cre­at­ing a Periodic task that re­peats every 1000 mil­lisec­onds and sends some JSON pay­load to the ad­dress "load".

If you run this ap­pli­ca­tion right now you won’t see much since there is no fron­tend 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 open­ing a EventBus bridge over SockJS and reg­is­ter a han­dler data to con­sume mes­sages sent to that ad­dress. Once such a mes­sage ar­rives we do some house keep­ing to avoid fill­ing our browser mem­ory and then add the in­com­ing mes­sage to the data queue and triger a ren­der­ing of the data. There is how­ever one in­ter­est­ing issue here, since the mes­sage pay­load is JSON there is no na­tive sup­port for Date ob­jects so we need to do some pars­ing from what ar­rives from the server. In this case the server sends a sim­ple time since epoch num­ber, but one can choose any for­mat he likes.

At this mo­ment you can build and pack­age your app like mvn clean package, then de­ploy it to your rasp­ber­rypi like: scp target/rpi-1.0-fat.jar pi@raspberrypi:~/ and fi­nally run it: java -jar rpi-1.0-fat.jar.

Open a browser to see the re­al­time graph!

Screenshot

Next post

Vert.x 3 init.d Script

Let's say you have a Vert.x 3 application you want to install on a Linux server. But you want the old school way (I mean not the Docker way).

Read more
Previous post

Vert.x 2.1.6 released!

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

Read more
Related posts

Some Rest with Vert.x

This post is part of the Introduction to Vert.x series. Let’s go a bit further this time and develop a CRUD-ish application

Read more

Unit and Integration Tests

Let’s refresh our mind about what we developed so far in the introduction to vert.x series. We forgot an important task. We didn’t test the API.

Read more

Real-time bidding with Websockets and Vert.x

The expectations of users for interactivity with web applications have changed over the past few years. Users during bidding in auction no longer want to press the refresh button.

Read more