GORM 6 with Ratpack

25 February 2017

With the many awesome features of GORM, it is great to see that it is easy to use outside Grails. In this blog, we will see how you can setup GORM for use in Ratpack, using the Hikari Connection Pool and a PostgreSQL database. Dan Woods have an example in his book "Learning Ratpack", but in the latest release of GORM, it has become even easier to setup. Thanks also to Graeme Rocher for helping with a few details on the configuration.

Dependencies

For this example, three dependencies are necessary, GORM, a driver for the database (Postgres), and a Ratpack dependency for the Hikari Connection Pool. As long as the connection pool is on the classpath, GORM will notice it and use it for connections.
// File: build.gradle
dependencies {
// Other dependencies omited....

compile "org.grails:grails-datastore-gorm-hibernate5:6.1.0.M1"
compile 'org.postgresql:postgresql:9.4-1203-jdbc4'
compile ratpack.dependency('hikari')
}

Domain Class

The domain class must implement GormEntity and be annotated with @Entity.
// File: src/main/groovy/Person
package demo

import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import grails.gorm.annotation.Entity
import org.grails.datastore.gorm.GormEntity

@Entity
@JsonIgnoreProperties(['dirtyPropertyNames', 'errors', 'dirty', 'attached', 'version'])
class Person implements GormEntity {

    String firstName
    String lastName

}

Configuring GORM - GormModule

The main configuration of GORM is made as a Ratpack module, where the username and password should be handled in a secure way. In this example, it is hardcoded, and you would have to fix that detail yourself. The Gorm module provides a HibernateDatastore, and the datastore is configured with the class names of the domain classes, see line 24.
// File: src/main/groovy/GormModule
package demo

import com.google.inject.AbstractModule
import com.google.inject.Provides
import org.grails.orm.hibernate.HibernateDatastore

class GormModule extends AbstractModule {

    @Override
    protected void configure() {}

    @Provides
    HibernateDatastore hibernateDatastore() {
        Map configuration = [
                'hibernate.hbm2ddl.auto':'update',
                'dataSource.driverClassName':'org.postgresql.Driver',
                'dataSource.url':'jdbc:postgresql://localhost:5432/demodb',
                'dataSource.username':'demo',
                'dataSource.password':'demo-password',
                'dataSource.dialect':'org.hibernate.dialect.PostgreSQLDialect',
        ]

        HibernateDatastore hibernateDatastore = new HibernateDatastore( configuration ,Person)
        hibernateDatastore
    }
}

Initializing the Datastore

The application needs to be informed of the GormModule, and at startup include the HibernateDatastore in the registry. This is done in ratpack.groovy, like below. We also bootstrap a few persons in GORM, to have some data to serve.
// File: src/main/ratpack/ratpack.groovy
ratpack {
  bindings {
    module GormModule

    bindInstance new Service() {
      void onStart(StartEvent e) throws Exception {
          e.getRegistry().get(HibernateDatastore)

          Blocking.exec {
              Person.withNewSession {
                  if( !Person.count() ) {
                      new Person(firstName: "Bart", lastName: "Simpson").save(flush: true)
                      new Person(firstName: "Homer", lastName: "Simpson").save(flush:true)
                      new Person(firstName: "Liza", lastName: "Simpson").save(flush:true)
                  }
              }
          }
      }
    }
  }

  handlers {
    get {
        Blocking.get {
            Person.withNewSession {
                Person.list()
            }
        } then { names ->
            render(json(names))
        }
    }
  }
}
The handler is for demo purposes only. A standalone handler, with a corresponding service class should be created for real applications. Here any GET request just servers all persons in the database as json.

Testing the Application

It is easy to test the actual application using Spock, and the GroovyRatpackMainApplicationUnderTest. In the example below, we delegate a get request to Ratpacks build in http client, and verifies we actually gets the values from the database.
// File: src/test/groovy/demo/RatpackGormSpec.groovy
package demo

import groovy.json.JsonSlurper
import ratpack.groovy.test.GroovyRatpackMainApplicationUnderTest
import ratpack.test.http.TestHttpClient
import spock.lang.Specification
import spock.lang.AutoCleanup
import spock.lang.Shared

class RatpackGormSpec extends Specification {

    @AutoCleanup
    @Shared
    GroovyRatpackMainApplicationUnderTest aut = new GroovyRatpackMainApplicationUnderTest()

    @Delegate
    TestHttpClient client = aut.httpClient


    void "Test we get data from database"() {
        when:
        get()

        then:
        response.statusCode == 200

        when:
        def json = new JsonSlurper().parseText(response.body.text)

        then:
        json.size() == 3
        json*.firstName == ['Bart', 'Homer', 'Liza']
    }
}
The full sourcecode for this blog can be found at github.com/JacobAae/GORM6-Ratpack-example. In the README, there are details on creating the PostgreSQL database, or if you have docker installed, Gradle tasks are available to create and remove a dockerized database, for the demo application. The GORM documentation is available at gorm.grails.org.