Entrepreneur. Creator of Groovy++ Alex is a DZone Zone Leader and has posted 31 posts at DZone. You can read more from them at their website. View Full User Profile

Kotlin in action: wrapping vert.x

07.17.2012
| 14111 views |
  • submit to reddit

This is pretty short note where I want to show power of Kotlin in real life use.

We will wrap amazing vert.x framework in order to make it a bit Kotlin-ish but the main goal will be to show couple of standard ways to wrap existing Java API.

Let us start with standard example from vert.x - Echo websocket server. Here is Java code

public class PerfServer extends Verticle {

  private static final int BUFF_SIZE = 32 * 1024;

  public void start() throws Exception {
    vertx.createHttpServer().setReceiveBufferSize(BUFF_SIZE).setSendBufferSize(BUFF_SIZE).setAcceptBacklog(32000).
        websocketHandler(new Handler<ServerWebSocket>() {
      public void handle(ServerWebSocket ws) {
        Pump.createPump(ws, ws, BUFF_SIZE).start();
      }
    }).listen(8080, "localhost");
  }
}

And here is the same code with Kotlin

public class PerfServer() : Verticle() {
class object {
val BUFF_SIZE = 32*1024
}

public override fun start() {
createHttpServer{
receiveBufferSize = BUFF_SIZE
sendBufferSize = BUFF_SIZE
acceptBacklog = 32000

websocketHandler { ws ->
//System.out.println("connected " + ++count);
Pump.createPump(ws, ws, BUFF_SIZE)!!.start();
}
}.listen(8080, "localhost");
}
}

We use very important pattern here - "function literal representing extension function" Probably the easiest way to explain what do I mean is to show what is the method createHttpServer we use in the code snippet above.

public fun Vertx?.createHttpServer(config: HttpServer.()->Unit) : HttpServer {
    val httpServer = this!!.createHttpServer()!!
    httpServer.config()
    return httpServer
}

public fun Verticle.createHttpServer(config: HttpServer.()->Unit) : HttpServer = getVertx().createHttpServer(config)

What we do here is "extension functions accepting extension function as parameter". We "extend" Vertx and Verticle interfaces from vertx Java API with new methods and when we pass function literal as parameter to a call to createHttpServer there is implicit this/receiver of the type HttpServer and we can use methods and properties without specifiing receiver explicitly. This is very powerful ingridient of building DSLs with Kotlin.

It is also interesting to notice that in the method Vertx?.createHttpServer we have to deal with nullability (Java API integration point) but in one we really use (Verticle.createHttpServer) we do not.

Now small note on extension properties. Vertx has convension of chainig setters. In Kotlin world each such setter returns HttpServer? (? means nullable), so we either have to use !!-operator (ensure not null) on every chained call or to do something different. My first (and very natural) solution was to make a lot of named arguments with default value for the createHttpServerMethod similar to what we did in previous article To make life more interesting we will use another power approach - "extension properties"

I hope following code in self explaining. We extend HppServer class from vertx Java API with new properties

public var HttpServer.sendBufferSize : Int
    get() = getSendBufferSize()!!
    set(v: Int) {
        setSendBufferSize(v)
    }

public var HttpServer.receiveBufferSize : Int
    get() = getReceiveBufferSize()!!
    set(v: Int) {
        setReceiveBufferSize(v)
    }

public var HttpServer.acceptBacklog : Int
    get() = getAcceptBacklog()!!
    set(v: Int) {
        setAcceptBacklog(v)
    }

And finally just for the sake of completeness I want to show probably the simplest part, which is definition of websocketHandler method

public fun HttpServer.websocketHandler(handlerFun: (ServerWebSocket)->Any?): HttpServer
        = websocketHandler(handler(handlerFun))!!

public fun <T> handler(handlerFun: (T)->Any?) : Handler<T?>  = object: Handler<T?> {
    public override fun handle(arg: T?) {
        handlerFun(arg!!)
    }
}

Utility function handler helps us to wrap Kotlin function literal in to Handler interface from vertx Java API and websocketHandler extension function let us use nice Kotlin function literal syntax.

You can find more examples and tricks on vertex-kotlin project on github

Thank you for reading. As usually I hope it was interesting.

Till next time.

Published at DZone with permission of its author, Alex Tkachman.