Grails Starter Kit

After years of working with Grails, I thought I would put down in one place a few things I tend to use frequently in my Grails projects. These are things I thought might help others getting started with Grails.

Templates

    > grails install-templates

You will then need to edit the web.xml contained in the following directory structure that was generated from the above command.

src -> templates -> war -> web.xml

you can now modify the timeout value

<session-config>
    <session-timeout>180</session-timeout>
 </session-config>

Custom Domain Classes

Update your domain class templates to reduce having to type in your company standards for every domain class. One of the environments I worked in had a database standard that required us to label Primary Key column name(PK_column_name) and use oracle’s generator for ids. I addressed this by creating a private company "db standards" Grails plugin.

First I updated the

templates-> artifacts ->DomainClass.groovy file


@artifact.package@class @artifact.name@ {
    Date lastUpdated
    Date dateCreated
    String createdBy
    String updatedBy

    static constraints = {

    }
    static mapping={
        id generator: 'sequence', params: [sequence: '@artifact.name.uppercase@_SEQ']
        columns { id column: '[email protected]@_ID' }//prod/test
    }
}

I then copied and modified a core grails script(see comments in code) that creates domain classes and renamed it create-my-domain(well it was better names then this… but you get the gist :D). See below.

Then I can run

    > create-domain Book

The following concrete domain class is generated(notice the sequence,id, and generator are all there).

class Book{

  Date lastUpdated
  Date dateCreated
  String createdBy
  String updatedBy
  static mapping = {
    id generator: 'sequence', params: [sequence: 'BOOK_SEQ']
    columns { id column: 'PK_BOOK_ID' }
}

Datasource(s)

There are times when I need to query a database that I don’t need/want a Domain Class for. I tend to create a datasource and inject it into a service that will be handling the connection/query with groovySql

Here is an example datasource in the DataSource.groovy file.

dataSource_salesInfo {
  driverClassName = "oracle.jdbc.driver.OracleDriver"
  url = ""//more on how to configure this later in this blog entry
  username = ""

  password = ""
  dialect = "org.hibernate.dialect.Oracle10gDialect"
  hibernate {
    cache {
      use_second_level_cache = false
      use_query_cache = false
    }
  }
}

Example service that uses the defined datasource entry.

class AwesomeService{

  def dataSource_salesInfo //Inject it

  def queryDB(){
  def sql = new Sql(dataSource_salesInfo)
  String myQuery ='..'
  sql.rows(myQuery).each { resultSet -> /*do something*/}
  }
}

Externalize Datasources

One way to externalize your jdbc connection url is to use an system environment variable. Another is to have your operations team generate a properties file based on the tnsnames.ora file and read it into your grails application. I will describe how the properties file based solution would work. An Example tnsnames.properties entry might look like the following.

DATAWAREHOUSE=jdbc:oracle:thin:@xyaeyp49:1521:DATAWAREHOUSE

in datasource.groovy file, I add the following to the top of the file.

def props = new Properties()
new File('pathToTNS.properties').withInputStream { stream ->
props.load(stream) }

then I reference the property in the URL entry for the datasource I am working with

username='javazquez'
url = props.get("DATAWAREHOUSE")
...

Most of my day is spent with Oracle databases. The validation query that I use is

validationQuery = "SELECT sysdate from dual"

here is a complete example.

production {
  dataSource {
    url = props.get("DATAWAREHOUSE")
    username = ""
    password = ""
    properties {
      maxActive = -1
      minEvictableIdleTimeMillis = 1800000
      timeBetweenEvictionRunsMillis = 1800000
      numTestsPerEvictionRun = 3
      testOnBorrow = true
      testWhileIdle = true
      testOnReturn = true
      validationQuery = "SELECT sysdate from dual"
    }
  }
}

Here are the lines that actually allow you to externalize your config/datasources(Thanks to Burt Beckwith and his book )

production {
    grails.config.locations = [
    "file:path_2_external_config.properties" //NOTE: don't leave spaces
    ]
}

I like to have the following in my path

grails.config.locations = [
    "file:path_${appName}/${appName}_${grails.util.Environment.current.name_config.groovy",
]

This forces the file name to have development || production || test and the application name in the configuration file to prevent copy and paste errors(you would never do that right 😉 )

SQL Logging

There are a couple of ways to see what is going on under the hood when your application is querying the database.

The easiest is to add the logSql = true to your datasource

development {
  dataSource {
    url = props.get("DATAWAREHOUSE")
    logSql = true
    ...
    }
  }
}

If you need more information, Burt Beckwith has the following Logging Hibernate SQL post that you should read. He shows how adding the following lines to your log4j closure will help with understanding what is happening under the hood.


log4j = {
   ...
   debug 'org.hibernate.SQL'
   trace 'org.hibernate.type.descriptor.sql.BasicBinder'
}

Misc

A log pattern that works with tomcat(YMMV)

appenders {
console name: 'stdout', threshold: org.apache.log4j.Level.INFO
rollingFile name: 'MyLogs', file: 'logs/MyLog.log', maxSize: 104576, threshold: org.apache.log4j.Level.INFO ,
layout:pattern(conversionPattern: "%d{yyyy-MM-dd HH:mm:ss} [%t] %p %c - %m%n")

}

Have your war tell you what environment you are deploying to

grails.project.war.file = "target/${appName}-${appVersion}-${System.getProperty('grails.env')[0..3]}.war"

Websites and links to check out

Many of the things I have learned have come from the above links and people. A big Thank You to the gr8 community for all the help over the years.

-Juan