Share your Gradle configuration with the Gradle Kotlin DSL — A guide for Android projects

Share your Gradle configuration with the Gradle Kotlin DSL — A guide for Android projects

This guide will help you to convert your Gradle build scripts from Groovy to Kotlin, allowing you to take advantage of some great benefits! These include:

  • Shareable Gradle configuration, minimizing the amount of duplicate code across your module build scripts
  • Shared dependency notation and versioning, making tasks like bumping dependency versions a breeze
  • Improved IDE support, enhancing features such as autocompletion, navigation to source, quick documentation, etc.

Step 1 – The buildSrc module

First, we will create a new directory at the root of our project named buildSrc. This is where all of our shared Gradle configuration, dependencies, versioning, etc. will live.

To make this directory a module we create a Kotlin build script at the root, so that the file path is {your_project}/buildSrc/build.gradle.kts

https://medium.com/media/96ca14688c6ebb508d27c60d7c2211b4/href

You should ensure that the versions used for com.android.tools.build:gradle and org.jetbrains.kotlin:kotlin-gradle-plugin match what you already have specified in your project build script ({your_project}/build.gradle) rather than using the versions in this example.

It’s also important to note the comments added to this file, it isn’t possible to utilise the shared versioning here so these dependencies will need to be updated manually.

Step 2 – Shared dependencies & versioning

It’s time to create the objects that will store our dependency notation and versioning, the process of moving all of your dependencies to these shared objects can be a bit painful depending on the number of dependencies your app uses.

Let’s start by creating the object that will hold our dependency notation. This should be created at {your_project}/buildSrc/src/main/kotlin/Dependencies.kt. I recommend going through your :app module’s build.gradle and copying any dependencies from there as a starting point.

I find it useful to group dependencies in nested objects as it increases readability, though you may structure this however you like. We can also group dependencies that are commonly included together using DependencyHandlerScope (you’ll see this in use later).

https://medium.com/media/15b390227cf6c356d7986d21b4b104e1/href

Now, let’s create the object that will house all of our versioning, create it alongside Dependencies at {your_project}/buildSrc/src/main/kotlin/Versions.kt.

As you can see, we’ve added all versions required by our dependencies, along with some versioning specific to our app in the nested App object.

https://medium.com/media/8cb1c4f7c663da91837c932d5080a7ff/href

I find it useful to also create a Modules object for storing module paths and a Plugins object for storing plugin identifiers to share even more values across build scripts!

https://medium.com/media/d199a3a76856389128c3b16c1ea457e6/hrefhttps://medium.com/media/b2a92abe9a4bc77069cec45e92d37a72/href

Step 3 – Converting app module build script to Kotlin

The steepest learning curve with the Gradle Kotlin DSL is the syntax. Below is an example Kotlin build script for the :app module which covers some common configuration, along with using our previously created Dependencies, Versions, Modules, and Plugins objects. If you have some complicated configuration that you’re struggling to convert, there are some links at the bottom of this guide to documentation that may help.

https://medium.com/media/138eceb26c5c19c2e79a2da1e778a20b/href

Step 4 – Shared module configuration

In my opinion, this is the greatest benefit of using the Gradle Kotlin DSL, the ability to easily share build script configuration across modules. First, let’s create a script that contains our shared configuration.

{your_project}/buildSrc/src/main/kotlin/common.gradle.kts

https://medium.com/media/22c734d091bf1ef32557b5c30df04bc9/href

Now we can utilise this to make module build scripts pithy by including common as a plugin!

https://medium.com/media/0071d30d46131f23961ce755fdb66679/href

Now you can go through each of your module build scripts and convert them to Kotlin, all whilst moving any dependencies, module paths, plugin identifiers, and versioning to the objects we created in step 2 so that they can be shared; allowing for easy alterations/updates in the future.

Step 5 – Converting project build script and settings.gradle to Kotlin

The final step is to convert your top-level (project) build.gradle and settings.gradle to Kotlin. This should be fairly straightforward as they won’t contain many configurations.

https://medium.com/media/2e4d9c296dd0a695da0a3c7a21354b15/hrefhttps://medium.com/media/f13cbe8ceeac3b56d8fb17772370041f/href

Fin

That’s it! 🎉 I hope this guide was useful and that you enjoy your new Gradle setup. All example code shown can be viewed in the example project linked below 🙂

MichaelM97/Gradle-Kotlin-DSL-Android-Example

Useful resources

Click 👏 to say “thanks!” and help others find this article.

To be up-to-date with great news on Kt. Academy, subscribe to the newsletter, observe Twitter and follow us on Medium.

