Skip to content

Commit 86bcf4f

Browse files
author
Al Scott
authored
Merge pull request #1 from campspot/figure-out-jdbi-transactions
Figure out request lifecycle transactions for JDBI
2 parents ad44452 + 666c746 commit 86bcf4f

File tree

15 files changed

+102
-65
lines changed

15 files changed

+102
-65
lines changed

.idea/kotlinc.xml

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pom.xml

+16-15
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
</dependencyManagement>
3939

4040
<dependencies>
41+
<dependency>
42+
<groupId>com.campspot</groupId>
43+
<artifactId>dropwizard-jdbi3-transactions-core</artifactId>
44+
<version>1.0</version>
45+
</dependency>
4146
<dependency>
4247
<groupId>io.dropwizard</groupId>
4348
<artifactId>dropwizard-core</artifactId>
@@ -55,21 +60,6 @@
5560
<artifactId>dropwizard-jdbi3</artifactId>
5661
<version>1.2</version>
5762
</dependency>
58-
<dependency>
59-
<groupId>org.jdbi</groupId>
60-
<artifactId>jdbi3-core</artifactId>
61-
<version>3.0.1</version>
62-
</dependency>
63-
<dependency>
64-
<groupId>org.jdbi</groupId>
65-
<artifactId>jdbi3-kotlin</artifactId>
66-
<version>3.0.1</version>
67-
</dependency>
68-
<dependency>
69-
<groupId>org.jdbi</groupId>
70-
<artifactId>jdbi3-kotlin-sqlobject</artifactId>
71-
<version>3.0.1</version>
72-
</dependency>
7363
<dependency>
7464
<groupId>mysql</groupId>
7565
<artifactId>mysql-connector-java</artifactId>
@@ -104,6 +94,12 @@
10494
</dependency>
10595

10696

97+
<dependency>
98+
<groupId>com.campspot</groupId>
99+
<artifactId>dropwizard-jdbi3-transactions-test</artifactId>
100+
<version>1.0</version>
101+
<scope>test</scope>
102+
</dependency>
107103
<dependency>
108104
<groupId>io.dropwizard</groupId>
109105
<artifactId>dropwizard-testing</artifactId>
@@ -247,6 +243,11 @@
247243
<groupId>org.jetbrains.kotlin</groupId>
248244
<artifactId>kotlin-maven-plugin</artifactId>
249245
<version>${kotlin.version}</version>
246+
<configuration>
247+
<args>
248+
<arg>-java-parameters</arg>
249+
</args>
250+
</configuration>
250251
<executions>
251252
<execution>
252253
<id>compile</id>

src/main/kotlin/com/campspot/TimeTrackingApplication.kt

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package com.campspot
22

33
import com.campspot.dao.PunchDAO
4+
import com.campspot.jdbi3.DAOManager
5+
import com.campspot.jdbi3.TransactionApplicationListener
46
import com.campspot.lib.MockableObject
57
import com.campspot.lib.PunchLib
6-
import com.campspot.middleware.CharsetResponseFilter
8+
import com.campspot.middleware.charset.CharsetResponseFilter
79
import com.campspot.resources.PunchResource
10+
import com.fasterxml.jackson.annotation.JsonCreator
811
import com.fasterxml.jackson.module.kotlin.KotlinModule
12+
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule
913
import com.github.arteam.jdbi3.JdbiFactory
1014
import io.dropwizard.Application
1115
import io.dropwizard.assets.AssetsBundle
@@ -43,6 +47,7 @@ class TimeTrackingApplication : Application<TimeTrackingConfiguration>() {
4347

4448
val objectMapper = environment.objectMapper
4549
objectMapper.registerModule(KotlinModule())
50+
objectMapper.registerModule(ParameterNamesModule(JsonCreator.Mode.PROPERTIES))
4651
objectMapper.configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
4752
objectMapper.setTimeZone(utc)
4853

@@ -52,11 +57,14 @@ class TimeTrackingApplication : Application<TimeTrackingConfiguration>() {
5257
jdbi.installPlugin(KotlinSqlObjectPlugin())
5358
TimeZone.setDefault(DateTimeZone.UTC.toTimeZone())
5459

55-
environment.jersey().register(CharsetResponseFilter())
60+
val daoManager = DAOManager(PunchDAO::class)
61+
val punchLib = PunchLib(daoManager, MockableObject())
5662

57-
val punchDAO = jdbi.onDemand<PunchDAO>(PunchDAO::class.java)
63+
val transactionApplicationListener = TransactionApplicationListener(daoManager)
64+
transactionApplicationListener.registerDbi(TimeTrackingApplication.MASTER, jdbi)
65+
environment.jersey().register(transactionApplicationListener)
5866

59-
val punchLib = PunchLib(punchDAO, MockableObject())
67+
environment.jersey().register(CharsetResponseFilter())
6068

6169
environment.jersey().register(PunchResource(punchLib))
6270
}
@@ -66,5 +74,7 @@ class TimeTrackingApplication : Application<TimeTrackingConfiguration>() {
6674
@JvmStatic fun main(args: Array<String>) {
6775
TimeTrackingApplication().run(*args)
6876
}
77+
78+
const val MASTER = "master"
6979
}
7080
}

