Grails Starter Kit
2015-01-06After 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
- Groovy Weekly
- An Army of Solipsists – Burt Beckwith
- http://mrhaki.blogspot.com/
- Cédric Champeau’s blog
- Andres Almiray’s blog
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