Announcing Krush – idiomatic persistence layer for Kotlin, based on Exposed

We’ve released a persistence library for Kotlin, you can find it on our Github. It’s a JPA-to-Exposed SQL DSL generator.

TL;DR

We’ve released a persistence library for Kotlin, you can find it on our Github. It’s a JPA-to-Exposed SQL DSL generator.

The state of persistence in Kotlin

One of the key decisions that helped Kotlin gain massive popularity was to reuse Java ecosystem instead of inventing it’s own. This means that you can safely use Kotlin as a primary language for a project developed using any popular Java stack like Spring Boot and built with Java build tool like Maven. What this also means is that natural choice for persistence layer in Kotlin is Spring Data with JPA 3 with Hibernate as an implementation.

However, JPA, which highly relies on mutable objects and dirty checking, may not look like pure Kotlin, which tries to embrace functional programming and immutability. The official Spring JPA guide for Kotlin uses mutable classes and properties which is not really idiomatic for Kotlin where you want to use immutable data classes whenever it’s possible.

There are some other options, which can be used safely with Kotlin and data classes, like Spring Data JDBC — interesting approach based on pure JDBC, embracing DDD and aggregate root concepts or Micronaut Data JDBC — if you’re not tied to Spring ecosystem. But they’re both relatively new, not mature yet and miss another idiomatic Kotlin feature — a DSL for making SQL queries.

DSL for SQL queries

Another thing that made Kotlin really powerful and popular is its ability to construct Domain Specific Languages using features like property reference, operators, infix and extension functions. For example, for Android development there is excellent anko library for constructing complex view layouts for Android apps. In Spring/JPA the default approach to SQL queries are query methods, where you use special naming convention of methods in repository interfaces. The method names are parsed at runtime to provide required SQL queries and mapping. The naming convention is supported by IntelliJ Idea and other IDEs and works well in simple cases, but may be not flexible enough when you want complex queries e.g. with some conditions based on dynamic filters. If you want to use a true, type-safe, composable and idiomatic Kotlin SQL DSL, you can try to use other libraries, like Requery or Exposed.

Requery

Requery is a lightweight persistence library for Java and Kotlin with RxJava and Java 8 streams support. It uses annotations (both custom and JPA) to process your entities and generate some infrastructure code called “model”.

So given a Book interface:

@Entity
@Table(name = "books")

interface Book : Persistable {
    @get:Key @get:Generated
    val id: Long

    val isbn: String
    val author: String
    val title: String

    val publishDate: LocalDate
}

 

You can instantiate and persist it by using generated BookEntity class:

//given
val book = BookEntity().apply {
    setIsbn("1449373321")
    setPublishDate(LocalDate.of(2017, Month.APRIL, 11))
    setTitle("Designing Data-Intensive Applications")
    setAutor("Martin Kleppmann")
}

// when
val persistedBook = dataStore.insert(book)

And the use SQL DSL to fetch data and map the results back to entities:

// then
val books = dataStore.select(Book::class).where(Book::id eq  book.id).get().toList()

assertThat(books).containsExactly(persistedBook)

This was really close to our needs! We like the idea of having annotations on the entities combined with the rich SQL DSL. Also the RxJava bindings and lazy Kotlin sequences support looks promising. On the other side, there are few minor issues related to immutable classes support:

  • immutable interface approach needs to be backed up with this generated, mutablexxxEntity class
  • there are some restrictions: e.g. you cannot use them to map relations to other entities (just foreign keys by ids)
  • @Generated also doesn’t work for ids in data classes.

You can check example project using Requery in requery branch of krush-example project on GitHub.

Exposed

Another approach which given you rich SQL DSL support is Exposed — a Kotlin-only persistence layer maintained by the JetBrains team. It comes in two flavors: active-record DAO and lightweight SQL DSL. As we are not the fans of active records, we tried the SQL DSL flavor. It works by creating additional mapping code using Kotlin objects and extension functions:

object  BookTable : Table("books") {
    val id: Column<Long> = long("id").promaryKey().autoIncrement()
    val isbn: Column<String> = varchar("isbn". 255)
    val autor: Column<String> = varchar("author". 255)
    val title: Column<String> = varchar("title". 255)
    val publishDate: Column<LocalDate> = date("publishDate")
}

Then you can refer to these Column properties to create type-safe queries and map results using Kotlin collections API:

val titles: List<String> = BookTable
        .select { BookTable.author like "Martin K%" }
        .map { it[BookTable.title] }

As you can see, Exposed is not a full-blown ORM — there is no direct mapping to/from your domain classes into these Table objects, but it’s not hard to write simple mapping functions for that. You can also benefit from Kotlin null-types support and write bindings for your own types by using Kotlin’s extension functions. We wrote some time ago this article about our approach to using Exposed in our projects.

Krush

We really like the Kotlin-first feeling combined with great flexibility of Exposed, but at some time we were tired of writing these table mappings manually. We thought that it would be nice to generate them from JPA-compatible annotations, in similar way it’s done in Requery. This ended with building a library called Krush, which we’re announcing today ;)

Krush consist of two components:

  • annotation-processor which generates Exposed mappings by reading (a subset of) standard JPA annotations found on entity classes
  • utility functions for persisting entities and mapping from/to Exposed objects

So given this entity:

@Entity
@Table(name = "books")

data class Book(
    @Id @GeneratedValue
    val id: Long? = null,

    val isbn: String,
    val author: String,
    val title: String,
    val publishDate: LocalDate
)

Krush will generate BookTable object which allows to persist it like this:

//given
val book = Book(
        isbn = "1449373321", publishDate = LocalDate.of(2017, Month.APRIL, 11),
        title = "Designing Data-Intensive Applications", author = "Martin Kleppmann"
)
val persistedBook = BookTable.insert(book)
assertThat(persistedBook.id).isNotNull()

And write queries using type-safe DSL just like you were using plain Exposed:

val bookId = book.id ?: throw IllegalargumentException( )
val fetchedBook = BookTable.select { BookTable.id eq bookId }.singleOrNull()?.toBook( )
assertThat(fetchedBook).isEqualTo(book)

val selectedBooks = BookTable
        .select { BookTable.author like "Martin Kx" }
        .toBookList()

assertThat(selectedBooks).containsOnly(book)

That’s it! You can find more details and supported features in the README of Krush repository or in some example projects.

Enjoy! Looking for feedback from the community!

You May Also Like

ODEO new release

Recently, I released a new version 1.1.34 of ODEO (it's ODE tuned for Oracle and ServiceMix).You can check details (and downloads) here: http://top.touk.pl/confluence/display/top/ODEO.This version contains yet another set of fixes, which drive your BPE...Recently, I released a new version 1.1.34 of ODEO (it's ODE tuned for Oracle and ServiceMix).You can check details (and downloads) here: http://top.touk.pl/confluence/display/top/ODEO.This version contains yet another set of fixes, which drive your BPE...

Thought static method can’t be easy to mock, stub nor track? Wrong!

No matter why, no matter is it a good idea. Sometimes one just wants to check or it's necessary to be done. Mock a static method, woot? Impossibru!

In pure Java world it is still a struggle. But Groovy allows you to do that really simple. Well, not groovy alone, but with a great support of Spock.

Lets move on straight to the example. To catch some context we have an abstract for the example needs. A marketing project with a set of offers. One to many.

import spock.lang.Specification

class OfferFacadeSpec extends Specification {

    OfferFacade facade = new OfferFacade()

    def setup() {
        GroovyMock(Project, global: true)
    }

    def 'delegates an add offer call to the domain with proper params'() {
        given:
            Map params = [projId: projectId, name: offerName]

        when:
            Offer returnedOffer = facade.add(params)

        then:
            1 * Project.addOffer(projectId, _) >> { projId, offer -> offer }
            returnedOffer.name == params.name

        where:
            projectId | offerName
            1         | 'an Offer'
            15        | 'whasup!?'
            123       | 'doskonała oferta - kup teraz!'
    }
}
So we test a facade responsible for handling "add offer to the project" call triggered  somewhere in a GUI.
We want to ensure that static method Project.addOffer(long, Offer) will receive correct params when java.util.Map with user form input comes to the facade.add(params).
This is unit test, so how Project.addOffer() works is out of scope. Thus we want to stub it.

