Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 335
Mario Avatar asked Mar 28 '16 10:03

Mario


2 Answers

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.

like image 100
Michael Avatar answered Nov 05 '22 12:11

Michael


Since Kotlin 1.1, .use has an AutoCloseable implementation.

@SinceKotlin("1.1")
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@kotlin.internal.InlineOnly
public inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R {
    var exception: Throwable? = null
    try {
        return block(this)
    } catch (e: Throwable) {
        exception = e
        throw e
    } finally {
        this.closeFinally(exception)
    }
}

Copied from source

like image 31
Islam Abdalla Avatar answered Nov 05 '22 11:11

Islam Abdalla