DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

How does AI transform chaos engineering from an experiment into a critical capability? Learn how to effectively operationalize the chaos.

Data quality isn't just a technical issue: It impacts an organization's compliance, operational efficiency, and customer satisfaction.

Are you a front-end or full-stack developer frustrated by front-end distractions? Learn to move forward with tooling and clear boundaries.

Developer Experience: Demand to support engineering teams has risen, and there is a shift from traditional DevOps to workflow improvements.

Related

  • Spring Data: Data Auditing Using JaVers and MongoDB
  • Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 4)
  • Develop a Secure CRUD Application Using Angular and Spring Boot
  • Testcontainers With Kotlin and Spring Data R2DBC

Trending

  • Beyond Automation: How Artificial Intelligence Is Transforming Software Development
  • How to Install and Set Up Jenkins With Docker Compose
  • Apache Doris and DeepSeek: Redefining Intelligent Data Analytics
  • How Docker Desktop Enhances Developer Workflows and Observability
  1. DZone
  2. Data Engineering
  3. Databases
  4. A Geospatial Messenger With Kotlin, Spring Boot and PostgreSQL

A Geospatial Messenger With Kotlin, Spring Boot and PostgreSQL

Sebastien Deleuze brings use through a sample application using some essential technologies and written in Kotlin.

By 
Pieter Humphrey user avatar
Pieter Humphrey
DZone Core CORE ·
Mar. 29, 16 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
11.0K Views

Join the DZone community and get the full member experience.

Join For Free

Following my first Kotlin blog post, today I want introduce the new Spring Boot + Kotlin application I have developed for my next week talk “Developing Geospatial Web Services with Kotlin and Spring Boot” at Breizhcamp conference.

Dealing With Native Database Functionalities

One of the goal of this application is see how to take advantage of native database functionalities like we do in NoSQL world. Here we want to use Geospatial support provided by PostGIS, the spatial database extender for PostgreSQL.

This Geospatial Messenger sample application is available on GitHub in 2 flavors:
 - The master branch uses Exposed, a Kotlin SQL library with a typesafe API created by JetBrains. It could be compared to Query DSL SQL or jOOQ but provides an idiomatic Kotlin API and does not require code generation.
 - The spring-data-jdbc-repository branch is using spring-data-jdbc-repository, a community project that allows to use Spring Data PagingAndSortingRepository API with raw SQL queries without JPA. I am using this Jakub Jirutka fork which is an improved version of Tomasz Nurkiewicz original project.

A Spring Data JPA + Hibernate Spatial variant would be interesting, so feel free to contribute it with a PR ;-) Kotlin Query DSL support would be also nice but this is currently not supported (please comment on this issue if you are interested). In this blog post I will focus on the Exposed variant.

A Tour of Geospatial Messenger Code

Our domain model is described easily thanks to these 2 Kotlin data classes:

data class Message(
        var content: String,
        var author: String,
        var location: Point? = null,
        var id: Int? = null
)

data class User(
        var userName: String,
        var firstName: String,
        var lastName: String,
        var location: Point? = null
)

Exposed allows us to describe the structure of our tables with a type-safe SQL API quite handy to use (autocomplete, refactoring and error prone):

object Messages : Table() {
    val id = integer("id").autoIncrement().primaryKey()
    val content = text("content")
    val author = reference("author", Users.userName)
    val location = point("location").nullable()
}

object Users : Table() {
    val userName = text("user_name").primaryKey()
    val firstName = text("first_name")
    val lastName = text("last_name")
    val location = point("location").nullable()
}

It is interesting to notice that Exposed does not support natively PostGIS functionalities like geometry types or geospatial requests. That’s where Kotlin extensions shine, and allow with a few lines of code to add such support without requiring to use extended classes:

fun Table.point(name: String, srid: Int = 4326): Column<Point> = registerColumn(name, PointColumnType())

infix fun ExpressionWithColumnType<*>.within(box: PGbox2d) : Op<Boolean> = WithinOp(this, box)

Our repository is also quite short and very flexible, since it allows you to write any kind of SQL request even with complex WHERE clause with a type-safe SQL API. Currently we need to use db.transaction{ } wrapper which is not ideal, I have created Exposed issues #24 and #25 to be able to use regular Spring transaction management, feel free to add your +1 ;-)

