Is there standard way to use multiple resources?

Something like

getConnection().use { connection ->
  connection.createStatement().use { statement ->
    statement.executeQuery(sql).use { resultSet ->
      while (resultSet.next()) { ... }
    }
  }
}

looks weird with multiple nested levels for multiple resources. I rolled my own simple implementation for multiple resources:

class Resources : AutoCloseable {
  val resources = mutableListOf<AutoCloseable>()

  fun <T: AutoCloseable> T.use(): T {
    resources += this
    return this
  }

  override fun close() {
    var exception: Exception? = null
    for (resource in resources.reversed()) {
      try {
        resource.close()
      } catch (closeException: Exception) {
        if (exception == null) {
          exception = closeException
        } else {
          exception.addSuppressed(closeException)
        }
      }
    }
    if (exception != null) throw exception
  }
}

inline fun <T> withResources(block: Resources.() -> T): T = Resources().use(block)

which could be used:

withResources {
  val connection = getConnection().use()
  val statement = connection.createStatement().use()
  val resultSet = statement.executeQuery(sql).use()
  while (resultSet.next()) { ... }
}

This works for me, but I wonder if there’s better way with standard library or something like that.

9 Likes

No, there’s no standard solution at this time.

Hello there,
i had the same problem in my project, so i generated multiple inline functions based on the “using”-keyword from C#.

Maybe this is also usefull to you:

Best Regards,

Felix

3 Likes

Hi,
I’m looking for the same thing. Has there been any development?

@ vbezhenar, thank you for your implementation. It works great and is elegant.

Lovely solution, thank you.
Could you let us in on a little secret, how you injected
block: Resources.() -> T
into a use with signature
block: (Resources) -> T
?


Edit: it/this receivers can be interchanged, didn’t know that.