Grails Environment Aware Framework

One of the awesome features Grails provides is its ability to configure multiple environments to run your application. It comes with three initial environment setups – Development, Test, Production. Besides these environments,  you are able to setup your own custom environment.

The advantage of having multiple environments is the ability to execute your application with different settings, different data sources and other specifics. For example, you may wish to run tests against different database than one used by actual application. Likewise, you may wish not load application data (User, etc) when testing to avoid tests to break. Despite the need, it is accomplished by having different settings in DataSource, Config, BootStrap, BuildConfig and Searchable configurations(grails-app/conf/) each executed per specified environment.

In this post, first I will briefly  cover how to run different environments. Afterwards, I will demonstrate how to declare and configure environments, all of which in relation to practical problem/solution examples from my development process

Run Apps Different Environment

To run app or execute any command(i.e grails war, etc.) in different environment it is needed to specify the environment after ‘grails’ command (i.e. ‘grails [env] run-app’). Here is some examples:

>grails dev run-app
>grails -Dgrails.env=mycustomenv war
>grails test dbm-status

As you can see, the enviroment is specified right after ‘grails’ command. If you don’t specify, it is using the default which is ‘dev’ or Development environment. For your custom environments, you add ‘Dgrails.enf=’ with the name of your custom environment you wish to run

Practical Usages

1. Loading App Data in Bootstrap

At some point, your application will need to have some data like users, roles, etc. One of the ways to import data is to BootStrap(specify in BootStrap.groovy file) the data into your application, however. At the time of running tests, that is in test environment, you probably don’t want to have any data bootstraped, otherwise, it will break your tests(i.e. assert User.count() == 0 fails). So, the solution is to look up environment before importing or not importing data in BootStrap.groovy. Here is example:

class BootStrap {

    def loadDomainDataService

    def init = { servletContext ->

        environments {
            test {
                log.info("starting in Test env.....")
            }
            dbgorm {
                log.info("starting in dbgorm env.....")
            }
            development {
                log.info("starting in dev env.....")
                (User.findAll().empty) ? loadDomainDataService.loadSecurityData() : log.info("Security Data already loaded. Skipped loading...")
                (RentalUnit.findAll().empty) ? loadDomainDataService.loadAppData() : log.info("App Data already loaded. Skipped loading...")

                //don't start app if data not loaded
                assert User.count()
                assert RentalUnit.count()
            }
        }
...

Or Another way:

import grails.util.GrailsUtil
class BootStrap {

    def loadDomainDataService

    def init = { servletContext ->

        switch (GrailsUtil.environment) {
            case "test":
                log.info("starting in Test env.....")
                break
            case "dbgorm":
                log.info("starting in dbgorm env.....")
                break
            default:
                (User.findAll().empty) ? loadDomainDataService.loadSecurityData() : log.info("Security Data already loaded. Skipped loading...")
                (RentalUnit.findAll().empty) ? loadDomainDataService.loadAppData() : log.info("App Data already loaded. Skipped loading...")
                //don't start app if data not loaded
                assert User.count()
                assert RentalUnit.count()
                break
        }
...

In the above code snippets, the different environments configured is highlighted. There are the predefined env such as ‘test’, ‘dev’ and there is our custom env – ‘dbgorm’. For the custom env, there is no need declare it separately prior using them. Just use them in any configuration file like any of the predefined environments. The custom env will be referenced by the name you choose to use in the configuration files. It is case sensitive.

From the above you can see how we prevent the app data be loaded in ‘test’ or ‘dbgorm’ environment but do load data if application run in ‘dev’ and other env . On the side note, to load data itself we use Grails Fixture plugin about which another post

2. Data Source Dependent on Env
Once your application is loaded with data needed for application like Users, Roles, etc than this info is stored in Database. Afterwards, you would like run tests, however, many of the tests will fail because your database contains application data that most likely conflicts with assertions in your tests (i.e. Users.count()==0).

One of the solutions is to use a separate database for running tests. You have your ‘dev’ environment configured for one database and then your ‘test’ environment with another database. The database used by each environment is configure in conf/DataSource.groovy file. Here is an example:

// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "" // one of 'create', 'create-drop', 'update', 'validate', ''
            driverClassName = "com.mysql.jdbc.Driver"
            url = "jdbc:mysql://localhost/minnehaha"
            username = "root"
            password = "mysql"
        }
    }
test {
        dataSource {
            dbCreate = "" // one of 'create', 'create-drop', 'update', 'validate', ''
            driverClassName = "com.mysql.jdbc.Driver"
            url = "jdbc:mysql://localhost/minnehaha_test"
            username = "root"
            password = "mysql"

        }
    }
...

The highlighted lines shows the each different database configured. So, in our situation, if application is started in ‘dev’ it will be using ‘minnehaha’ database. If  tests run(i.e. grails test-app) then it uses by default the ‘test’ environment, thus, the tests are run against database – ‘minnehaha_test’. This way we are sharing the same application to develop and test while separating the data into two different databases to avoid conflicting between process of testing and other

Interestingly to note, both 'test' and 'dev' databases is managed by Grails Database Migration Plugin, so how would you run migration commands against each different database? Make sure you specify environment when calling any of the Database migration plugin commands. Here is an example:
 >grails dbm-update
 >grails test dbm-update
 The first command will run migrations on default environment which is 'dev' updating database - 'minnehaha' in our case. The second command will run migration script in 'test' env that will update database - 'minnehaha_test' only

3. Migration Script Run at Start Up?… Not Always
We use Grails Database Migration Plugin to manage the database updates, new table creation and database roll backs when needed. Every time the branch is changed or  I received a new code changeset, I was finding myself repetitively running ‘dbm-update’ manually to get dev database in sync. It turns out, this step can be automized, so that when the grails application start, it runs ‘dbm-update’ if there is new migration scripts. For more, see section ‘Run Migration Scripts at Start’ in  the post – Grails Database Migration Plugin

In times adding/updating domain objects, this was a problem. This is because, after making changes in GORM, it was in conflict with current DB structure built by migration scripts at the start up. To solve the problem we created custom environment specifically for GORM development as follows:

Step 1. In the custom env – dbgorm the database will not use migration plugin. Here is conf/DataSource.groovy:

environments {
..
    dbgorm {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', ''
//          url = "jdbc:h2:mem:devDb;MVCC=TRUE"
            driverClassName = "com.mysql.jdbc.Driver"
            url = "jdbc:mysql://localhost/minnehaha_gorm"
            username = "root"
            password = "mysql"

        }
    }
...
}

We accomplish this by configuring our custom environment create and drop database, instead of database migration plugin does it(change ‘dbCreate’ attribute to ‘create-drop’ data source as highlighted in above code).

Step 2. The step 1 takes care of building the database structure, but we still need to prevent migration scripts to run at start up in our custom env – dbgorm. To accomplish, we update conf/Config.groovy as follows:

//To dbm-update On Start
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ["changelog.groovy"]
grails.plugin.databasemigration.changelogLocation = 'grails-app/migrations'

environments {
    dbgorm {
        grails.plugin.databasemigration.updateOnStart = false
    }
}

So, if the application is run in env – dbgorm, we set the updateOnStart to false that way preventing migrations scripts to be run at start up.

With this setup, we change/update domain class or GORM in dbgorm environment. Afterwards, when we satisfied with the changes then we run:

 grails dbm-gorm-diff --add filename.groovy

in dev environment for capturing the changes. This generates migration scripts added in the changeset log(for more, see post ‘Grails Database Migration Plugin‘) and that is run next time app starts in environment other than dbgorm.

How To Know What’s default?

You may wonder what is the default settings if none is specified for your custom environment. For example, if you have custom environment but you don’t specify Data Source for it, what Data Source is it going to use?

Grails configuration files – DataSurce, Config, BuildConfig,etc are using Groovy utility – ConfigSlurper. The ConfigSlurper “allows a default setting to exist in the property file that can be superceded by a setting in the appropriate environments closure”(from ConfigSlurper documentation). In another words, following example of Data Source, there is the default property – ‘datasource’  following with declarations of ‘datasource’ for each environment that supercedes the default one.

//default
dataSource {
 ...
}

// environment specific settings
environments {

	development {
		dataSource {
...

Useful Links

Groovy Snippets

This is ongoing blog where i plan to record groovy code snippets that convenient, useful and powerful

Generating Long Strings

Generating certain size string( used in testing to test sized string constraints)

def genString(size){
    def nameTooLong = 'x'
    size.times { nameTooLong <<= "x" }
    nameTooLong
}

-or-

'x'*100

Avoid Exception – MissingPropertyException

There is null safe operator (?.) to avoid exceptions when calling methods on null object, however. If you call a property or method that is not defined, you will receive an exception – ‘missingPropertyException’. To make it similar as null safe but this time exception safe, add the following to your class:

def propertyMissing( name ) {
  null
}

This will make call to a method, that hasn’t been defined, return null, instead throwing exception. Likewise, this will make access to a variable, that hasn’t been defined, return null instead of throwing exceptions

If you don’t have access to changing the class, then the alternative would something like:

def result = obj.hasProperty( 'b' ) ? obj.b : null

It requires much more to accomplish the same as adding the method – propertyMissing to the class only once, but it may work some situation better

 Remove last characters from string

assert 'some' == 'someString'[0..-7]

Checking if String

To determine whether its valid string, make sure check case for empty string like – ‘ ‘:

asset someString?.trim()

Java Gotchas

This is ongoing post where i hope to continue list different Java gotches

1. java.util.ConcurrentModificationException – Removing children from the parents’s collection while we’re iterating over it.

As example we use groovy. In our example, we have RentalUnit object that contains colection of Reviews and Reviews contain collection of RentalUnit all in many-to-many relationship

Error:

review1.rentalUnits*.removeFromReviews(review1)

Solution:

def r = []
r += review1.rentalUnits
r.each {RentalUnit renUnit ->
     renUnit.removeFromReviews(review1)
}

Domain Object One-To-One Relationship In Grails GORM and SQL Relational Database

This is following post series about ‘Domain Object Relationships in Grails GORM and SQL Relational Databases‘ where we look at the details how the relationships are build in GORM with how physically structrured in DB while cascading and direction addressed. This post is divided into 4 section as following:

Each section contains the following:

  • Class Diagram
  • Code Snippet
  • ER Diagram with Tables snippet
Summary: There is the same parent-child database structure with foreign key constrain for all 4 different versions of One-to-One relationship. We learn that cascading and direction is enforced solely by GORM without no changes in tables structure.

1. One-To-One Unidirectional Relationship with No-Cascading

(a) Class Diagram

In our example, we have object Book and Author and the one-to-one relationship is where Book has one Author as displayed in the following class diagram:

(b) Code Snippet

So, to have One-To-One unidirectional relationship without cascading for GORM the code looks as following:

By declaring Author in the Book class it becomes unidirectional no-cascading one-to-one relationship.

(c) ER Diagram with Tables snippet

Here is how it physically structured in SQL Rational DB:

As we can see ‘Author’ becomes a child for entity -‘ Book’ by having foreign key as ‘author_id’ part of Book table. Interesting to note that foreign key name is created by concatenation of  name of the Entity +  ‘__’ +  primary key(i.e. author_id)

2. One-To-One Unidirectional With Cascading

(a) Class Diagram

(b) Code Snippet

In order to have cascading enforced by GORM, it needs to be told GORM that ‘Author’ is a child of ‘Book’. Here is how its done:

So,  adding “static belongsTo = Book” lets GORM know that ‘Author’ is a child and needs to be cascaded whenever parent – ‘Book’ deleted, saved.

(c) ER Diagram with Tables snippet

There are no changes in the physical table structure. GORM handles cascading. In short, to have unidirectional and cascading relationship you have two things – declaring child relationship as is  ‘Author’ in the Book entity(green) and letting GORM know its a child in the ‘Author’ entity(red)

3. One-To-One Bidirectional Cascading

(a) Class Diagram

Here is our updated class diagram showing bidirectional relationship:

(b) Code Snippet

Here is the code to have One-to-One bidirectional cascading relationship

The green  code from the code snippet above is what was for making relationship unidirectional. The red code is what changed and turned it into bidirectional while keeping cascading. In short, by making variable ‘belongsTo’  turns the relationship bidirectional

(c) ER Diagram and Tables snippet

There are no change in DB structure. This is telling that just like cascading as well as direcretion –  bidirection and unidirection is solely enorced by GORM and there is no specific changes in SQL DB.

4. One-to-One Bidirectional No Cascading

To enable no cascading, the following code need to added in Book class:

...
static mapping = {
        author cascade: "none"
    }
...

This will disable any cascading. Some times you may need disable cascade on Deletes only or some other way. These are some alternative cascading options –

  • none
  • save
  • update
  • save-update
  • delete
  • all
  • all-delete-orphan

Domain Object Relationships in Grails GORM And SQL Relational Databases

When doing re-factoring  for applications with SQL Databases, it may be helpful to know the details how GORM creates different relationships and how those relationships are physically structured in the DB. This post starts the post series to cover – One-To-One, One-To-Many, Many-To-Many and Inheritance for Domain objects relationships. we hope to answer following questions

  • How these relationships are physically structured in DB?
  • How these relationships  are implemented in respect to cascading and direction(bidirectional vs unidirectional) and whether it changes DB structure?

Here is summary:

Inheritance Relationship

Summarized – Quick Reference

Relationship Unidirectional Bidirectional
One-To-One

(book*-to-author)

Many-To-One

(book*-to-author)

  Not Possible (see post)
One-To-Many

(RentalUnit*-to-review)

Many-To-Many

(RentalUnit*-to-review)

Inheritance img