If you need a Kotlin workshop, check how we can help you: kt.academy.


Share your Gradle configuration with the Gradle Kotlin DSL — A guide for Android projects was originally published in Kt. Academy on Medium, where people are continuing the conversation by highlighting and responding to this story.

Continue ReadingShare your Gradle configuration with the Gradle Kotlin DSL — A guide for Android projects

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

Hibernate with Kotlin – powered by Spring Boot

In this post, I’d like to demonstrate what you need to consider when using Hibernate with Kotlin. Hibernate is probably the most famous framework for object-relational mapping (ORM) on the JVM, which is used to persistently store Plain Old Java Objects (POJOs) in relational databases. It also implements the Java Persistence API, a specification that “describes the management of relational data” on the JVM.

Summary (TL;DR)

  • Put the kotlin-noarg compiler plugin on your build path, it will generate no-argument constructors for your Hibernate entities.
    • In Gradle, add the following to your buildscript dependencies: classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    • Further examples can be found here
  • Enable the kotlin-jpa plugin, which works on top of kotlin-noarg by enabling the no-arg generation for Hibernate annotated classes
    • In Gradle, activate the plugin like this: apply plugin: "kotlin-jpa"
    • Further examples can be found here
  • Put the kotlin-allopen compiler plugin on your build path, and configure it to open classes with entity annotations as Hibernate should not be used with final classes
    • In Gradle, add the following to your buildscript dependencies: classpath "org.jetbrains.kotlin:kotlin-allopen:${versions.kotlin}" and add the following configuration:
    allOpen {
        annotation("javax.persistence.Entity")
        annotation("javax.persistence.MappedSuperclass")
        annotation("javax.persistence.Embeddable")
    } 
    
    • Further examples can be found here
  • Abstract your hashCode/equals implementations in an abstract base class and define entities as ordinary classes inheriting from the abstract base class
    • Do not use data classes to define your @Entity classes – JPA doesn’t work well with the generated equals/hashCode functions.

Hibernate Entity Type

The most important thing we need to do when integrating Hibernate into an application is defining the entity types we want to persist, i.e. defining the mappings between tables and classes. The Hibernate documentation describes an “Entity” as follows:

The entity type describes the mapping between the actual persistable domain model object and a database table row. To avoid any confusion with the annotation that marks a given entity type, the annotation will be further referred as @Entity.

Let’s see how valid entity classes need to look like.

Hibernate Requirements for Entity classes

Hibernate imposes certain requirements on a valid Entity type: An entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider)
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended)
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types
  • … needs to provide useful implementations for equals and hashCode (Why? find information here)

If we think about which kind of class in Kotlin best suits these requirements, one might say data classes did. As it turns out though, this is probably not the best solution as discussed in the following.

The equals/hashCode dilemma: Don’t use data classes as Hibernate entities

It seems to be a good idea to use data classes for defining our Hibernate entities: They basically just need a concise primary constructor with annotated parameters, provide neat things like hashCode, equals, copy, toString out of the box and may be immutable (actually they can’t be for Hibernate).

There’s a problem though: We need to be very careful with auto-generated equals/hashCode functions when working with Hibernate, especially because the entity identifier may be set after the object has been constructed. Actually, using auto-generated IDs means that our classes can never be immutable. Consider the following scenario:

  1. Create an object of your entity Person
  2. Put this object into a HashSet
  3. Persist object via Hibernate (this leads to a generated and updated Person::id and thus changes its hashCode)
  4. Test if the object still exists in the HashSet will yield false since the hash code changed

This dilemma could be fixed by using natural keys (aka business keys) instead, i.e. we’d need to find a combination of properties that clearly identify an entity. For a person, this could be their name and address, which still might be insufficient. We don’t have natural keys for every entity actually. Also, it’s a bit cumbersome to implement such behavior with data classes since we’d have to put the natural key parts into the primary constructor and everything else in the class body, the caller would have to set properties after construction. This does not feel right, so let’s not do it…

Hibernate Suggestion

What the Hibernate documentation suggests:

Although using a natural-id is best for equals and hashCode, sometimes you only have the entity identifier that provides a unique constraint. It’s possible to use the entity identifier for equality check, but it needs a workaround:
– you need to provide a constant value for hashCode so that the hash code value does not change before and after the entity is flushed.
– you need to compare the entity identifier equality only for non-transient entities.

They say that we can use the Hibernate-generated ID for equality checks as long as we provide a “constant value” for hashCode. This is because, reviewing the example scenario from earlier, the hash code should not change for an object once it’s been put into hash-based collections. Using a constant value for hashCode fixes this and still is a valid implementation according to its contract (taken from Oracle JavaDocs):

