Jim Cheung

Vert.x

(groovy notes)

Verticles

// server.groovy
import static org.vertx.groovy.core.streams.Pump.createPump
vertx.createNetServer().connectHandler { socket ->
    createPump(socket, socket).start()
}.listen(1234);

run with vertx run server.groovy

then telnet localhost 1234

when stop:

def vertxStop() {
    println "some cleanup"
}

container and vertx object

each verticle has

// get config
def config = container.config
// config passed by -conf option
$ vertx run foo.groovy -conf myconf.json 
// log
def logger = container.logger
logger.info "log something"
// environment variables
// container.env 
// deploying
container.deployVerticle(main)
container.deployWorkerVerticle(foo)
container.deployModule("some.module")
// passing config
def config = [ foo: "wibble", bar: false ]
container.deployVerticle("foo.childVerticle", config)
// specifying number of instances
container.deployVerticle("Foo.groovy", 10)
// getting notice
container.deployVerticle("Foo.groovy") { asyncResult ->
    if (asyncResult.succeeded) {
        println "deployed, id ${asyncResult.result}"
    } else {
        asyncResult.cause.printStackTrace()
    }
}
// undeploying
container.undeployVerticle(deploymentID)

Event Bus

messages are sent on the event bus to an address (any string, acme.games.pacman, X)

handler is a thing that receives messages from the bus. you register a handler at an address.

register and unregister

// set a message handler
def eb = vertx.eventBus
eb.registerHandler("test.address") { message -> println "message received ${message.body}" }
// or
def myHandler = { message -> println "message received ${message.body}" }
eb.registerHandler("test.address", myHandler) { println "registered" }
// unregister
eb.unregisterHandler("test.address", myHandler) { println "unregistered" }

publishing messages

eb.publish("test.address", "hello")

sending messages

sending a message will result in only one handler registered at the address receiving the message. this is the point to point messaging pattern. (non strict round-robin)

eb.send("test.address", "hello")

replying messages

after you send a message you want to receive a reply from the recipient (request-response pattern)

// the receiver
def myHandler = { message -> 
    println "received ${message.body}"
    message.reply "this is a reply"
}
eb.registerHandler("test.address", myHandler)
// sender
eb.send("test.address", "this is a message") { message -> 
    println "reply received ${message.body}"
}

it's a good convention to communicating with JSON

eb.send("test.address", ["foo": "wibble", "bar": "eek"])

distributed event bus

to make each vert.x instance participate on the same event bus, start each vert.x instance with -cluster

Shared Data

currently only support within same vert.x instance.

shared maps

def map = vertx.sharedData.getMap("demo.mymap")
map["some-key"] = 123
// in another verticle
def map = vertx.sharedData.getMap("demo.mymap")
//...

shared sets

def set = vertx.sharedData.getMap("demo.myset") // <--- getSet ??
set << "some-value"

Buffers

creating buffer

def buff = new Buffer()
def buff = new Buffer("foo")
def buff = new Buffer("some-string", "UTF-16")
def buff = new Buffer(100000)

writing to buffer

def buff = new Buffer()
// use appendXXX methods
buff.appendInt(123).appendString("hello\n")
// or leftShift operator
buff << 123 << "hello" << "\n"
socket << buff
// random access 
def buff = new Buffer()
buff.setInt(1000, 123)
buff.setBytes(0, "hello")
// or
buff[1000] = 123
buff[0] = "hello"

reading from buffer

def buff = ...
for (i in 0 ..< buff.length) {
    println "byte value at $i is ${buff.getByte(i)}"
    // or
    println "byte value at $i is ${buff[i]}"
}

other buffer methods: length(), copy()