From ff2e3abe0048e625d5497c47cb89153c4dc1eb5d Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Mon, 9 May 2016 23:07:35 +0200 Subject: [PATCH] Use interfaces + JDK dynamic proxies instead of CGLIB It allows to remove open keyword on repositories --- .../kotlin/io/spring/messenger/Application.kt | 4 ++++ .../messenger/repository/CrudRepository.kt | 13 ++++++++++++ ...ository.kt => DefaultMessageRepository.kt} | 20 +++++++++++++------ ...Repository.kt => DefaultUserRepository.kt} | 19 +++++++++++------- .../io/spring/messenger/web/UserController.kt | 1 - 5 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/io/spring/messenger/repository/CrudRepository.kt rename src/main/kotlin/io/spring/messenger/repository/{MessageRepository.kt => DefaultMessageRepository.kt} (57%) rename src/main/kotlin/io/spring/messenger/repository/{UserRepository.kt => DefaultUserRepository.kt} (62%) diff --git a/src/main/kotlin/io/spring/messenger/Application.kt b/src/main/kotlin/io/spring/messenger/Application.kt index 9989423..fd9793b 100644 --- a/src/main/kotlin/io/spring/messenger/Application.kt +++ b/src/main/kotlin/io/spring/messenger/Application.kt @@ -12,6 +12,7 @@ import org.springframework.boot.CommandLineRunner import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.context.annotation.Bean +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder import org.springframework.transaction.annotation.EnableTransactionManagement import javax.sql.DataSource @@ -30,6 +31,9 @@ open class Application { @Bean open fun transactionManager(dataSource: DataSource) = SpringTransactionManager(dataSource) + @Bean // PersistenceExceptionTranslationPostProcessor with proxyTargetClass=false, see https://github.com/spring-projects/spring-boot/issues/1844 + open fun persistenceExceptionTranslationPostProcessor() = PersistenceExceptionTranslationPostProcessor() + @Bean open fun init(ur: UserRepository, mr: MessageRepository) = CommandLineRunner { ur.createTable() diff --git a/src/main/kotlin/io/spring/messenger/repository/CrudRepository.kt b/src/main/kotlin/io/spring/messenger/repository/CrudRepository.kt new file mode 100644 index 0000000..b0ff286 --- /dev/null +++ b/src/main/kotlin/io/spring/messenger/repository/CrudRepository.kt @@ -0,0 +1,13 @@ +package io.spring.messenger.repository + +import org.postgis.PGbox2d +import org.postgis.Point + +interface CrudRepository { + fun createTable() + fun create(m: T): T + fun findAll(): Iterable + fun deleteAll(): Int + fun findByBoundingBox(box: PGbox2d): Iterable + fun updateLocation(userName:K, location: Point) +} diff --git a/src/main/kotlin/io/spring/messenger/repository/MessageRepository.kt b/src/main/kotlin/io/spring/messenger/repository/DefaultMessageRepository.kt similarity index 57% rename from src/main/kotlin/io/spring/messenger/repository/MessageRepository.kt rename to src/main/kotlin/io/spring/messenger/repository/DefaultMessageRepository.kt index bbbf826..3f9bed3 100644 --- a/src/main/kotlin/io/spring/messenger/repository/MessageRepository.kt +++ b/src/main/kotlin/io/spring/messenger/repository/DefaultMessageRepository.kt @@ -6,25 +6,33 @@ import io.spring.messenger.within import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.statements.UpdateBuilder import org.postgis.PGbox2d +import org.postgis.Point import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +interface MessageRepository: CrudRepository + @Repository @Transactional // Should be at @Service level in real applications -open class MessageRepository() { +class DefaultMessageRepository() : MessageRepository { - open fun createTable() = SchemaUtils.create(Messages) + override fun createTable() = SchemaUtils.create(Messages) - open fun create(m: Message): Message { + override fun create(m: Message): Message { m.id = Messages.insert(toRow(m)).get(Messages.id) return m } - open fun findAll() = Messages.selectAll().map { fromRow(it) } + override fun findAll() = Messages.selectAll().map { fromRow(it) } - open fun findByBoundingBox(box: PGbox2d) = Messages.select { Messages.location within box }.map { fromRow(it) } + override fun findByBoundingBox(box: PGbox2d) = Messages.select { Messages.location within box }.map { fromRow(it) } - open fun deleteAll() = Messages.deleteAll() + override fun updateLocation(id:Int, location: Point) { + location.srid = 4326 + Messages.update({ Messages.id eq id}) { it[Messages.location] = location} + } + + override fun deleteAll() = Messages.deleteAll() fun toRow(m: Message): Messages.(UpdateBuilder<*>) -> Unit = { if (m.id != null) it[id] = m.id diff --git a/src/main/kotlin/io/spring/messenger/repository/UserRepository.kt b/src/main/kotlin/io/spring/messenger/repository/DefaultUserRepository.kt similarity index 62% rename from src/main/kotlin/io/spring/messenger/repository/UserRepository.kt rename to src/main/kotlin/io/spring/messenger/repository/DefaultUserRepository.kt index a7b4d06..1e6eab8 100644 --- a/src/main/kotlin/io/spring/messenger/repository/UserRepository.kt +++ b/src/main/kotlin/io/spring/messenger/repository/DefaultUserRepository.kt @@ -10,24 +10,29 @@ import org.postgis.Point import org.springframework.stereotype.Repository import org.springframework.transaction.annotation.Transactional +interface UserRepository: CrudRepository + @Repository @Transactional // Should be at @Service level in real applications -open class UserRepository() { +class DefaultUserRepository() : UserRepository { - open fun createTable() = SchemaUtils.create(Users) + override fun createTable() = SchemaUtils.create(Users) - open fun create(user: User) = Users.insert( toRow(user) ) + override fun create(user: User): User { + Users.insert(toRow(user)) + return user + } - open fun updateLocation(userName:String, location: Point) = { + override fun updateLocation(userName:String, location: Point) { location.srid = 4326 Users.update({Users.userName eq userName}) { it[Users.location] = location} } - open fun findAll() = Users.selectAll().map { fromRow(it) } + override fun findAll() = Users.selectAll().map { fromRow(it) } - open fun findByBoundingBox(box: PGbox2d) = Users.select { Users.location within box }.map { fromRow(it) } + override fun findByBoundingBox(box: PGbox2d) = Users.select { Users.location within box }.map { fromRow(it) } - open fun deleteAll() = Users.deleteAll() + override fun deleteAll() = Users.deleteAll() fun toRow(u: User): Users.(UpdateBuilder<*>) -> Unit = { it[userName] = u.userName diff --git a/src/main/kotlin/io/spring/messenger/web/UserController.kt b/src/main/kotlin/io/spring/messenger/web/UserController.kt index 235b41f..e53db6f 100644 --- a/src/main/kotlin/io/spring/messenger/web/UserController.kt +++ b/src/main/kotlin/io/spring/messenger/web/UserController.kt @@ -5,7 +5,6 @@ import io.spring.messenger.repository.UserRepository import org.postgis.PGbox2d import org.postgis.Point import org.springframework.http.HttpStatus.* -import org.springframework.transaction.annotation.Transactional import org.springframework.web.bind.annotation.* @RestController