hashCode Contract

The general contract of hashCode is:
– Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
– If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
– It is not required that if two objects are unequal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

So this is all good although we need to take a closer look at the last sentence of this contract:

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables

hashCode Performance Implications

If we decide to yield constant values from hashCode for any object of a class, performance will suffer. You cannot expect hash collections to work as efficient as with properly distributed hash codes:

This implementation [HashMap] provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

If you can work around these performance implications, you should be fine to follow the described approach. For us, this isn’t considered problematic.

As a result, we want to let our entities’ equals be based on their identifier and provide a constant value for hashCode. Also, since data classes do not seem to be an adequate solution, we’ll be using ordinary, more flexible, classes.

Implementing Hibernate Entities with Kotlin

As a starter, it feels appropriate to provide a generic base class for our entities that defines an auto-generated identifier and, based on that, implements equals and the constant hashCode:


@MappedSuperclass abstract class AbstractJpaPersistable<T : Serializable> { companion object { private val serialVersionUID = -5554308939380869754L } @Id @GeneratedValue private var id: T? = null override fun getId(): T? { return id } override fun equals(other: Any?): Boolean { other ?: return false if (this === other) return true if (javaClass != ProxyUtils.getUserClass(other)) return false other as AbstractJpaPersistable<*> return if (null == this.getId()) false else this.getId() == other.getId() } override fun hashCode(): Int { return 31 } override fun toString() = "Entity of type ${this.javaClass.name} with id: $id" }

The class AbstractJpaPersistable is pretty straightforward: It defines a generic nullable @Id property, which is going to be auto-generated by Hibernate. The equals and hashCode look like discussed earlier. Now we can create our entities based on that class:

@Entity
class Person(
    val name: String,
    @OneToOne(cascade = [(CascadeType.ALL)], orphanRemoval = true, fetch = FetchType.EAGER)
    val address: Address
) : AbstractJpaPersistable<Long>()

@Entity
class Address(
    val street: String,
    val zipCode: String,
    val city: String
) : AbstractJpaPersistable<Long>()

We can see two rather simple entities: A Person which has an associated Address. Both @Entity classes extend AbstractJpaPersistable<Long> and therefore rely on an auto-generated id of type Long.

Reviewing the entity requirements

As depicted earlier, we have a few requirements for entities that need to be considered. Let’s review what the approach from above already takes care of:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ❌
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ❌
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept to not have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

We still have two things to fix:
1. Kotlin classes are final by default, which is good practice in most cases but Hibernate does not really like that. Since it makes use of proxies that allow e.g. lazy-loading of entities, classes should not be final if possible.
2. We did not provide a no-argument constructor so far.

The following will take care of both problems.

Writing a sample application

Setup

Now that we know how to abstract Hibernate entities properly, let’s write a sample application and see if there are more things to consider. We’ll use a Spring Boot base for our application which can easily be generated via start.spring.io:

start.spring.io
start.spring.io

(If you like to find out more about Spring and its fantastic Kotlin support, I encourage you to read this blog post as well.)

Fixing remaining Entity requirements

As discussed earlier, Hibernate expects a no-argument constructor defined for its entities. Since we don’t want to provide one at compile time, we use a compiler plugin by JetBrains called kotlin-noarg, which “generates an additional zero-argument constructor for classes with a specific annotation. The generated constructor is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.”

In addition, we need to tell the tool which annotations it should apply the no-arg constructor rule on. This can be done manually or by adding the plugin kotlin-jpa to our build, which is “wrapped on top of no-arg. The plugin specifies @Entity, @Embeddable and @MappedSuperclass no-arg annotations automatically.”

Also, taking care of the final classes problem, we configure the kotlin-allopen plugin to remove the final modifier from all compiled entity classes.

The Gradle build file

Altogether, the build script looks like this (Gradle Groovy DSL):

buildscript {
    ext {
        kotlinVersion = '1.2.60'
        springBootVersion = '2.0.4.RELEASE'
        h2 = '1.4.196'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:${kotlinVersion}")
    }
}

apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: "kotlin-jpa"

group = 'com.kotlinexpertise'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

allOpen {
    annotation("javax.persistence.Entity")
    annotation("javax.persistence.MappedSuperclass")
    annotation("javax.persistence.Embeddable")
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    compile("org.jetbrains.kotlin:kotlin-reflect")
    // Database Drivers
    compile("com.h2database:h2:$h2")

    //Jackson Kotlin
    compile('com.fasterxml.jackson.module:jackson-module-kotlin')

    //Junit 5
    testCompile('org.springframework.boot:spring-boot-starter-test') {
        exclude module: 'junit'
    }
    testImplementation('org.junit.jupiter:junit-jupiter-api')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine')

    testCompile('org.springframework.boot:spring-boot-starter-test')

}