@Repository
open class UserRepository @Autowired constructor(val db: Database) {

    open fun createTable() = db.transaction {
        create(Users)
    }

    open fun create(user: User) {
        db.transaction {
            Users.insert( map(user) )
        }
    }

    open fun updateLocation(u:String, l: Point) = db.transaction {
        location.srid = 4326
        Users.update({Users.userName eq u}) { it[Users.location] = l}
    }

    open fun findAll() = db.transaction {
        unmap(Users.selectAll())
    }

    open fun findByBoundingBox(box: PGbox2d) = db.transaction {
        unmap(Users.select { Users.location within box })
    }

    open fun deleteAll() = db.transaction {
        Users.deleteAll()
    }

    private fun map(u: User): Users.(UpdateBuilder<*>) -> Unit = {
        it[userName] = u.userName
        it[firstName] = u.firstName
        it[lastName] = u.lastName
        it[location] = u.location
    }

    private fun unmap(rows: SizedIterable<ResultRow>): List<User> =
        rows.map { User(
                it[Users.userName],
                it[Users.firstName],
                it[Users.lastName],
                it[Users.location])
        }
}

Controllers are also very concise and use Spring Framework 4.3 upcoming @GetMapping / @PostMapping annotations which are just method-specific shortcuts for @RequestMapping annotations:

@RestController
@RequestMapping("/user")
class UserController @Autowired constructor(val repo: UserRepository) {

    @PostMapping
    @ResponseStatus(CREATED)
    fun create(@RequestBody u: User) { repo.create(u) }

    @GetMapping
    fun list() = repo.findAll()

    @GetMapping("/bbox/{xMin},{yMin},{xMax},{yMax}")
    fun findByBoundingBox(@PathVariable xMin:Double,
                          @PathVariable yMin:Double,
                          @PathVariable xMax:Double,
                          @PathVariable yMax:Double)
            = repo.findByBoundingBox(
                        PGbox2d(Point(xMin, yMin), Point(xMax, yMax)))

    @PutMapping("/{userName}/location/{x},{y}")
    @ResponseStatus(NO_CONTENT)
    fun updateLocation(@PathVariable userName:String,
                       @PathVariable x: Double,
                       @PathVariable y: Double)
            = repo.updateLocation(userName, Point(x, y))
}

The client side is a pure HTML + Javascript application developed with OpenLayers mapping library (see index.html and map.js for more details) that geolocalizes you and creates geolocalized messages sent/received to/from other users thanks to Server-Sent Events.

Screenshot

And last but not least, the REST API is fully tested and documented thanks to the awesome Spring REST docs project, see MessageControllerTests and index.adoc for more details.

Conclusion

The main impression I had developing this application is that it was fun, efficient, with a high level of flexibility and safety provided by the SQL API and Kotlin null safety. The resulting Spring Boot application is a 18 MBytes self-contained executable jar with low memory consumption. Using Spring REST docs was also a pleasure, demonstrating again Kotlin nice Java interoperability.

The few pain points I have encountered (array annotation attributes, Java 8 Stream support), are planned to be fixed in Kotlin 1.1. Exposed library is still young and need to mature, but from my point of view this is promising.

And keep in mind that officially supported Spring Data projects works well with Kotlin as shown in the spring-boot-kotlin-demo project in my previous blog post.

If you happen to be in Barcelona mid May (never a bad time to be in Barcelona anyway!), don’t miss the chance to join the Spring I/O conference where I’ll be presenting on the latest and greatest in Spring Data in general. Also, the registration for SpringOne Platform (early August, Las Vegas) has opened recently, in case you want to benefit from early bird ticket pricing. The latter is also still open for talk proposals. So if you’re interested to give a talk about Spring or Pivotal-related technologies, feel free to submit!

Spring Framework Kotlin (programming language) Spring Boot Messenger (software) Spring Data Database PostgreSQL application

Published at DZone with permission of Pieter Humphrey, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Spring Data: Data Auditing Using JaVers and MongoDB
  • Best Performance Practices for Hibernate 5 and Spring Boot 2 (Part 4)
  • Develop a Secure CRUD Application Using Angular and Spring Boot
  • Testcontainers With Kotlin and Spring Data R2DBC

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: