Search code examples
kotlintry-with-resourcesautocloseable

My own solution for Kotlin's try-with-resources absence


Kotlin provides the use function for Closeable objects, but it seems they forgot to consider AutoCloseable (e.g. DB prepared statements) for the try-with-resources full Java equivalent.

I've implemented the next "home-made" solution:

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)
    }
}

I'm new to Kotlin and I would like to know if I'm missing something important in my own solution that could give me problems/leakages in a production environment.


Solution

  • Your implementation will work fine but it's different from a standard try-with-resources implementation. If you want it to work like in Java you should do something like that:

    inline fun <T : AutoCloseable, R> trywr(closeable: T, block: (T) -> R): R {
      var currentThrowable: java.lang.Throwable? = null
      try {
        return block(closeable)
      } catch (throwable: Throwable) {
        currentThrowable = throwable as java.lang.Throwable
        throw throwable
      } finally {
        if (currentThrowable != null) {
          try {
            closeable.close()
          } catch (throwable: Throwable) {
            currentThrowable.addSuppressed(throwable)
          }
        } else {
          closeable.close()
        }
      }
    }
    

    UPDATE:

    As mfulton26 pointed out in his comment kotlin.Throwable doesn't contain addSuppressed(Throwable) method so we have to cast kotlin.Throwable to java.lang.Throwable to make the code work.