Skip to content
Bluetape4k docs1.11

Connection and DataSource lifecycle

Latest stable Based on Bluetape4k release 1.11.0

Separate ownership of the DataSource, pool, and Connection before choosing a helper. The application manages the DataSource and pool lifecycle. withConnect closes only the connection borrowed for one operation. Returning that connection or passing it to another thread uses a closed resource after the block ends.

import io.bluetape4k.jdbc.sql.withConnect
import javax.sql.DataSource
fun ping(dataSource: DataSource): Boolean =
dataSource.withConnect { connection ->
connection.prepareStatement("SELECT 1").use { statement ->
statement.executeQuery().use { rs -> rs.next() }
}
}

withConnect throws IllegalStateException if DataSource.connection is null and closes a successfully acquired connection with use. The creating code still closes each statement and ResultSet.

APIResourceClosing boundary
DataSource.withConnectConnectionCloses after the block.
DataSource.withStatementConnection, StatementCloses in nested block order.
DataSource.runQueryConnection, Statement, ResultSetThe mapper must consume the result before returning.
Connection.preparedStatementPreparedStatementCloses the statement; the caller still owns the connection.
hikariDataSourceOfHikariDataSourceCreates only; the application closes it.

DataSource extensions usually borrow and close a connection for one block. Connection extensions do not transfer ownership of a connection the caller already holds.

HikariCP is an optional compileOnly dependency. Add it to the application runtime before using these helpers.

import io.bluetape4k.jdbc.hikari.hikariDataSourceOf
val dataSource = hikariDataSourceOf(
jdbcUrl = "jdbc:postgresql://db.example.com:5432/app",
username = "app",
password = databasePassword,
) {
poolName = "app-pool"
maximumPoolSize = 16
connectionTimeout = 3_000
}
try {
// application work
} finally {
dataSource.close()
}

hikariConfigOf and hikariDataSourceOf only wrap Hikari configuration in Kotlin lambdas. They do not choose pool sizes, manage credentials, or install shutdown hooks.

A Spring transaction manager may bind a connection to the current transaction. Calling a separate DataSource.withConnect or withTransaction can create another connection or transaction boundary. Prefer the framework-managed boundary and use only the low-level mapping or statement helpers that fit inside it.

  • Create the pool at application startup and close it once at shutdown.
  • Do not create a HikariDataSource per request.
  • Do not return Connection, Statement, ResultSet, or a lazy Sequence from withConnect.
  • Observe acquisition time, active and idle connections, timeout, and leak detection through pool metrics.

After ownership is explicit, continue with Prepared statements and batches.