Saturday, August 22, 2015

Write your own Chat service with Vert.x and RiotJS - Part 2

Welcome back!

Glad you made it! After all I promised a fully functioning chat service and haven’t delivered yet!
Let’s see what part deux will do for you. Our goal is to have something chat-like working and be able to deploy it.

Piercing the layers

We are following a tiered approach to architecting this software. There will be a front-end, a web-server and some kind of database.

Instead of completely developing all three tiers after the other, I’m a firm believer in focusing on one or two use-cases and following them through all the layers.
We neglected this a little bit in part 1, starting with the middle tier, but we will try to follow this principle for the rest of the tutorial.

RiotJS 2.x - the good parts of React and Polymer

In order to keep the learning curve small, I opted for RiotJS for our browser-based UI.
It is simple, easy to understand and keeps the amount of magic behind the scenes to a minimum.
We will be using it to develop components (i.e. custom tags) that communicate with each other through events.

A component is basically a piece of HTML template with view/controller logic inside.

Each component will also have a shared API object to talk to our back-end.
It is a pretty simple but battle-tested pattern.

Here’s what a typical interaction with our UI would look like:

Created with Raphaël 2.1.2UserUserRiotTagRiotTagAPIAPIVert.xVert.x<click>channels()GET /chatty/channels{channels:[...]}channelsCallback()update()

Wow, sequence diagrams!

For styling we’ll stick to Bootstrap, since everybody seems to know that one.


Add a web directory to your project directory and…
Well, this is getting too long already. Just grab the code from Github.

If you have a checkout already:

git pull
git checkout part2

If you are starting from scratch:

git clone
cd chatty
git checkout part2

In essence, we are adding a stub index.html, some custom tags, some local JavaScript files and are loading a few more from various CDNs.
The two most important JavaScript files will be vertxbus.js that comes with Vert.x and the implementation of our API in api.js.

Chatty UI

What components does a chat application have?
Maybe a main menu, a list of chat channels, a chat history for the currently selected channel and an input field to chat?
With RiotJS, we can start with something simple like this and evolve it easily:


All we need to do is add a browser-side API, put these new custom tags in their own files and knit it all together in index.html


Our index.html looks deceptively simple:

