2015-10-11

Kotlin, Callable and ExecutorService

I've recently written about using Callable in Groovy, but how does it look like in kotlin?

Callable instance as separete class

First, let's create class which implements Callable interface:
class MyJob : Callable<Int> {
    override fun call() = 42
}

Now we could pass instance of this class to executorService:
fun callableAsClassInstance() =
    executorService.submit(MyJob()).get()

When we run it, as we expect, it returns 42. (Tests are written in groovy, not in kotlin).
def 'should submit callable as class instance from kotlin'() {
    expect:
        callableExample.callableAsClassInstance() == 42
}

Casting to Callable

If we create map with string "call" to closure or just closure and try to cast to Callable, we always obtain CastClassException:
fun callableAsMap() =
    executorService.submit(mapOf("call" to { 42 }) as Callable<Int>).get()

fun callableAsClosure() =
    executorService.submit({ 42 } as Callable<Int>).get()
def 'should submit callable as closure from kotlin'() {
    when:
        callableExample.callableAsClosure() == 42
    then:
        thrown(ClassCastException)
}

def 'should submit callable as map from kotlin'() {
    when:
        callableExample.callableAsMap() == 42
    then:
        thrown(ClassCastException)
}

It does not work as in groovy...

Pass instance method

So maybe passing an instance method which produces value will work?
private fun callMe() = 42

fun callableAsPassedFunction(): Int? {
    return executorService.submit(::callMe).get()
}

It does not even compile. Why? It moans that there is no submit method which could be called with such argument...

But, what interesting, if we create a value to which we assign closure and pass it to submit method then everything is ok and get returns 42.
private val callMe = { 42 }

fun callableAsPassedLocalFunction(): Int? {
    return executorService.submit(callMe).get()
}

Inline implementation

Of course, there is also an option to create Callable inline:
fun callableAsInlineImplementation() =
    executorService.submit(Callable<Int> { 42 }).get()

And this is IHMO the best and the most comfortable way to create Callable in kotlin, because its syntax is much nicer than in java or groovy.

Source code is available here.