Plugin Configurations in Grails

Perhaps, you have a plugin and you would like to configure it instead of hard coding the settings. Lets say, it is a url for REST service that your plugin consumes. In this post, we cover how to incorporate the plugin configurations into part of the default Grails configurations(conf/Config.groovy). In the second part, we cover how to separate the plugins configurations into a separate configurations file while still part of the application

Configurations From App conf/Config.groovy

First, add the configurations setting in the Grails app configuration file(conf/Config.groovy):

// This default value...
yourConfigurationName.url='http://service.com/restapi/'
...
environments {
  development {
    // configurations when in development environment
    yourConfigurationName.url='http://service.com/restapi/'
  }
}

The configuration name may be as you like. From your plugin, this configurations setting can be accessed as follows:

class NodeDriverProxyService {
    def grailsApplication
    def http

    public someMethod(){
        http = new HTTPBuilder(grailsApplication.config.yourConfigurationName.url)
...

As you see, first we inject grailsApplication and then access your setting via grailsApplicaiton.config

This way it is also possible to externalize plugin settings among the other grails configurations as described in post Externalizing Configurations per Grails Application

Configuration from plugins config file

Perhaps, you like to put plugin configurations into separate configuration file instead Grails default Config.groovy
First, create your configuration file and add the configurations. For example grails-app/conf/myPluginName.groovy:

// This default value...
yourConfigurationName.url=http://service.com/restapi/
...
environments {
  development {
    // configurations when in development environment
    yourConfigurationName.url=http://service.com/restapi/
  }
}

This is exact same as part of the Application configurations. Next, here is how to access from plugin:

GroovyClassLoader classLoader = new GroovyClassLoader(getClass().getClassLoader())
ConfigObject config
try {
   config = new ConfigSlurper().parse(classLoader.loadClass('myPluginName'))
}
catch (Exception e) {/*
    if exception, set default settings
*/}

//to access
config.yourConfigurationName.url

Here, we load the file and then use Groovy ConfigSlurper utility to parse and access plugin configurations

To summarize, we covered two ways for plugins configurations being incorporated in the application. One as part of the Grails configuration and another as a separate plugin configurations within the application.

Issues

1. grailsApplication is null
Make sure grailsApplication.config is used within a method. i.e:

class someClass{
def grailsApplication
def url = grailsApplication.config.pluginName.url//this is going to be null

public someMethod(){
   url = grailsApplication.config.pluginName.url//this works!!!
  }
}

Useful Links

  • http://groovy.codehaus.org/ConfigSlurper
  • http://stackoverflow.com/questions/843216/configuration-of-grails-plugin

Request Automatic Parsing in Grails

Grails comes with a parser that takes the request and parses it into variables – ‘params’ and ‘request’

Reading Url Params

The URL part is parsed into the ‘params’ variable. This includes the Url query string as well as URL-encoded string(body). Here is GET request initiated from Curl:
curl -G -d "title=Great%20Place" http://localhost:8010/minnehaha/review/update/100
So, at the controller to read Url parameters as follows:

//action in controller
def update() {
     params.id
     params.title
     params.action
     params.controller
...
}

Besides Url parameters, Grails parses also the ‘action’ and ‘controller’ for the given request

Reading Request Body

The body of the request is parsed into ‘request’ variable depending of ‘content-type’ specified in request. By default, the request parser supports two types – XML and JSON. Here is PUT request initiated via Curl:
curl -i -H "Content-Type: application/json" -X PUT -d '{"title":"great place"}' -d '{"content":"coming again soon"}' http://localhost:8010/minnehaha/review/update/100
At the controller, the request parser looks at the content-type, finds ‘json’ and parses into request.JSON:

..
request.JSON.title == 'great place'
request.JSON.content == 'coming again soon'
..

A common mistake is to forget specify ‘content-type’ in request resulting the ‘request.JSON’ variable to be empty because without the type, the parser is unable to parse request

The parser will always try to parse whenever there is a body attached to request even for GET and DELETE requests:
curl -i -H "Content-Type: application/json" -X GET -d '{"title":"great place"}' http://localhost:8010/minnehaha/review/update/100

By convention, the GET and DELETE requests doesn’t have raw/chunked body attached, however. HTTP/1.1 RFC does not forbids it and grails parser will parse it.

What if other than JSON or XML?

There may be situation where the data in body for the request is neither JSON nor XML format. To read the raw data:

request.getReader().text

However, this will give the following error:
getInputStream() has already been called for this request
This is because the default request parser needs to be turned off before reading the body text. Here is one way how to do it in the grails-app/conf/UrlMapping:

class UrlMappings {

    static mappings = {
        "/api/review/$id?"(controller: 'review', parseRequest: false){
            action = [ PUT: "update", POST: "save", GET: "show"]
        }
...
}

By specifying ‘parseRequests:false’ in highlighted line, it will turn off the Grails automatic parsing and make it possible to read the body data (i.e. request.getReader().text)

Content Negotiation

The Content Negotiation is topic in its own and should be separate post. Just to clarify, in the request header the ‘accept’ field is used for content negotiation and the ‘content-type’ is used for request parser to parse the body of request in Grails.

Useful Links:

  • http://grails.1312388.n4.nabble.com/Incoming-JSON-in-Controller-td4495260.html
  • http://grails.org/doc/2.2.x/ref/Controllers/withFormat.html
  • http://grails.org/doc/2.2.x/guide/single.html#contentNegotiation
  • http://jira.grails.org/browse/GRAILS-7099
  • http://grails.org/doc/1.3.9/ref/Servlet%20API/request.html
  • http://stackoverflow.com/questions/5905916/payloads-of-http-request-methods
  • http://sislands.com/coin70/week6/cgi.htm

Mocking Log Service and Others in Grails and Groovy

In this post, we cover different ways of mocking Services and other entities when writing tests in Grails. For the examples in this post, we use the Log service to better demonstrate

Environment: Grails 2.1.2, Spock 1.0, Mac 10.7

Using Grails mockFor

In this example, the Grails mockFor mechanism of mocking is used to mock the log service:


    def "mock using grails mockFor"(){
        setup:
        def httpBuildMock = new MockFor(HTTPBuilder.class)
        def logTo = []
        def loggerMock = mockFor(org.apache.commons.logging.Log)
        loggerMock.demand.warn(1..1){ String message ->
            logTo << [msg:message,level: 'warn']
        }
        service.log = loggerMock.createMock()

        when:
        service.methodLogging()

        then:
        assert logTo.msg == 'some message'

First we create global variable ‘logTo’ to store the logged value, so we can assert it later. Then we create mock of Log interface and mock the method ‘log.warn’. At last, the mocked logger is assigned to the logger used by the service

Using Groovy Closure

Since Groovy provides convenient way to implement interfaces, the mocking of logger can be done via closure as following:

def "mock via groovy closure"(){
        setup:
        def logTo = []
        def logInstance = {String message -> logTo << [msg: message]} as org.apache.commons.logging.Log
        service.log = logInstance

        when:
        service.methodLogging()

        then:
        assert logTo.msg == 'some message'

In the highlight line, the closure is created and assigned to a type of org.apache.commons.logging.Log interface. This closure is going to be executed whenever any of the Log methods(warn,error,etc.) is going to be called. Afterwards, the new logger is assigned to the service logger instance

Important to note, for mocking multiple methods the interface is implemented via Groovy Map as following

def "mock via groovy closure"(){
        setup:
        def logTo = []
        def impl = [
                warn:{String message ->
                    logTo << [warn: message]
                },
                error:{String message ->
                    logTo << [error: message]
                }
        ]

        def logInstance = impl as org.apache.commons.logging.Log
        service.log = logInstance

        when:
        service.methodLogging()

        then:
        assert logTo.warn == 'some message'
        assert logTo.error == 'some message'

As you see, here the two closures one for method ‘warn’ and another for ‘error’ are created and put into Map. Afterwards, the interface type assigned and injected into service as the logger instance

Using Groovy MockFor

Another alternative is to use Groovy MockFor mechanism that is very similar to the one in Grails

def "mock via groovy MockFor"(){
        setup:
        def logTo = []
        def logService = new MockFor(org.apache.commons.logging.Log)
        logService.demand.warn(1){ String message ->
            logTo << [msg: message]
        }
        service.log = logService.proxyInstance()

        when:
        service.methodLogging()

        then:
        assert logTo.warn == 'some message'

This is almost identical to Grails mockFor implementation

In summary, there are choices when mocking logger or any other collaborator for that matter. The three different alternatives listed here can be applied to any collaborator in your test of interest

Useful links:

  • http://slf4j.org/faq.html about IlligalAccessError
  • http://blog.springsource.com/2009/12/04/logging-dependencies-in-spring/
  • http://stackoverflow.com/questions/3032654/hibernate-spring-and-slf4j-binding
  • http://groovy.codehaus.org/Groovy+way+to+implement+interfaces

Revise GEB Functional Tests in Grails

At work, i have been doing enough functional tests to begun note some important aspects that can help boost productativity

Accessing Page Content in Helper Method

In my fellow developer’s code, i noticed in Page objects a lot of repetitive setters for each page content defined. Here is example:

class RentalUnitEditPage extends Page {
...
    static content = {
        nameInput(wait: true) { $("input#name") }
        review(wait: true) { $("select", id: "review.id") }
        someGroupSelect(wait: true) { $("select#someGroup\\.id") }
        paymentMethodSelect(wait: true) { $('select#paymentMethodType') }
        companyTypeSelect(wait: true) { $('select#companyType') }
        groupSizeSelect(wait: true) { $('select#classification') }
...
}

    void setName(String newName) {
        nameInput.value(newName)
    }

    void setSomeGroup(String group) {
        someGroupSelect.value(group)
    }

    void setReview(String rev) {
        review.value(rev)
    }

    void setPaymentMethod(PaymentMethodType paymentMethod) {
        paymentMethodSelect.value(paymentMethod.id)
    }
...
}

As you see, there is setter for each input variable and we need setter because in the test we update fields to validate it updated correctly, however. With so many setters, we certainly are not following DRY(Don’t Repeat Yourself) principle. To do so, instead of the many setters for each field, lets have general setter as follows:

class RentalUnitEditPage extends Page {
...
    void setField(String fieldName, String fieldValue){
        browser.page."$fieldName".value(fieldValue)
    }
...
}

So, this way we can remove the many setters only having one – the general one described above

Upload file widget Module Example

In the ‘Book of GEB‘, it encourages to use Modules for reusing functionality. Here is an example of module for uploading files widget:


class LoadFileModule extends Module {
    String buttonName
    String inputId
    String inputUrl

    static content = {
        fileUploadField(wait: true) { $("input#${inputId}") }
        loadButton(wait: true) { $("input", name: buttonName) }
    }

    void clickLoad(Class toPage){
        fileUploadField.value(inputUrl)
        loadButton.click(toPage)
    }
}

So, for page objects that has the upload file widget, you don’t have to recreate functionality to upload file in test. You could just include the LoadFileModule module and use it as follows:

class SomeLoadPage extends Page {
...
    static content = {
        ...
        loadFile(wait: true) { inId, inUrl, bName -> module  LoadFileModule, inputId: inId, inputUrl: inUrl, buttonName: bName}
    }

    AfterLoadStatusPage loadSomeFile(String filePath) {
        loadFile("fileInputFieldId", filePath, "uploadFileButtonName").clickLoad(AfterLoadStatusPage)
        ...
    }
}

As you can see, first we load the module LoadFileModule(highlighted line) and pass three parameters – inId that is fileInputFieldId, inUrl that is file path and bName that is the button name. Then, in your test to load file all you need is call this method while giving file path.

Externalizing Configurations per Grails Application

You may have multiple grails applications and each is using different datasource, mail, etc configurations. It may be benefit to externalize those configurations for maintainability as well as portability reasons. In this post, i demonstrate one way to accomplish it.

Make Grails Externalize

In order to externalize configurations, you have to add following line in the conf/Config.groovy:


grails.config.locations = ["file:${userHome}/.grails/apps-config/${appName}/${appName}-config.groovy"]

This way you specify the path as well as the name of the configuration file. We choose to keep our configuration in Groovy file, however, it works as well if .properties file:


grails.config.locations = ["file:${userHome}/.grails/apps-config/${appName}/${appName}-config.properties"]

However, its preferable in .groovy file because that way you are able to script. Please see section ‘.Groovy vs .Properties’ below

Naming Application

In the above, you can see we using variable – appName. This variable is set by Grails at the startup. It is defined in the ‘application.properties’ file in root directory of the application. Here is example:


#Grails Metadata file
#Sat Oct 06 09:17:17 CDT 2012
app.grails.version=2.1.1
app.name=minnehaha
app.servlet.version=2.5

Grails reads the value of ‘app.name’ and initializes variable ‘appName’ that you can use in any of Grails configuration file. In our case, we use to set proper directory as well as the externalized configurations file name

External Configuration File

Once externalized in ‘conf/Config.groovy’ and application name set as described above, at last, create groovy script with externalized configurations and place it in directory specified above. Here is an example of mail server configuration externalized:

grails{
    mail{
        host="smtp.gmail.com"
        port=465
        username="website@ms.com"
...
    }

}

This will configure mail server with the email account for the specific application

.Groovy vs .Properties file

Externalizing in .groovy file,  does not necessary mean you are unable to accomplish the same with .properties file. For the fact it is doable, however, let me demonstrate how, so its clear, going with .groovy file, is the preferred way.

For example, to externalize in .groovy configuration file something per different environment such as datasource is as easy as adding:

environments {
    test {
       dataSource {
          driverClassName = "com.mysql.jdbc.Driver"
         ...
         }
    }
    development {
       dataSource {
          driverClassName = "com.mysql.jdbc.Driver"
         ...
         }
    }
}

It doesn’t necessary mean you are unable to accomplish the same with .properties file. For the fact it is doable, however, let me demonstrate how, so its clear, going with .groovy file, is the preferred way.

To accomplish the same – different datasource per environment, its necessary to update the externalization variable ‘grails.config.locations’ in the .conf/Config.groovy:

grails.config.locations = ["file:${userHome}/.grails/${appName}-config-${grails.util.Environment.current.name}.properties"]

From the code snippet you can see, we append the environment to the .properties file name. So, that different .properties file is read for each environment that way different configurations applied:

dataSource.dbCreate =
dataSource.driverClassName = com.mysql.jdbc.Driver
dataSource.url = jdbc:mysql://localhost/minnehaha_test
dataSource.username = root
dataSource.password = mysql

Above is an example for test environment .properties file to use appropriate database, however. There needs to be .properties file per environment:

 >/home/me/.grails/myapp/myapp-config-development.properties
  >/home/me/.grails/myapp/myapp-config-test.properties
  >/home/me/.grails/myapp/myapp-config-production.properties

In short, it required many more .properties files to accomplish the same in one .groovy due to scripting capabilities

NOTE: For .properties config files, make sure quotes are removed,otherwise, errors like such ‘ Cannot load JDBC driver class ‘”com.mysql.jdbc.Driver”‘ is received

Its important to note that externalized configurations supersede the configurations in any of the Grails configuration files(BuildConfig.groovy, Config.groovy, DataSource.groovy,etc.)

Issues

1. If the externalized .groovy script file has syntax errors then none of the configurations are read as well as Grails continues the startup without any error notification.

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 be 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

Interesting to note,that on the right side(Author) of the Book-Author relationship there is cascading enabled while on the left(Book) there is none. It is apparent, that the cascading setting on left(Book) specified with ‘static mapping’ supersedes.

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:

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