... bootstrap, sockjs, jquery, riot ...
    <script src="js/vertxbus.js"></script>
    <script src="js/api.js"></script>
    <script src="tag/chatty.html" type="riot/tag"></script>
    <script src="tag/chatty-menu.html" type="riot/tag"></script>
    <script src="tag/chat-history.html" type="riot/tag"></script>
    <script src="tag/chat-input.html" type="riot/tag"></script>
    var eb = new vertx.EventBus('/chatty/channel-events');
    eb.onopen = function() {
        console.log("Event Bus is ready");
        api.eventBus = eb;
        riot.mount('chatty', {api: api});

Ignore the head section for a moment.
There’s the new chatty tag, which we will initialize in a second.

We are setting up an event bus connection to vert.x first. This is the same event bus you used in part 1, all the way extended to the browser (more details about that at the end of this part).

We need to wait until we have a connection established before showing the UI, which is why the rest of the setup is in a callback function. (We’ll not be bothering with AMD or other module loaders for now).

We store a reference to the event bus in our API and then start the RiotJS magic.

The ‘head’ section loads various custom tags as typeriot/tag, one of them being the chatty custom tag.
Calling riot.mount('chatty', { api: api }) tells Riot to compile the contents of tag/chatty.html and insert it into the DOM. We also pass in options (available as opts in the custom tag code) which is our little api object that sits between the components and the server-side.

Here’s tag/chatty.html:

    <chatty-menu api="{opts.api}"></chatty-menu>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-1" style="height:100%;"><channel-list api={opts.api}></channel-list></div>
            <div class="col-md-11"><chat-history api="{opts.api}"></chat-history></div>

We added some scaffolding around our new custom tags (and you can probably tell, that I’m not super good at this). Let’s look at them more closely.

(inside chatty.html)

Things get slightly more interesting here, as we define what a channel list is and how we are getting the data.
As you can see, we have the actual template and the code controlling it in the same place, which makes it really easy to maintain and understand.
(We could even omit the script tag and use ES6 syntax if we wanted to)

    <div style="margin-top:60px; margin-left:8px;">
    <ul class="nav nav-pills">
        <li each="{channels}"><a href="#" onclick="{parent.selectChannel}">{name}</a></li>
        var self = this;
        this.channels = [];

        opts.api.channels(function(ch) {
            self.channels = ch.channels;

        this.selectChannel = function(event) {
            opts.api.trigger('channel.selected', event.item);


The HTML part looks fairly standard with the exception of new attributes like each and substitutions inside curly braces. RiotJS supports any JS expression inside those.
What we want to do here is to get the list of channels from our server and display them inside an ul tag.

The element that has the each attribute is then repeated for each entry of our list. It also establishes a new context, i.e. the expression {name} refers to the current object in the {channels} list. (This is also the reason the onclick handler needs to refer to the parent context.)

If the list of channels changes, RiotJS will figure out how to re-arrange and change the DOM for us.

The script section has all the logic we need for this component. The opts variable contains any options passed into the component. As part of our design we chose to always have the api object passed in.
We call its channels function and provide a callback to get the list of channels via the REST API we wrote in part 1.
When we receive it, we store the result in our channels variable and update the component.

We also provided an onclick event handler: If a channel is clicked, selectChannel will be called with the channel object in event.item.

Now instead of trying to figure out which parts of the UI need to be updated, we simply send an channel.selected event via the api object with the currently selected channel and hope someone picks up on the other end.

This keeps the component clean of any other dependencies and makes it very simple.
Which is a good guideline: If your component’s code becomes too large, you might need to add a few more sub-components or re-think your component model.

Someone clicked on a channel! What now?


Well, in that case we want to switch to the chat history of that channel and show any incoming chat messages.

    <div class="container" style="height:100%; overflow: scroll; margin-top:60px;">
        <div class="row" each="{chat in chatLines}">
            <div class="col-md-12">
                <system-message if="{chat.type=='system'}" message={chat}></system-message>
                <chat-message if={chat.type=='chat'} message={chat}></chat-message>
        <div class="row" style="height:40px;" id="empty"></div>
    <chat-input api="{opts.api}"></chat-input>
        var self = this; = {};
        this.chatLines = [];

        opts.api.on('channel.selected', function(channel){
            console.log("Switch to channel: " + JSON.stringify(channel));
   = channel;
            self.chatLines.push({alias:'system', type:'system',
                message: '--- ' + + ' ---'});

        opts.api.on('message.received', function(msg, channel) {
            if (channel.address == {
                    behavior: "smooth",
                    block: "end"


The crucial part of this component is each="{chat in chatLines}".
We store all the chat lines in chatLines and we are inserting custom-tags for each of those. Depending on the type of chat message, we insert <system-message> or <chat-message> (check the if attribute).
Finally, we add a custom tag for users to enter a chat line.

The script part is equally simple: We register for internal events being sent via the api object (which is an Observable) and meet our old friend ‘channel.selected’.
Here we use api.subscribe(..) to register for any event bus messages being sent over this channel.

Lastly we register for any messages being sent from the API. If we receive one, we just stuff it into the chatLines array, let RiotJS update our DOM and then scroll the new line into view.

self.empty is automatically set to the DOM element with that ID. No need to look up elements via jQuery.

Custom tags like <chat-message> take care of the actual layout of the chat message. We are using bootstrap’s media classes for this.


Time to actually provide an input field to type a message!


    <footer class="footer navbar-fixed-bottom" style="left: 81px;">
    <form class="form-inline" action="#" style="margin:4px;">
        <div class="form-group">
            <div class="input-group">
                <div class="input-group-addon"><i class="glyphicon glyphicon-chevron-right"></i></div>
                <textarea disabled="{channel == null}" type="text" class="form-control" rows="1" cols="60" id="chatLine" placeholder="{channel ? 'Get chatty':'Select channel'}" onkeydown="{keydown}"></textarea>
                <!--<div class="input-group-addon"><i class=""</i></div>-->

        var self = this; = null;
        opts.api.on('channel.selected', function(channel){
   = channel;

        this.keydown = function(event) {
            if (event.keyCode == 13) {
                if (event.shiftKey) {
                    return true;
                } else {
                    var line = self.chatLine.value.replace(/$/mg,'<br>');
                    var chat = {type: 'chat', message: line};
                    self.chatLine.value = "";
                    self.chatLine.rows = 1;
                    return false;
            return true;

The interesting parts are the attributes on the textarea tag and the component’s code. We have a few short JavaScript expressions in there.
If those get too long, we would simply add appropriate functions to the script part.

We register for the channel.selected event to focus on the textarea and we register a handler to receive keystrokes. We want the input field to grow by a line whenever shift+enter is pressed.
Note that in event handlers, RiotJS will call update() automatically.


We’ll skip that for now since we don’t have any proper user management yet. In the demo app, just fill in an e-mail address which will be used as chat alias (and avatar).


There is no vert.x or backend specific stuff in any of the UI components. All components consider the api object as the only facade into the dirty world of network communication and caching etc.

If we decide to replace the backend, we could do so if we stick to the interface defined by the api object.

api = (function() {
    var api = riot.observable();
    api.subscriptions = {};
    api.useAlias = function(alias)  {
        this.alias = alias;

    api.channels = function(callback) {
        $.getJSON("/chatty/channels", callback);

    api.subscribe = function(channel) {
        if (!api.subscriptions[channel.address]) {
            api.subscriptions[channel.address] = function (msg) {
                api.trigger('message.received', msg, channel);
            this.eventBus.registerHandler(channel.address, api.subscriptions[channel.address]);
            console.log("Subscribed to " + channel);

    api.sendChat = function(message, channel) {
        message.alias = this.alias;
        message.avatar = this.avatar;
        this.eventBus.publish(channel.address, message);

    // helper functions

    return api;

(We don’t mess with modules yet, so excuse the global variable)
Our actual api object is an observable, which means it has on and trigger functions which are used to communicate with the UI components as seen.

Here we finally have some Vert.x specific code.
this.eventBus is the gateway to the server-side event bus and we use it to register for channel addresses (map subscriptions ensures we only register once).

Whenever a message from Vert.x is received, we simply broadcast it via the RiotJS event system to interested parties like <chat-history>.

We could provide our own chat message cache here, if we wanted to. Maybe synchronize it with the server-side when coming out of offline mode? Ahh, dreams for later tutorials.

sendChat is where we are actually sending off a chat message. We use broadcast here, which means all interested listeners will receive the message, i.e. each user of chatty that has a subscription for the current channel!
Vert.x takes care of the server-side distribution (we’ll see how in a moment).

There’s a few more functions:

  • useAlias just registers the chat alias to use
  • channels uses jQuery to make an AJAX call to our backend to retrieve the list of channels. Note that we also could use an event bus messages for this! Also, we could broadcast to the UI components that a new channel list has arrived. We’ll take care of that later when we can actually add/remove channels

That basically wraps it up for the client-side for now.

We have added a new use case to our app: sending a chat message.
But haven’t changed the backend yet to deal with it.

Vert.x EventBus via SockJS

Meanwhile, most of the actual web server code can be found in
I ditched our HelloChatty.js file and moved the REST API code.

We need to add support for sending event bus messages all the way to the browser and back. Vert.x comes with a SockJS server (and client) to accomplish this. SockJS allows us to notify connected clients (and will automatically figure out the best way to do this: short polling, long polling, websocket, etc.)

Let’s add a bridge that connects the internal Vert.x event bus to the outer world:

SockJSHandler sockJSHandler = SockJSHandler.create(vertx);

With this and vertxbus.js in your web/js directory, we can make SockJS connections and send any message.
And that is a little bit of a problem.

The client can’t be trusted.

Exactly. The client code can’t be trusted and you don’t want client-side code to be able to send and receive any message.
That’s why we can add filters to the bridge that allows connected clients to only send and receive specific messages.

BridgeOptions options = new BridgeOptions();                                          
options.addOutboundPermitted(new PermittedOptions().setAddressRegex("channel\\..*")); 
options.addInboundPermitted(new PermittedOptions().setAddressRegex("channel\\..*"));  

Now, only addresses that start with channel. are allowed on the event bus bridge.

Serving Static Content

Let’s have Vert.x also serve all of our juciy UI code. For this, we are adding a static handler that is part of the vertx-web module.

StaticHandler web = StaticHandler.create("web").setFilesReadOnly(true).setDirectoryListing(false);

This will serve the contents of our web directory as static file.

Let’s give it a go. Start ChattyServer
vertx run us.monoid.vertx.chatty.ChattyServer

and point your browser to:

Pick an alias (if you use an e-mail address, we’ll get an avatar from gravatar) in the main menu, select a channel and chat away.
Open a second tab to the same address and chat a bit with yourself.
It’s therapeutic.
It will help you understand why you keep reading overly long tutorials.


We’ll be using Heroku to deploy our little chat app.
If you haven’t done so yet, sign up for Heroku and install the Heroku toolbelt.
Heroku is free for our little test instance and it automates a lot of things for us.

Building a stand-alone JAR file

We’ll be using the lovely maven-shade plugin to package our app, along with the web pages and the kitchen-sink into a single JAR file.

Check the pom.xml plugin section for <artifactId>maven-shade-plugin</artifactId>

We need to configure it with a manifest entry, so it knows how to deploy our app:


The shade plugin adds itself to the standard mvn package goal, so if we run mvn package now, we end up with a ‘fat’ jar. About 4.4MB for our little app. Not too bad!

Now we can run our app like this:

java -jar target/chatty-fat.jar


Heroku deployment

We are going to use the Heroku deployment plug-in for deployment.
Since we are only deploying a single JAR file, we tell it to ignore all the rest.

         <web>java -jar target/${project.artifactId}-fat.jar</web>

One more thing we need to change: Heroku expects your app to use the PORT environment variable for your web application.

We’ll change our start verticle accordingly:

private int port = 8888;
    public void start() throws Exception {
        Optional.ofNullable(System.getenv("PORT")).ifPresent(it -> port = Integer.parseInt(it));

and in startWebServer()


Still not quite there: We should add a forward from ‘/’ to the actual homepage of Chatty. There’s no forward() function available yet, so we have to write our own little handler.

router.route("/").handler(rc -> {
  if (rc.request().uri().equals("/")) {
    String uri = rc.request().absoluteURI();
    rc.response().setStatusCode(301).putHeader("Location", uri + "/chatty/app/index.html" ).end();
   } else {;

Next, go to the project root directory and run

heroku login
heroku create

This creates the app on the Heroku servers.
You only need to do this once!

Now, to build and deploy, run this:

mvn clean heroku:deploy

then run

heroku open

to see Chatty in all its (non)-glory!

And that concludes the second part. We still haven’t talked about persistence and there’s so much wrong with this app before it becomes a real chat app,
but we have a start.

Written with StackEdit.

Sunday, August 16, 2015

Write your own Chat service with Vert.x 3.0 - Part 1


This is a multi-part tutorial on how to write a chat service with Vert.x 3.0.
Bring some knowledge about Java, JavaScript and maven (or gradle) and tolerance for overly long sentences and let’s have some fun!

What is Vert.x 3 again?

Vert.x is a reactive, actor-based, event-bus driven, asynchronous, polyglot tool-kit for the JVM. (Wow, that’s a mouthful.) Let’s look at what this means in detail:
Event-Bus Driven
At the heart of Vert.x lies an event bus with a very simple address scheme that supports publishing and sending messages, along with replying to messages. Payload is usually JSON or plain-text.
Vert.x supports the popular RxJava library that allows you to write observers that react to sequences of events.
Most code in Vert.x is written as a so-called “Verticle”. In its simplest form a Verticle is a piece of single-threaded code that acts on events from the event bus.
Any I/O in Vert.x is performed asynchronously. Instead of blocking the current thread and waiting for data to arrive, you usually specify a callback-handler that is called when data arrives. You can still run blocking code though (in separate worker threads).
Vert.x’s API is available in several programming languages. Verticles deployed in Java, JavaScript, Groovy, Python or Ruby can seamlessly communicate via the event bus. You are free to use – say – JavaScript to write your REST API and do the heavy lifting in some Java-based Verticles.
You can also think of Vert.x as the ‘multi-threaded Node.js of the Java world’. Kinda.
A few useful links
Vert.x documentation
Vert.x download

Another Chat service? Noooooo.

I understand. But a chat service is a good showcase for the capabilities of Vert.x. One of those being the event bus, which can be extended all the way to the browser.
Let’s quickly summarize some features we would like to have for our initial prototype:
  • Create a chat alias
  • See a list of channels
  • Join or create a chat channel
  • Send a message
  • Leave a chat channel
We’ll cover more features, such as presence and typing indicators, in later parts of this tutorial.
We’ll also be writing some funky HTML later on using RiotJS. Because, why not?
It looks like our list above already has identified some actors we need. For this exercise we’ll turn them into Vert.x actors and see what we can do with them.
We have a User using an alias, we have a Channel and there are Messages exchanged between Users of a Channel.
That seems easy enough.
Let’s get coding!
The source code for this tutorial is on github. Each part will be tagged as a release.

New Project! New Project! New Project!

I’m using Intellij here to set up a new Maven-based project. Feel free to use your favorite IDE.
Create a new Maven project called Chatty, pick any group ID, and add this to your pom.xml:




This will give us the core Vert.x libraries, the freshly baked web libraries for our REST API, and the JavaScript language binding.
We also need to tell Maven that we are living in the future and want to use Java 8 for compilation and where our JavaScript code will be hiding (see <resources> tag)
All set.
Let’s give it a spin.
If you are tired of copying and pasting stuff, you can get the code like this:
git clone
cd chatty
git checkout part1

Hello Chatty

Let’s start with a simple HTTP service written in JavaScript.
If you haven’t cleverly anticipated it yet, create a js directory in src/main and add a HelloChatty.js file to it. Here’s our first working HTTP server written with Vert.x!
var html = '<link rel="stylesheet" href="">'
    + '<h1 style="color:navy;position:relative;top:50%;transform:translateY(-50%);"'
    + 'align="center" class="animated infinite rubberBand">Hello Chatty</h1>';

var Router = require("vertx-web-js/router");
var router = Router.router(vertx);
router.route('/chatty').handler(function (routingContext) {
    routingContext.response().putHeader("Content-Type", "text/html")
print('Go to http://localhost:8888/chatty');
You can run this via command line from your project’s root directory (if you have downloaded and unpacked the full version of Vert.x 3.0):
$ ~/Downloads/vert.x-3.0.0/bin/vertx run src/main/js/HelloChatty.js 
Or you can run it from your IDE using io.vertx.core.Starter as main class and adding run HelloChatty.js as arguments. (In IDEA, use an Application configuration)
Go to http://localhost:8888/chatty and admire the bad color choice and obnoxious CSS animation!
Wait! What? A full web-server in 4 lines of code?
Let’s look at the details.
Ignoring the bad HTML in the first few lines, let’s look at this Router thingie more closely:
var Router = require("vertx-web-js/router");
This loads the router module from the web module (a full list is available here)
var router = Router.router(vertx);
The JavaScript environment contains a pre-defined vertx object which is used to access the vertx core classes and functions. Here we create a new router and tell it to use this vertx object. We’ll see how to do this with Java later on.
What is a router anyway?
A router allows you to attach functions to the individual parts of an HTTP request! In the simplest case, each part of an URL can be matched to one or more routes.
A handler function can then be attached to a route to handle the HTTP request.
In short, a router sits between HTTP requests and your code and handles mapping the request method, path, header and parameters to your functions.
In our example, we define a route and attach a handler for the /chatty part of the URL:
router.route('/chatty').handler(function (routingContext) {
    routingContext.response().putHeader("Content-type", "text/html")
This in essence means, whenever any kind of HTTP request is received that starts with /chatty, call the handler function.
The function takes a single parameter routingContext which gives you access to the HTTP request and response.
In our simple example, we are declaring the response to be proper HTML and then use the end(...) to end the response with a piece of not-really-HTML-conformant-garbage-a-browser-will-still-display.
Last but not least we set up the actual HttpServer listening to port 8888. The requestHandler function expects a handler for all incoming HTTP requests which our router provides.

Very Verticle!

Let’s write a Java verticle now to illustrate how they are in essence single-threaded actors which use the event bus to communicate.
For a real chat service, we need some function that provides a list of channels and returns it. A perfect excuse for a Verticle.
A Java verticle is simply an instance of a subclass of AbstractVerticle.
Vert.x gives a Verticle a few excellent guarantees:
  • once deployed, its code will always run in the same event-loop thread which makes synchronizing on instance data unnecessary
  • messages will be received in order
But it also demands a few things from your code:
  • don’t block! No Thread.sleep, no synchronous I/O etc. in your Verticle. There are still ways to do it (in worker threads), but we usually can just rely on the Vert.x API
  • don’t call other verticles directly (use the event bus instead). This is important for scalability issues as the event bus will find an available verticle for you (if you deployed more than one of the same kind)

Channel Manager - does almost nothing

That said, let’s look at our Verticle ‘ChannelManager’:
 public class ChannelManager extends AbstractVerticle {
    Map<String, ChannelInfo> channelMap = new HashMap<>();

    public void start() throws Exception {
        new ChannelInfo("#general").registerWith(channelMap);
        vertx.eventBus().consumer("channels.list", msg -> {
            msg.reply(new JsonObject().put("channels", new JsonArray(channelMap.values().stream().map(ci -> ci.toJson()).collect(Collectors.toList()))));
        vertx.eventBus().consumer("channels.join", (Message<JsonObject> msg) -> {
            // sanity checks for the values
            ChannelInfo channel = channelMap.computeIfAbsent(msg.body().getString("name"), name -> new ChannelInfo(name));

    static class ChannelInfo {
        String name, address;

        ChannelInfo(String name) {
   = name;
            this.address = "channel." + name; // we could use UUID.getRandom().toString here as well
        JsonObject toJson() {
            return new JsonObject().put("address", address).put("name", name);

        void registerWith(Map<String, ChannelInfo> channelMap) {
            channelMap.put(name, this);
We use a simple Map<String,ChannelInfo> to store information about all existing channels.
In start(), stuff is getting more interesting.
First we add a standard channel (so we have something to send).
Then we register with the even bus to consume any messages arriving on address ‘channels.list’. The message handler is a simple lambda expression that gets passed a Message<?> object.
We can use that object to reply to the sender of the message! In this case, we use some stream() magic to assemble a JSON object with the list of channels.

Test, Decker-Unit!

Let’s get fancy and write a unit test for this. We will be using bog-standard JUnit 4 for this:
public class ChannelManagerTest {
    private static Vertx vertx;

    public static void setUp() throws Exception {
        CountDownLatch latch = new CountDownLatch(1);
        vertx = Vertx.vertx();
        vertx.deployVerticle(new ChannelManager(), res -> {

    public void listChannels() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        vertx.eventBus().send("channels.list", null, reply -> {
        if (!latch.await(5, TimeUnit.SECONDS)) {
@BeforeClass is where we set up our test environment and where we deploy a single instance of the ChannelManager. Note that deployment is asynchronous in nature, we are registering a callback that then counts down on the latch to allow the JUnit thread to finish set up.
We’ll be using this little trick a few more times (There are a few extensions for JUnit out there that deal with the asynch nature of things. We’ll try to keep in simple by relying on a CountDownLatch.
Test method listChannels uses the Vert.x event bus to send an (empty) message to the address bus address ‘“channels.list”’. Luckily, that is exactly the address the ChannelManager is listening on!
Note that listChannels has no idea about the existence of ChannelManager. It just knows that when it sends something to "channels.list", it will get a reply.
We could exchange our implementation of ChannelManager with a Ruby one and as long as we keep the message format the same, we are good to go!
Our test code also has a reply handler with a lambda expression:
It expects to get a reply with a list of channels.
Run the test and hopefully it will complete and give you this output:
We have a list of channel objects with a name and an event bus address we will use later.

Listing Channels the traditional way

Getting the list of channels via the event bus works now, but we also want to expose it as a REST resource.
Open HelloChatty.js and add the following on line 5 or so:
This deploys a single instance of the ChannelManager verticle.
And we need to add a simple REST API to get a list of channels.
router.route('GET', '/chatty/channels').handler(function(routingContext) {
    vertx.eventBus().send('channels.list', null, function(reply, err) {
        if (err == null) {
            var channelList = reply.body();
            routingContext.response().putHeader("Content-Type", "application/json").end(JSON.stringify(channelList));
If a client does a GET request on /chatty/channels, we will send a message to the event bus, register a function as reply handler and - if we get a valid reply -(which is automatically converted into a JS object), stringify the channel list and send it as payload.
Now, run HelloChatty again.
If your IDE is clever, the classpath is already set up.
If you run vert.x from the command line, try this:
~/Downloads/vert.x-3.0.0/bin/vertx run src/main/js/HelloChatty.js -cp target/classes
Then point your browser to http://localhost:8888/chatty/channels
Working? Not working?
Let me know in the comments.

Sending a chat message

With a list of channels in hand we have enough information to actually chat directly via the event bus (in later parts we might re-visit that decision).
vertx.eventBus().publish(channel.address, {message:'Hello World', alias: 'beders' });
This snippet above will send a message to ALL listeners of a chat channel, which is what we will be using in part 2, where we’ll have a first prototype ready to go that can actually - you know - send chat messages between users.