Best language features in Kotlin (for me)

I have been doing Java and Scala for many years. Recently my team switched to Kotlin and everybody is enjoying it so far. In this blog post I want to share a personal selection of language features that I really like.

Smart casts on polymorphic collections


Kotlin has a super concise and safe way to narrow down a polymorphic list to a specific sub-type using the as? syntax.

interface Animal {
val name: String
}
data class Monkey(override val name: String): Animal
data class Fish(override val name: String): Animal
val animals: List<Animal> = listOf(Monkey("gorilla"), Fish("trout"), Monkey("oranutan"))
val monkeys: List<Monkey> = animals.mapNotNull { it as? Monkey }


Logging return values


There are situations, where we want to log the return value of a function before actually returning it. Usually, this is done by storing the return value into a variable, doing the log statement and finally returning that variable. Kotlin makes this is a bit simpler with the .also keyword for side-effects. Using .also, we don't have to introduce this artificial variable.

class Service(dependency: Dependency) {
private val logger = KotlinLogging.logger {}
fun doSomething(userId: String): Int {
return dependency.evaluate(userId = userId).also { result ->
logger.trace { "UserId '$userId' was evaluated to: $result" }
}
}
}


... more to come

DynamoDBLocal and UnsatisfiedLinkError in Gradle

This week I started to work on a new project using DynamoDB. As always, I’d like to write some integration tests, to verify my datastore integration works as intended. I know one cheap way to test DynamoDB, is using containers and LocalStack. However, I decided to go even simpler and give DynamoDBLocal a spin. This is just a library, for your tests to depend on. Super easy to integrate in gradle or maven projects.

Unfortunately using DynamoDBLocal is not as straightforward. Relatively soon you might hit a UnsatisfiedLinkError related to SQLLite - similar to:







To fix this in a gradle build, we modified our test task, to copy some binaries around and also make a system property available to the tests.

dependencies {
...
testCompile "com.amazonaws:DynamoDBLocal:1.11.477"
}
task copyDependencies(type: Copy) {
from(configurations.compile + configurations.testCompile) {
include '*.dll'
include '*.dylib'
include '*.so'
}
into 'build/libs'
}
test {
dependsOn copyDependencies
systemProperty 'sqlite4java.library.path', 'build/libs'
useJUnitPlatform()
}
view raw build.gradle hosted with ❤ by GitHub

One last pitfall might be your IntelliJ IDE. Delete all existing test configurations and make sure to run your tests using Gradle Runner.