Rick

Rick
Rick

Sunday, February 21, 2016

Step 3 Adding Kotlin (Microservices with Vertx)

We decided to add Kotlin to the mix. It is terse and modern and very compatible with the core Java libs. It builds on your knowledge of Java. The Idea guys explain how to do add Kotlin to a Gradle project, yet it still took some messing around.
You can find the source code for this in this branch.
To do this we added the Kotlin plugin to gradle.

Adding Kotlin to gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.0-beta-4584'
    }
}


plugins {
    id 'java'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '1.2.2'
    id 'idea'
}


apply plugin: "kotlin"

...

dependencies {
...
    compile 'org.slf4j:slf4j-api:1.7.12'
    compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.0-beta-4584'
    testCompile group: 'junit', name: 'junit', version: '4.11'
}


Most of the gradle build files stays the same. The way we build and execute stays the same as well.
We left WebVerticle in Java for now. We changed the other files and we were able to get rid of a few files as well by grouping enums with the classes that more or less own them.

HelloWorldService.kt

package com.github.vertx.node.example

import io.vertx.core.AbstractVerticle
import io.vertx.core.eventbus.Message
import org.slf4j.LoggerFactory

enum class HelloWorldOperations {

    SAY_HELLO_WORLD
}


class HelloWorldVerticle : AbstractVerticle() {

    private val logger = LoggerFactory.getLogger(HelloWorldVerticle::class.java)
    override fun start() {
        vertx.eventBus().consumer<Any>(Services.HELLO_WORLD.toString()) { message -> dispatchMessage(message) }
    }

    private fun dispatchMessage(message: Message<Any>) {

        try {
            val operation = HelloWorldOperations.valueOf(message.body().toString())
            when (operation) {
                HelloWorldOperations.SAY_HELLO_WORLD -> message.reply("HELLO WORLD FROM KOTLIN")
                else -> {
                    logger.error("Unable to handle operation {}", operation)
                    message.reply("Unsupported operation")
                }
            }
        } catch (ex: Exception) {
            logger.error("Unable to handle operation due to exception" + message.body(), ex)
        }

    }

}

MainService.kt

package com.github.vertx.node.example

import io.vertx.core.AbstractVerticle
import io.vertx.core.Vertx
import org.slf4j.LoggerFactory
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
import kotlin.collections.forEach

enum class Services {
    HELLO_WORLD
}


public class MainVerticle : AbstractVerticle() {


    private val logger = LoggerFactory.getLogger(MainVerticle::class.java)

    override fun start() {

        /** Count of services.  */
        val serviceCount = AtomicInteger()

        /** List of verticles that we are starting.  */
        val verticles = Arrays.asList(HelloWorldVerticle(), WebVerticle())

        verticles.forEach { verticle->
            vertx.deployVerticle(verticle) { deployResponse ->

                if (deployResponse.failed()) {
                    logger.error("Unable to deploy verticle ${verticle.javaClass.simpleName}",
                            deployResponse.cause())
                } else {
                    logger.info("${verticle.javaClass.simpleName} deployed")
                    serviceCount.incrementAndGet()
                }
            }
        }


        /** Wake up in five seconds and check to see if we are deployed if not complain.  */
        vertx.setTimer(TimeUnit.SECONDS.toMillis(5)) { event ->

            if (serviceCount.get() != verticles.size) {
                logger.error("Main Verticle was unable to start child verticles")
            } else {
                logger.info("Start up successful")
            }
        }

    }

    companion object {
        @JvmStatic fun main(args: Array<String>) {
            val vertx = Vertx.vertx()
            vertx.deployVerticle(MainVerticle())
        }
    }
}
The code is a bit smaller and there are less files. We think Kotlin will be a big boon when we start using data class.
Kafka and Cassandra support, training for AWS EC2 Cassandra 3.0 Training