We can also see some additional dependencies for Jackson, Junit5 (Jupiter) and an in-memory H2 database.

This results in a neat setup with valid Hibernate entities:

The Entity…

  • … must be annotated with the javax.persistence.Entity annotation (or be denoted as such in XML mapping, which we won’t consider) ✔️
  • … must have a public or protected (or package-private) no-argument constructor. It may define additional constructors as well ✔️
  • … should not be final. No methods or persistent instance variables of the entity class may be final (technically possible but not recommended) ✔️
  • … may extend non-entity classes as well as entity classes, and non-entity classes may extend entity classes. Both abstract and concrete classes can be entities ✔️
  • … may provide JavaBean-style properties. This is not a must, i.e. setters are not necessary ✔️ (We accept not to have setters)
  • … must provide an identifier attribute (@Id annotation), recommended to use nullable, non-primitive, types ✔️
  • … needs to provide useful implementations for equals and hashCode ✔️

A simple repository

Thanks to Spring, the implementation for a repository that exposes Person entities is quite easy:

interface PersonRepository : JpaRepository<Person, Long> {
    fun getByAddressStreet(street: String): Person?
}

The interface org.springframework.data.jpa.repository.JpaRepository defines common CRUD operations and we add custom ones by extending the interface with PersonRepository. You can find out more about this mechanism here. As you might guess, the implementation of such an abstract repository definition happens via Spring.
You could now go on and inject this repository into controllers and expose a CRUD API to users. For simplicity, observe the following test case:

@ExtendWith(SpringExtension::class)
@SpringBootTest
class HibernateDemoApplicationTests(@Autowired val repo: PersonRepository) {

    @Test
    fun `basic entity checks`() {
        val p = Person("Paul", Address("HelloStreet", "A-55", "Paris"))
        val hashCodeBefore = p.hashCode()
        val personSet = hashSetOf(p)
        repo.save(p)
        val hashCodeAfter = p.hashCode()
        assertThat(repo.findAll()).hasSize(1)
        assertThat(personSet).contains(p)
        assertThat(hashCodeAfter).isEqualTo(hashCodeBefore)
    }
}

This test runs on JUnit 5, which allows constructor injection for certain objects. The used SpringExtension adds support for autowired dependencies and, as a result, we can inject the PersonRepository into the test class.
In the test case itself, we create a sample Person object, persist it by using the repository and then verify that it can be found via findAll. Assertions are based on org.assertj.
In addition, the test verifies that the hashCode for a Person does not change after it got persisted through Hibernate and that a HashSet works properly with these entities.

Further Hibernate Topics

In this article, we focused mainly on defining Hibernate entity classes since this task is probably the most vital one to do. We saw that a few constraints need to be fulfilled and that compiler plugins help us with integrating Hibernate with Kotlin. All of the demonstrated stuff is just a tiny set of Hibernate. Thanks to Spring though, many things like querying and transaction handling can easily be abstracted, which we made use of here. If you have doubts, I suggest to read “How Hibernate Almost Ruined my Career” very carefully – Hibernate can cause many headaches obviously ;-).

The source code can be found in my hibernateOnKotlin repository on GitHub.

Please don’t hesitate to reach out if you use different best practices in your applications.
Also, if you like, have a look at my Twitter account and other Kotlin related posts on this page and follow if you’re interested in more Kotlin stuff 🙂

Thanks a lot.

The post Hibernate with Kotlin – powered by Spring Boot appeared first on Kotlin Expertise Blog.

Continue ReadingHibernate with Kotlin – powered by Spring Boot

Execute Kotlin Scripts with Gradle

Organize Kotlin Scripts as Gradle tasks

In this article, you will learn how you can organize multiple Kotlin scripts as Gradle tasks and make them easily executable this way. I’ve found a discussion about this here. Somebody wanted to execute Kotlin scripts with Gradle build scripts which is, of course, possible by using kotlinc as shown in this (Groovy) build script. This doesn’t look very pretty though, and, as described in the corresponding thread, isn’t very performant and manageable. Another solution would be to use Gradle scripts written with the Kotlin DSL and define custom tasks within a build.gradle.kts file, which obviously can hold and run Kotlin code naturally:

// build.gradle.kts
//
// Execute Kotlin task with:  gradle  -q foo

