Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ import java.sql.Connection
* `transaction(database) { }` block completes — so this provider performs no cleanup.
*
* Use when your application manages transactions via Exposed (e.g. Ktor + Exposed apps).
* Must be called from within an active Exposed transaction; otherwise
* `TransactionManager.current()` throws.
* Must be called from within an active Exposed transaction; otherwise [withConnection]
* throws an [IllegalStateException] pointing the caller at the missing `transaction { }`
* block, instead of letting Exposed's own less specific error surface.
*/
class ExposedConnectionProvider : ConnectionProvider {
override fun <T> withConnection(block: (Connection) -> T): T {
val connection = TransactionManager.current().connection.connection as Connection
return block(connection)
val transaction = TransactionManager.currentOrNull()
?: throw IllegalStateException(
"ExposedConnectionProvider.withConnection must be called within an Exposed transaction { } block",
)
return block(transaction.connection.connection as Connection)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.softwaremill.okapi.exposed

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import org.jetbrains.exposed.v1.jdbc.Database
import org.jetbrains.exposed.v1.jdbc.transactions.transaction

class ExposedConnectionProviderTest : FunSpec({

val provider = ExposedConnectionProvider()

test("throws IllegalStateException with actionable message when called outside an Exposed transaction") {
val ex = shouldThrow<IllegalStateException> {
provider.withConnection { /* unreachable */ }
}
ex.message shouldContain "ExposedConnectionProvider.withConnection"
ex.message shouldContain "Exposed transaction { } block"
}

test("supplies the active Exposed transaction's connection to the block") {
val db = Database.connect(
"jdbc:h2:mem:exposed_provider_test_${System.nanoTime()};DB_CLOSE_DELAY=-1",
driver = "org.h2.Driver",
)

val connectionWasOpen: Boolean = transaction(db) {
provider.withConnection { conn -> !conn.isClosed }
}

connectionWasOpen shouldBe true
}
})