try-with-resources: "use" extension function in Kotlin does not always work
Kotlin 1.1+ has a standard library that targets Java 8 to support Closeable resource
pattern - kotlin-stdlib-jre8
Gradle
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.1"
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:1.1.1"
Maven
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jre8</artifactId>
<version>1.1.1</version>
</dependency>
Sample
val resource: AutoCloseable = getCloseableResource()
resource.use { r -> //play with r }
For classes that do not support the "use" function, I have done the next homemade try-with-resources:
inline fun <T:AutoCloseable,R> trywr(closeable: T, block: (T) -> R): R {
try {
return block(closeable);
} finally {
closeable.close()
}
}
Then you can use it the next way:
fun countEvents(sc: EventSearchCriteria?): Long {
return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) {
var rs = it.executeQuery()
rs.next()
rs.getLong(1)
}
}
Kotlin targets Java 6 at the moment, so its standard library does not use the AutoCloseable
interface. The use
function only supports the Java 6 Closeable
interface. See the issue tracker for reference.
You can create a copy of the use
function in your project and modify it to replace Closeable
with AutoCloseable
:
public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
var closed = false
try {
return block(this)
} catch (e: Exception) {
closed = true
try {
close()
} catch (closeException: Exception) {
e.addSuppressed(closeException)
}
throw e
} finally {
if (!closed) {
close()
}
}
}