Skip to main content

Writing a Verticle

In this tutorial, you'll write a simple Verticle for the Telestion ecosystem.

Prerequisites

To complete this tutorial, you should be familiar with standard Java programming structures. You also need to have a Telestion Project repository set up on your machine.

What you'll build

In this tutorial, you'll build a basic Verticle that listens for a message containing a number on a specific channel and republishes the number times two on another channel.

In real applications, this could, for example, transform incoming Telemetry data into a suitable format for the database.

The full code for this tutorial looks like this:

MessageTransformer.java
package de.wuespace.telestion.project.example;

import de.wuespace.telestion.api.verticle.NoConfiguration;
import de.wuespace.telestion.api.verticle.TelestionVerticle;

public class MessageTransformer extends TelestionVerticle<NoConfiguration> {
@Override
public void onStart() {
var eb = vertx.eventBus();

eb.consumer("input", event -> {
var received = (int) event.body(); // cast body to integer
eb.publish("output", received * 2); // republish
});
}
}

Steps

Step 1: Create a new Verticle

A Verticle is nothing else than a Java class that extends the de.wuespace.telestion.api.verticle.TelestionVerticle class.

To create a new Verticle, the first thing you need to do is to create a new class. This tutorial assumes that you're working in the de.wuespace.telestion.project.example package.

Within that package, create a new class called MessageTransformer and paste the following code:

MessageTransformer.java
package de.wuespace.telestion.project.example;

import de.wuespace.telestion.api.verticle.NoConfiguration;
import de.wuespace.telestion.api.verticle.TelestionVerticle;

public class MessageTransformer extends TelestionVerticle<NoConfiguration> {
@Override
public void onStart() {
// your code goes here
}
}

Step 2: Listen to messages

Basically, every Verticle's main feature is to listen for messages on the so-called event bus, process them, and potentially publish new information to the event bus.

Messages on the event bus are "grouped" on so-called channels. Addresses (Strings) define a channel:

Link to Diagram that shows two Verticles publishing to a bus with an address 'xy' and one Verticle receiving messages from that busDiagram that shows two Verticles publishing to a bus with an address 'xy' and 
one Verticle receiving messages from that bus

For now, keep it simple and listen to the "input" channel:

MessageTransformer.java
package de.wuespace.telestion.project.example;

import de.wuespace.telestion.api.verticle.NoConfiguration;
import de.wuespace.telestion.api.verticle.TelestionVerticle;

public class MessageTransformer extends TelestionVerticle<NoConfiguration> {
@Override
public void onStart() {
var eb = vertx.eventBus();

eb.consumer("input", event -> {
var received = (int) event.body(); // cast body to integer
// further process the received value
});
}
}

This first gets an instance to the Event Bus APIs using vertx.eventBus().

Then, using eb.consumer(address, handler), this registers a handler that reacts to messages on the channel with the address address.

The first argument to that handler(message) callback is the message which contains all information about the message, including the body, optional headers, and more.

You can get the message's body by calling its body() method. Since this returns an Object (containing whatever you published to that channel), you need to cast it to an integer.

Body data type

In this simple example, you'll just send simple integers over the event bus.

This isn't ideal for several reasons, including missing type safety (your Verticle could fail if you sent something to "input" that Java can't cast to int).

In the later sections, you'll learn how to use JSON structures (including the JsonMessage from the telestion-core libraries) to properly handle type safety on the event bus.

You should use JSON based messages in real Telestion projects.

Step 3: Republish Messages

Verticles that listen to channels without ever publishing anything themselves can be useful, too. For example, you could write a Verticle that logs all incoming messages to a file or saves them to the database. But in this tutorial, you want to transform the data and "republish" it to the event bus (this time, on a different channel called "output").

Thankfully, the Event Bus APIs make this quite easy using the publish(address, body) method:

MessageTransformer.java
package de.wuespace.telestion.project.example;

import de.wuespace.telestion.api.verticle.NoConfiguration;
import de.wuespace.telestion.api.verticle.TelestionVerticle;

public class MessageTransformer extends TelestionVerticle<NoConfiguration> {
@Override
public void onStart() {
var eb = vertx.eventBus();

eb.consumer("input", event -> {
var received = (int) event.body(); // cast body to integer
eb.publish("output", received * 2); // republish
});
}
}

With that, whenever this receives a value received on "input", it publishes received * 2 to "output".

Step 4: Test the Verticle

To test Verticles, you can add a public static void main(String[] args) method to the Verticle class that tests the Verticle.

Given the fact that a Verticle, if it's well written, doesn't depend on any other Verticles, all you need to do to test the Verticle is to spawn it, send some messages to a channel it listens to and watch the reaction / messages on its output channels.

Put the theory into practice and write your static main() method:

MessageTransformer.java
package de.wuespace.telestion.project.example;

import de.wuespace.telestion.api.verticle.NoConfiguration;
import de.wuespace.telestion.api.verticle.TelestionVerticle;
import io.vertx.core.Vertx;

public class MessageTransformer extends TelestionVerticle<NoConfiguration> {

public static void main(String[] args) throws InterruptedException {
var vertx = Vertx.vertx(); // create a new Vertx instance to test on
// "hear" on the output channel and print out anything
vertx.eventBus().consumer(
"output",
message -> System.out.printf("Output: %s%n", message.body().toString())
);
// deploy our Verticle on the vertx instance
vertx.deployVerticle(new MessageTransformer()).onSuccess(res -> {
// publish a number once the Verticle is deployed
vertx.eventBus().publish("input", 3);
});
}

// [...]
}

First, you create a Vertx instance called vertx using Vertx.vertx().

Then, you add a listener on the "output" address that just prints "Output: [body]" to the console for every message. You can get an EventBus instance using vertx.eventBus() and just use the same APIs you used inside the Verticle's onStart() method to interact with the event bus.

Next, you deploy your MessageTransformer Verticle by creating an instance and hand it over to Vertx. This, in turn, calls its onStart() method to deploy the Verticle.

The deployment process returns a future object. When it resolves, you publish a random number (here: 3) to the "input" channel.

If everything worked out, you should, after a short while, see Output: 6 in your console. If it doesn't work, verify that your code matches the code on this page.

Next steps

Congratulations: You've just built your first Verticle. While this might not seem that impressive, right now, it's the core of everything you'll do when developing for the Application (Java) side of a Telestion project.

While the "inner workings" of a Verticle might get more complex in your projects, the basis always consists of a subset of the following steps:

  1. Setup listeners in the Verticle's onStart() method
  2. Listen for some event (e.g., from the event bus)
  3. Process that event
  4. Publish new information to the event bus

In the following sections, you can take a look at how to improve your Verticle by using Telestion's APIs to get type safety in event bus messages, add configurability to your Verticle (allowing you to re-use it), and more.

Using JsonMessage for event bus messages »/application/tutorials/using-jsonmessage/