src/main/kotlin/com/campspot/api/Punch.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ data class Punch(
77
val start: ZonedDateTime,
88
val end: ZonedDateTime,
99
val category: String,
10-
val description: String
10+
val description: String,
11+
var isPaid: Boolean
1112
)

src/main/kotlin/com/campspot/dao/PunchDAO.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package com.campspot.dao
22

33
import com.campspot.api.Punch
4+
import com.campspot.jdbi3.DAO
45
import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys
56
import org.jdbi.v3.sqlobject.statement.SqlQuery
67
import org.jdbi.v3.sqlobject.statement.SqlUpdate
78
import java.time.ZonedDateTime
89

9-
interface PunchDAO {
10+
interface PunchDAO: DAO {
1011
@SqlUpdate("INSERT INTO Punch (start, end, category, description) VALUES (:punch.start, :punch.end, :punch.category, :punch.description)")
1112
@GetGeneratedKeys
1213
fun create(punch: Punch): Long

src/main/kotlin/com/campspot/lib/PunchLib.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@ import com.campspot.api.Punch
44
import com.campspot.dao.PunchDAO
55
import com.campspot.exceptions.EntityNotFoundException
66
import com.campspot.exceptions.PunchCannotOverlapException
7+
import com.campspot.jdbi3.DAOManager
78
import java.time.ZonedDateTime
89

910
class PunchLib(
10-
private val punchDAO: PunchDAO,
11+
private val daoManager: DAOManager,
1112
private val mockableObject: MockableObject
1213
) {
1314
fun create(punch: Punch): Punch {
15+
val punchDAO = daoManager[PunchDAO::class]
1416
validatePunchDoesNotOverlap(punch)
1517

1618
val id = punchDAO.create(punch)
1719
return punchDAO.findById(id)
1820
}
1921

2022
fun update(punch: Punch): Punch {
23+
val punchDAO = daoManager[PunchDAO::class]
2124
validatePunchDoesNotOverlap(punch)
2225

2326
if (punch.id == null) {
@@ -29,10 +32,12 @@ class PunchLib(
2932
}
3033

3134
fun listForDates(start: ZonedDateTime, end: ZonedDateTime): List<Punch> {
35+
val punchDAO = daoManager[PunchDAO::class]
3236
return punchDAO.findAllInDateRange(start, end)
3337
}
3438

3539
fun somethingForTesting(category: String): String {
40+
val punchDAO = daoManager[PunchDAO::class]
3641
val firstForCategory = punchDAO.findFirstForCategory(category)
3742

3843
return firstForCategory.description
@@ -43,6 +48,7 @@ class PunchLib(
4348
}
4449

4550
private fun validatePunchDoesNotOverlap(punch: Punch) {
51+
val punchDAO = daoManager[PunchDAO::class]
4652
if (punchDAO.anyInRange(punch.start, punch.end)) {
4753
throw PunchCannotOverlapException()
4854
}

src/main/kotlin/com/campspot/middleware/CharsetResponseFilter.kt src/main/kotlin/com/campspot/middleware/charset/CharsetResponseFilter.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.campspot.middleware
1+
package com.campspot.middleware.charset
22

33
import javax.ws.rs.container.ContainerRequestContext
44
import javax.ws.rs.container.ContainerResponseContext

src/main/kotlin/com/campspot/resources/PunchResource.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package com.campspot.resources
22

3+
import com.campspot.TimeTrackingApplication.Companion.MASTER
34
import com.campspot.api.Punch
5+
import com.campspot.jdbi3.InTransaction
46
import com.campspot.lib.PunchLib
57
import com.codahale.metrics.annotation.Timed
68
import io.dropwizard.jersey.jsr310.ZonedDateTimeParam
79
import org.hibernate.validator.valuehandling.UnwrapValidatedValue
8-
import org.jdbi.v3.core.transaction.TransactionIsolationLevel
9-
import org.jdbi.v3.sqlobject.transaction.Transaction
1010
import javax.validation.Valid
1111
import javax.validation.constraints.NotNull
1212
import javax.ws.rs.*
@@ -20,23 +20,23 @@ class PunchResource(private val punchLib: PunchLib) {
2020
@POST
2121
@Timed
2222
@Valid
23-
@Transaction(TransactionIsolationLevel.READ_COMMITTED)
23+
@InTransaction(name = MASTER)
2424
fun create(@Valid @NotNull punch: Punch): Punch {
2525
return punchLib.create(punch)
2626
}
2727

2828
@PUT
2929
@Timed
3030
@Valid
31-
@Transaction(TransactionIsolationLevel.READ_COMMITTED)
31+
@InTransaction(name = MASTER)
3232
fun update(@Valid @NotNull punch: Punch): Punch {
3333
return punchLib.update(punch)
3434
}
3535

3636
@GET
3737
@Timed
3838
@Valid
39-
@Transaction(TransactionIsolationLevel.READ_COMMITTED, readOnly = true)
39+
@InTransaction(name = MASTER)
4040
fun list(
4141
@NotNull @UnwrapValidatedValue @QueryParam("start") start: ZonedDateTimeParam,
4242
@NotNull @UnwrapValidatedValue @QueryParam("end") end: ZonedDateTimeParam

src/main/resources/migrations.xml

+6
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,10 @@
2828
<column name="end"/>
2929
</createIndex>
3030
</changeSet>
31+
32+
<changeSet id="2" author="Al Scott">
33+
<addColumn tableName="Punch">
34+
<column name="isPaid" type="boolean"/>
35+
</addColumn>
36+
</changeSet>
3137
</databaseChangeLog>

src/test/kotlin/com/campspot/api/PunchTest.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ class PunchTest {
88
start = ZonedDateTime.parse("2016-10-05T06:45:00Z[UTC]"),
99
end = ZonedDateTime.parse("2016-10-05T07:30:00Z[UTC]"),
1010
category = "Activities",
11-
description = "Party rocking"
11+
description = "Party rocking",
12+
isPaid = true
1213
)
1314

1415
@Test

src/test/kotlin/com/campspot/dao/PunchDAOTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class PunchDAOTest : DAOTest() {
1818
.plusDays(5)
1919
.withHour(11)
2020
val end = start.plusMinutes(30)
21-
val punch = Punch(start = start, end = end, category = "", description = "")
21+
val punch = Punch(start = start, end = end, category = "", description = "", isPaid = true)
2222

2323
punchDAO.create(punch)
2424

src/test/kotlin/com/campspot/lib/PunchLibTest.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@ import com.campspot.api.Punch
55
import com.campspot.dao.PunchDAO
66
import com.campspot.exceptions.EntityNotFoundException
77
import com.campspot.exceptions.PunchCannotOverlapException
8+
import com.campspot.jdbi3.test.TestDAOManager
89
import org.assertj.core.api.Assertions.assertThat
910
import org.junit.Test
1011
import org.mockito.Mockito.*
1112
import java.time.ZonedDateTime
1213

1314
class PunchLibTest {
14-
val punchDAO = mock(PunchDAO::class.java)
1515
val mockableObject = mock(MockableObject::class.java)
16-
val subject = PunchLib(punchDAO, mockableObject)
16+
val daoManager = TestDAOManager()
17+
val subject = PunchLib(daoManager, mockableObject)
18+
val punchDAO = daoManager[PunchDAO::class]
1719

1820
val start = ZonedDateTime.now()
1921
val end = ZonedDateTime.now().plusMinutes(30)
20-
val basicPunch = Punch(start = start, end = end, category = "", description = "")
22+
val basicPunch = Punch(start = start, end = end, category = "", description = "", isPaid = true)
2123

2224
@Test(expected = PunchCannotOverlapException::class)
2325
fun create_ThrowsErrorIfPunchOverlaps() {

src/test/kotlin/integration/PunchResourceTest.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class PunchResourceTest : IntegrationTest() {
1717
.withHour(11)
1818
.withMinute(15)
1919
val end = start.withMinute(45)
20-
val punch = Punch(start = start, end = end, category = "Stuff", description = "Very important, pay me extra")
20+
val punch = Punch(start = start, end = end, category = "Stuff", description = "Very important, pay me extra", isPaid = true)
2121

2222
val createdPunch = apiClient!!.createPunch(punch).get()
2323

@@ -41,7 +41,7 @@ class PunchResourceTest : IntegrationTest() {
4141
val end = start.withMinute(45)
4242
val category = "Stuff"
4343
val description = "Very important, pay me extra"
44-
val punch = Punch(id = id, start = start, end = end, category = category, description = description)
44+
val punch = Punch(id = id, start = start, end = end, category = category, description = description, isPaid = false)
4545

4646
val handle = jdbi!!.open()
4747
handle.execute("INSERT INTO PUNCH (id, start, end, category, description) VALUES (?, ?, ?, ?, ?)", id, start, end, category, description)
@@ -72,7 +72,7 @@ class PunchResourceTest : IntegrationTest() {
7272
.plusDays(5)
7373
val rangeEnd = rangeStart.plusDays(5)
7474

75-
val basePunch = Punch(id = 0, start = rangeStart, end = rangeEnd, category = "", description = "")
75+
val basePunch = Punch(id = 0, start = rangeStart, end = rangeEnd, category = "", description = "", isPaid = true)
7676

7777
val beforeStartNoOverlap = basePunch.copy(id = 1, start = rangeStart.minusDays(5), end = rangeStart.minusDays(3))
7878
val beforeStartTillExactlyStart = basePunch.copy(id = 2, start = rangeStart.minusDays(5), end = rangeStart)

src/test/resources/fixtures/punch.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"start": "2016-10-05T06:45:00Z",
33
"end": "2016-10-05T07:30:00Z",
44
"category": "Activities",
5-
"description": "Party rocking"
5+
"description": "Party rocking",
6+
"isPaid": true
67
}

0 commit comments

Comments
 (0)