task("foo") {
  group = "com.kotlinexpertise"
  description = "my foo task"
  doLast {
    println("Hello from foo task")
  }
}

The problem with this approach is that, in my case, I had multiple large Kotlin scripts I wanted to make executable this way. If I had put all of them into tasks, the script would have been too bloated and hard to maintain. Note that in my case, these tasks would not contribute to the build logic directly but rather provide business-relevant tasks, which I wanted to make executable via Gradle.

Gradle buildSrc to the rescue

As described in the Gradle documentation, build logic and especially custom tasks shouldn’t live within the build script directly. Gradle, therefore, offers the possibility to use a so-called buildSrc directory. This directory is treated as an included build, i.e. Gradle automatically compiles and tests this code and makes it available on the build script classpath. The following shows a typical project structure using this special buildSrc directory:

├── build.gradle //main build
├── buildSrc
│   ├── build.gradle //build for buildSrc
│   └── src //custom plugins, taks etc.
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── enterprise
│       │               ├── Deploy.java
│       │               └── DeploymentPlugin.java
│       └── test
│           └── java
│               └── com
│                   └── enterprise
│                       └── DeploymentPluginTest.java
└── settings.gradle

As you can see here, the buildSrc has its own build.gradle, in which we define dependencies and plugins for buildSrc itself. As mentioned, the compiled code will be available for the surrounding build so that you can for instance define custom tasks in the buildSrc and use them in the main build.gradle.

A Kotlin example: Execute Kotlin Scripts with Gradle

Let’s say we have two bigger tasks we want to make available as Gradle tasks, which we call task1 and task2. Both tasks are good fits to be implemented with Kotlin.

The original project build looks like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.2.51"
}

java.sourceSets {
    getByName("main").java.srcDirs("...")
}

repositories {
    mavenCentral()
}