The most important is a GroovyMock(Project, global: true) statement.
What it does is modifing Project class to behave like a Spock's mock. 
GroovyMock() itself is a method inherited from SpecificationThe global flag is necessary to enable mocking static methods.
However when one comes to the need of mocking static method, author of Spock Framework advice to consider redesigning of implementation. It's not a bad advice, I must say.

Another important thing are assertions at then: block. First one checks an interaction, if the Project.addOffer() method was called exactly once, with a 1st argument equal to the projectId and some other param (we don't have an object instance yet to assert anything about it).
Right shit operator leads us to the stub which replaces original method implementation by such statement.
As a good stub it does nothing. The original method definition has return type Offer. The stub needs to do the same. So an offer passed as the 2nd argument is just returned.
Thanks to this we can assert about name property if it's equal with the value from params. If no return was designed the name could be checked inside the stub Closure, prefixed with an assert keyword.

Worth of  mentioning is that if you want to track interactions of original static method implementation without replacing it, then you should try using GroovySpy instead of GroovyMock.

Unfortunately static methods declared at Java object can't be treated in such ways. Though regular mocks and whole goodness of Spock can be used to test pure Java code, which is awesome anyway :)No matter why, no matter is it a good idea. Sometimes one just wants to check or it's necessary to be done. Mock a static method, woot? Impossibru!

In pure Java world it is still a struggle. But Groovy allows you to do that really simple. Well, not groovy alone, but with a great support of Spock.

Lets move on straight to the example. To catch some context we have an abstract for the example needs. A marketing project with a set of offers. One to many.

import spock.lang.Specification

class OfferFacadeSpec extends Specification {

    OfferFacade facade = new OfferFacade()

    def setup() {
        GroovyMock(Project, global: true)
    }

    def 'delegates an add offer call to the domain with proper params'() {
        given:
            Map params = [projId: projectId, name: offerName]

        when:
            Offer returnedOffer = facade.add(params)

        then:
            1 * Project.addOffer(projectId, _) >> { projId, offer -> offer }
            returnedOffer.name == params.name

        where:
            projectId | offerName
            1         | 'an Offer'
            15        | 'whasup!?'
            123       | 'doskonała oferta - kup teraz!'
    }
}
So we test a facade responsible for handling "add offer to the project" call triggered  somewhere in a GUI.
We want to ensure that static method Project.addOffer(long, Offer) will receive correct params when java.util.Map with user form input comes to the facade.add(params).
This is unit test, so how Project.addOffer() works is out of scope. Thus we want to stub it.

The most important is a GroovyMock(Project, global: true) statement.
What it does is modifing Project class to behave like a Spock's mock. 
GroovyMock() itself is a method inherited from SpecificationThe global flag is necessary to enable mocking static methods.
However when one comes to the need of mocking static method, author of Spock Framework advice to consider redesigning of implementation. It's not a bad advice, I must say.

Another important thing are assertions at then: block. First one checks an interaction, if the Project.addOffer() method was called exactly once, with a 1st argument equal to the projectId and some other param (we don't have an object instance yet to assert anything about it).
Right shit operator leads us to the stub which replaces original method implementation by such statement.
As a good stub it does nothing. The original method definition has return type Offer. The stub needs to do the same. So an offer passed as the 2nd argument is just returned.
Thanks to this we can assert about name property if it's equal with the value from params. If no return was designed the name could be checked inside the stub Closure, prefixed with an assert keyword.

Worth of  mentioning is that if you want to track interactions of original static method implementation without replacing it, then you should try using GroovySpy instead of GroovyMock.

Unfortunately static methods declared at Java object can't be treated in such ways. Though regular mocks and whole goodness of Spock can be used to test pure Java code, which is awesome anyway :)