Writing a Verticle
In this tutorial, you'll write a simple Verticle for the Telestion ecosystem.
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:
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:
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
(String
s) define a channel:
For now, keep it simple and listen to the "input"
channel:
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.
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:
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:
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:
- Setup listeners in the Verticle's
onStart()
method - Listen for some event (e.g., from the event bus)
- Process that event
- 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.
UsingJsonMessage
for event bus messages »/application/tutorials/using-jsonmessage/