dependencies {
    compile(kotlin("stdlib-jdk8"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

This is very basic and there’s nothing special in it. Now, the goal is to define two custom tasks taks1 and task2 within this script. Both tasks are supposed to be executable via gradle -q task1|task2. To make this possible, we create the buildSrc directory structure as shown above on the same level the build script already exists. Within the buildSrc, we now create the custom tasks as Kotlin classes:

package com.kotlinexpertise.tasks

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.sql.DriverManager

open class Task1 : DefaultTask() {

    init {
        group = "com.kotlinexpertise"
        description = "task1"
    }

    @TaskAction
    fun run() {
        Class.forName("com.mysql.jdbc.Driver")
        //heavy task implementation
    }
}

Just like we would define a task within a Gradle build script directly, we define group, description and the task itself in a method annotated with TaskAction, which we call run. Learn more about custom tasks here. To make this a bit more interesting, we want to load a MySQL driver in this task, which requires us to make the corresponding dependency available for the buildSrc build. Let’s take a look at its build script (existing directly in buildSrc):

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

dependencies {
    compile("mysql:mysql-connector-java:5.1.24")
}

As mentioned, we add the dependencies we want to use within the buildSrc. Another thing to note is that the org.gradle.kotlin.kotlin-dsl plugin is applied to this build in order to set up the Kotlin compiler features and dependencies to match the ones shipped with Gradle. We used the nicer alias kotlin-dsl in this example.

Now, after defining both Task1 and Task2 as subclasses of DefaultTask, they can be used in the main build.gradle.kts script like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.kotlinexpertise.tasks.*

//...

task<Task1>("task1")
task<Task1>("task2")

//...

Note that both probably need to be imported as shown here. In the console, gradle tasks will list them, and you can execute them by running gradle -q task1 and gradle -q task2 respectively. You can also see the tasks listed in IntelliJ IDEA:

gradle_idea

The source code can be found here: https://github.com/s1monw1/gradle_buildSrc_kotlin

You may want to read another article of mine about the Gradle Kotlin DSL to get more information about the topic. Enjoy.

The post Execute Kotlin Scripts with Gradle appeared first on Kotlin Expertise Blog.

Continue ReadingExecute Kotlin Scripts with Gradle

Execute Kotlin Scripts with Gradle

Organize Kotlin Scripts as Gradle tasks

In this article, you will learn how you can organize multiple Kotlin scripts as Gradle tasks and make them easily executable this way. I’ve found a discussion about this here. Somebody wanted to execute Kotlin scripts with Gradle build scripts which is, of course, possible by using kotlinc as shown in this (Groovy) build script. This doesn’t look very pretty though, and, as described in the corresponding thread, isn’t very performant and manageable. Another solution would be to use Gradle scripts written with the Kotlin DSL and define custom tasks within a build.gradle.kts file, which obviously can hold and run Kotlin code naturally:

// build.gradle.kts
//
// Execute Kotlin task with:  gradle  -q foo

task("foo") {
  group = "com.kotlinexpertise"
  description = "my foo task"
  doLast {
    println("Hello from foo task")
  }
}

The problem with this approach is that, in my case, I had multiple large Kotlin scripts I wanted to make executable this way. If I had put all of them into tasks, the script would have been too bloated and hard to maintain. Note that in my case, these tasks would not contribute to the build logic directly but rather provide business-relevant tasks, which I wanted to make executable via Gradle.

Gradle buildSrc to the rescue

As described in the Gradle documentation, build logic and especially custom tasks shouldn’t live within the build script directly. Gradle, therefore, offers the possibility to use a so-called buildSrc directory. This directory is treated as an included build, i.e. Gradle automatically compiles and tests this code and makes it available on the build script classpath. The following shows a typical project structure using this special buildSrc directory:

├── build.gradle //main build
├── buildSrc
│   ├── build.gradle //build for buildSrc
│   └── src //custom plugins, taks etc.
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── enterprise
│       │               ├── Deploy.java
│       │               └── DeploymentPlugin.java
│       └── test
│           └── java
│               └── com
│                   └── enterprise
│                       └── DeploymentPluginTest.java
└── settings.gradle

As you can see here, the buildSrc has its own build.gradle, in which we define dependencies and plugins for buildSrc itself. As mentioned, the compiled code will be available for the surrounding build so that you can for instance define custom tasks in the buildSrc and use them in the main build.gradle.

A Kotlin example: Execute Kotlin Scripts with Gradle

Let’s say we have two bigger tasks we want to make available as Gradle tasks, which we call task1 and task2. Both tasks are good fits to be implemented with Kotlin.

The original project build looks like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.2.51"
}

java.sourceSets {
    getByName("main").java.srcDirs("...")
}

repositories {
    mavenCentral()
}

dependencies {
    compile(kotlin("stdlib-jdk8"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

This is very basic and there’s nothing special in it. Now, the goal is to define two custom tasks taks1 and task2 within this script. Both tasks are supposed to be executable via gradle -q task1|task2. To make this possible, we create the buildSrc directory structure as shown above on the same level the build script already exists. Within the buildSrc, we now create the custom tasks as Kotlin classes:

package com.kotlinexpertise.tasks

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.sql.DriverManager

open class Task1 : DefaultTask() {

    init {
        group = "com.kotlinexpertise"
        description = "task1"
    }

    @TaskAction
    fun run() {
        Class.forName("com.mysql.jdbc.Driver")
        //heavy task implementation
    }
}

Just like we would define a task within a Gradle build script directly, we define group, description and the task itself in a method annotated with TaskAction, which we call run. Learn more about custom tasks here. To make this a bit more interesting, we want to load a MySQL driver in this task, which requires us to make the corresponding dependency available for the buildSrc build. Let’s take a look at its build script (existing directly in buildSrc):

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

dependencies {
    compile("mysql:mysql-connector-java:5.1.24")
}

As mentioned, we add the dependencies we want to use within the buildSrc. Another thing to note is that the org.gradle.kotlin.kotlin-dsl plugin is applied to this build in order to set up the Kotlin compiler features and dependencies to match the ones shipped with Gradle. We used the nicer alias kotlin-dsl in this example.

Now, after defining both Task1 and Task2 as subclasses of DefaultTask, they can be used in the main build.gradle.kts script like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.kotlinexpertise.tasks.*

//...

task<Task1>("task1")
task<Task1>("task2")

//...

Note that both probably need to be imported as shown here. In the console, gradle tasks will list them, and you can execute them by running gradle -q task1 and gradle -q task2 respectively. You can also see the tasks listed in IntelliJ IDEA:

gradle_idea

The source code can be found here: https://github.com/s1monw1/gradle_buildSrc_kotlin

You may want to read another article of mine about the Gradle Kotlin DSL to get more information about the topic. Enjoy.

The post Execute Kotlin Scripts with Gradle appeared first on Kotlin Expertise Blog.

Continue ReadingExecute Kotlin Scripts with Gradle

Execute Kotlin Scripts with Gradle

Organize Kotlin Scripts as Gradle tasks

In this article, you will learn how you can organize multiple Kotlin scripts as Gradle tasks and make them easily executable this way. I’ve found a discussion about this here. Somebody wanted to execute Kotlin scripts with Gradle build scripts which is, of course, possible by using kotlinc as shown in this (Groovy) build script. This doesn’t look very pretty though, and, as described in the corresponding thread, isn’t very performant and manageable. Another solution would be to use Gradle scripts written with the Kotlin DSL and define custom tasks within a build.gradle.kts file, which obviously can hold and run Kotlin code naturally:

// build.gradle.kts
//
// Execute Kotlin task with:  gradle  -q foo

task("foo") {
  group = "com.kotlinexpertise"
  description = "my foo task"
  doLast {
    println("Hello from foo task")
  }
}

The problem with this approach is that, in my case, I had multiple large Kotlin scripts I wanted to make executable this way. If I had put all of them into tasks, the script would have been too bloated and hard to maintain. Note that in my case, these tasks would not contribute to the build logic directly but rather provide business-relevant tasks, which I wanted to make executable via Gradle.

Gradle buildSrc to the rescue

As described in the Gradle documentation, build logic and especially custom tasks shouldn’t live within the build script directly. Gradle, therefore, offers the possibility to use a so-called buildSrc directory. This directory is treated as an included build, i.e. Gradle automatically compiles and tests this code and makes it available on the build script classpath. The following shows a typical project structure using this special buildSrc directory:

├── build.gradle //main build
├── buildSrc
│   ├── build.gradle //build for buildSrc
│   └── src //custom plugins, taks etc.
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── enterprise
│       │               ├── Deploy.java
│       │               └── DeploymentPlugin.java
│       └── test
│           └── java
│               └── com
│                   └── enterprise
│                       └── DeploymentPluginTest.java
└── settings.gradle

As you can see here, the buildSrc has its own build.gradle, in which we define dependencies and plugins for buildSrc itself. As mentioned, the compiled code will be available for the surrounding build so that you can for instance define custom tasks in the buildSrc and use them in the main build.gradle.

A Kotlin example: Execute Kotlin Scripts with Gradle

Let’s say we have two bigger tasks we want to make available as Gradle tasks, which we call task1 and task2. Both tasks are good fits to be implemented with Kotlin.

The original project build looks like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.2.51"
}

java.sourceSets {
    getByName("main").java.srcDirs("...")
}

repositories {
    mavenCentral()
}

dependencies {
    compile(kotlin("stdlib-jdk8"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

This is very basic and there’s nothing special in it. Now, the goal is to define two custom tasks taks1 and task2 within this script. Both tasks are supposed to be executable via gradle -q task1|task2. To make this possible, we create the buildSrc directory structure as shown above on the same level the build script already exists. Within the buildSrc, we now create the custom tasks as Kotlin classes:

package com.kotlinexpertise.tasks

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.sql.DriverManager

open class Task1 : DefaultTask() {

    init {
        group = "com.kotlinexpertise"
        description = "task1"
    }

    @TaskAction
    fun run() {
        Class.forName("com.mysql.jdbc.Driver")
        //heavy task implementation
    }
}

Just like we would define a task within a Gradle build script directly, we define group, description and the task itself in a method annotated with TaskAction, which we call run. Learn more about custom tasks here. To make this a bit more interesting, we want to load a MySQL driver in this task, which requires us to make the corresponding dependency available for the buildSrc build. Let’s take a look at its build script (existing directly in buildSrc):

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

dependencies {
    compile("mysql:mysql-connector-java:5.1.24")
}

As mentioned, we add the dependencies we want to use within the buildSrc. Another thing to note is that the org.gradle.kotlin.kotlin-dsl plugin is applied to this build in order to set up the Kotlin compiler features and dependencies to match the ones shipped with Gradle. We used the nicer alias kotlin-dsl in this example.

Now, after defining both Task1 and Task2 as subclasses of DefaultTask, they can be used in the main build.gradle.kts script like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.kotlinexpertise.tasks.*

//...

task<Task1>("task1")
task<Task1>("task2")

//...

Note that both probably need to be imported as shown here. In the console, gradle tasks will list them, and you can execute them by running gradle -q task1 and gradle -q task2 respectively. You can also see the tasks listed in IntelliJ IDEA:

gradle_idea

The source code can be found here: https://github.com/s1monw1/gradle_buildSrc_kotlin

You may want to read another article of mine about the Gradle Kotlin DSL to get more information about the topic. Enjoy.

The post Execute Kotlin Scripts with Gradle appeared first on Kotlin Expertise Blog.

Continue ReadingExecute Kotlin Scripts with Gradle

Execute Kotlin Scripts with Gradle

Organize Kotlin Scripts as Gradle tasks

In this article, you will learn how you can organize multiple Kotlin scripts as Gradle tasks and make them easily executable this way. I’ve found a discussion about this here. Somebody wanted to execute Kotlin scripts with Gradle build scripts which is, of course, possible by using kotlinc as shown in this (Groovy) build script. This doesn’t look very pretty though, and, as described in the corresponding thread, isn’t very performant and manageable. Another solution would be to use Gradle scripts written with the Kotlin DSL and define custom tasks within a build.gradle.kts file, which obviously can hold and run Kotlin code naturally:

// build.gradle.kts
//
// Execute Kotlin task with:  gradle  -q foo

task("foo") {
  group = "com.kotlinexpertise"
  description = "my foo task"
  doLast {
    println("Hello from foo task")
  }
}

The problem with this approach is that, in my case, I had multiple large Kotlin scripts I wanted to make executable this way. If I had put all of them into tasks, the script would have been too bloated and hard to maintain. Note that in my case, these tasks would not contribute to the build logic directly but rather provide business-relevant tasks, which I wanted to make executable via Gradle.

Gradle buildSrc to the rescue

As described in the Gradle documentation, build logic and especially custom tasks shouldn’t live within the build script directly. Gradle, therefore, offers the possibility to use a so-called buildSrc directory. This directory is treated as an included build, i.e. Gradle automatically compiles and tests this code and makes it available on the build script classpath. The following shows a typical project structure using this special buildSrc directory:

├── build.gradle //main build
├── buildSrc
│   ├── build.gradle //build for buildSrc
│   └── src //custom plugins, taks etc.
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── enterprise
│       │               ├── Deploy.java
│       │               └── DeploymentPlugin.java
│       └── test
│           └── java
│               └── com
│                   └── enterprise
│                       └── DeploymentPluginTest.java
└── settings.gradle

As you can see here, the buildSrc has its own build.gradle, in which we define dependencies and plugins for buildSrc itself. As mentioned, the compiled code will be available for the surrounding build so that you can for instance define custom tasks in the buildSrc and use them in the main build.gradle.

A Kotlin example: Execute Kotlin Scripts with Gradle

Let’s say we have two bigger tasks we want to make available as Gradle tasks, which we call task1 and task2. Both tasks are good fits to be implemented with Kotlin.

The original project build looks like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.2.51"
}

java.sourceSets {
    getByName("main").java.srcDirs("...")
}

repositories {
    mavenCentral()
}

dependencies {
    compile(kotlin("stdlib-jdk8"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

This is very basic and there’s nothing special in it. Now, the goal is to define two custom tasks taks1 and task2 within this script. Both tasks are supposed to be executable via gradle -q task1|task2. To make this possible, we create the buildSrc directory structure as shown above on the same level the build script already exists. Within the buildSrc, we now create the custom tasks as Kotlin classes:

package com.kotlinexpertise.tasks

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.sql.DriverManager

open class Task1 : DefaultTask() {

    init {
        group = "com.kotlinexpertise"
        description = "task1"
    }

    @TaskAction
    fun run() {
        Class.forName("com.mysql.jdbc.Driver")
        //heavy task implementation
    }
}

Just like we would define a task within a Gradle build script directly, we define group, description and the task itself in a method annotated with TaskAction, which we call run. Learn more about custom tasks here. To make this a bit more interesting, we want to load a MySQL driver in this task, which requires us to make the corresponding dependency available for the buildSrc build. Let’s take a look at its build script (existing directly in buildSrc):

plugins {
    `kotlin-dsl`
}

repositories {
    mavenCentral()
}

dependencies {
    compile("mysql:mysql-connector-java:5.1.24")
}

As mentioned, we add the dependencies we want to use within the buildSrc. Another thing to note is that the org.gradle.kotlin.kotlin-dsl plugin is applied to this build in order to set up the Kotlin compiler features and dependencies to match the ones shipped with Gradle. We used the nicer alias kotlin-dsl in this example.

Now, after defining both Task1 and Task2 as subclasses of DefaultTask, they can be used in the main build.gradle.kts script like this:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.kotlinexpertise.tasks.*

//...

task<Task1>("task1")
task<Task1>("task2")

//...

Note that both probably need to be imported as shown here. In the console, gradle tasks will list them, and you can execute them by running gradle -q task1 and gradle -q task2 respectively. You can also see the tasks listed in IntelliJ IDEA:

gradle_idea

The source code can be found here: https://github.com/s1monw1/gradle_buildSrc_kotlin

You may want to read another article of mine about the Gradle Kotlin DSL to get more information about the topic. Enjoy.

The post Execute Kotlin Scripts with Gradle appeared first on Kotlin Expertise Blog.

Continue ReadingExecute Kotlin Scripts with Gradle

End of content

No more pages to load