(Quick Reference)

4 Configuration - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari

Version: 3.0.17

4 Configuration

It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now. With Grails' default settings you can actually develop an application without doing any configuration whatsoever, as the quick start demonstrates, but it's important to learn where and how to override the conventions when you need to. Later sections of the user guide will mention what configuration settings you can use, but not how to set them. The assumption is that you have at least read the first section of this chapter!

4.1 Basic Configuration

Configuration in Grails is generally split across 2 areas: build configuration and runtime configuration.

Build configuration is generally done via Gradle and the build.gradle file. Runtime configuration is by default specified in YAML in the grails-app/conf/application.yml file.

If you prefer to use Grails 2.0-style Groovy configuration then you can create an additional grails-app/conf/application.groovy file to specify configuration using Groovy's ConfigSlurper syntax.

For Groovy configuration the following variables are available to the configuration script:

VariableDescription
userHomeLocation of the home directory for the account that is running the Grails application.
grailsHomeLocation of the directory where you installed Grails. If the GRAILS_HOME environment variable is set, it is used.
appNameThe application name as it appears in build.gradle.
appVersionThe application version as it appears in build.gradle.

For example:

my.tmp.dir = "${userHome}/.grails/tmp"

If you want to read runtime configuration settings, i.e. those defined in application.yml, use the grailsApplication object, which is available as a variable in controllers and tag libraries:

class MyController {
    def hello() {
        def recipient = grailsApplication.config.getProperty('foo.bar.hello')

render "Hello ${recipient}" } }

The config property of the grailsApplication object is an instance of the Config interface and provides a number of useful methods to read the configuration of the application.

Notice that the Config instance is a merged configuration based on Spring's PropertySource concept and reads configuration from the environment, system properties and the local application configuration merging them into a single object.

GrailsApplication can be easily injected into services and other Grails artifacts:

import grails.core.*

class MyService { GrailsApplication grailsApplication

String greeting() { def recipient = grailsApplication.config.getProperty('foo.bar.hello') return "Hello ${recipient}" } }

Finally, you can also use Spring's Value annotation to inject configuration values:

import org.springframework.beans.factory.annotation.*

class MyController { @Value('${foo.bar.hello}') String recipient

def hello() { render "Hello ${recipient}" } }

In Groovy code you must use single quotes around the string for the value of the Value annotation otherwise it is interpreted as a GString not a Spring expression.

As you can see, when accessing configuration settings you use the same dot notation as when you define them.

4.1.1 Options for the yml format Config

application.yml was introduced in Grails 3.0 for an alternative format for the configuration tasks.

Using system properties / command line arguments

Suppose you are using the JDBC_CONNECTION_STRING command line argument and you want to access the same in the yml file then it can be done in the following manner:

production:
    dataSource: 
        url: '${JDBC_CONNECTION_STRING}'

Similarly system arguments can be accessed.

You will need to have this in build.gradle to modify the bootRun target if grails run-app is used to start the application

run {
    systemProperties = System.properties
}

For testing the following will need to change the test task as follows

test { 
    systemProperties = System.properties 
}

4.1.2 Built in options

Grails has a set of core settings that are worth knowing about. Their defaults are suitable for most projects, but it's important to understand what they do because you may need one or more of them later.

Runtime settings

On the runtime front, i.e. grails-app/conf/application.yml, there are quite a few more core settings:

  • grails.enable.native2ascii - Set this to false if you do not require native2ascii conversion of Grails i18n properties files (default: true).
  • grails.views.default.codec - Sets the default encoding regime for GSPs - can be one of 'none', 'html', or 'base64' (default: 'none'). To reduce risk of XSS attacks, set this to 'html'.
  • grails.views.gsp.encoding - The file encoding used for GSP source files (default: 'utf-8').
  • grails.mime.file.extensions - Whether to use the file extension to dictate the mime type in Content Negotiation (default: true).
  • grails.mime.types - A map of supported mime types used for Content Negotiation.
  • grails.serverURL - A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See createLink. Also used by redirects.
  • grails.views.gsp.sitemesh.preprocess - Determines whether SiteMesh preprocessing happens. Disabling this slows down page rendering, but if you need SiteMesh to parse the generated HTML from a GSP view then disabling it is the right option. Don't worry if you don't understand this advanced property: leave it set to true.
  • grails.reload.excludes and grails.reload.includes - Configuring these directives determines the reload behavior for project specific source files. Each directive takes a list of strings that are the class names for project source files that should be excluded from reloading behavior or included accordingly when running the application in development with the run-app command. If the grails.reload.includes directive is configured, then only the classes in that list will be reloaded.

4.1.3 Logging

By default logging in Grails 3.0 is handled by the Logback logging framework and can be configured with the grails-app/conf/logback.groovy file.

If you prefer XML you can replace the logback.groovy file with a logback.xml file instead.

For more information on configuring logging refer to the Logback documentation on the subject.

4.1.4 GORM

Grails provides the following GORM configuration options:
  • grails.gorm.failOnError - If set to true, causes the save() method on domain classes to throw a grails.validation.ValidationException if validation fails during a save. This option may also be assigned a list of Strings representing package names. If the value is a list of Strings then the failOnError behavior will only be applied to domain classes in those packages (including sub-packages). See the save method docs for more information.

For example, to enable failOnError for all domain classes:

grails:
    gorm:
        failOnError: true

and to enable failOnError for domain classes by package:

grails:
    gorm:
        failOnError:
            - com.companyname.somepackage
            - com.companyname.someotherpackage
  • grails.gorm.autoFlush - If set to true, causes the merge, save and delete methods to flush the session, replacing the need to explicitly flush using save(flush: true).

4.2 The Application Class

Every new Grails application features an Application class witin the the grails-app/init directory.

The Application class subclasses the GrailsAutoConfiguration class and features a static void main method, meaning it can be run as a regular application.

4.2.1 Executing the Application Class

There are several ways to execute the Application class, if you are using an IDE then you can simply right click on the class and run it directly from your IDE which will start your Grails application.

This is also useful for debugging since you can debug directly from the IDE without having to connect a remote debugger when using the run-app --debug-jvm command from the command line.

You can also package your application into a runnable WAR file, for example:

$ grails package
$ java -jar build/libs/myapp-0.1.war

This is useful if you plan to deploy your application using a container-less approach.

4.2.2 Customizing the Application Class

There are several ways in which you can customize the Application class.

Customizing Scanning

By default Grails will scan all known source directories for controllers, domain class etc., however if there are packages in other JAR files you wish to scan you can do so by overriding the packageNames() method of the Application class:

class Application extends GrailsAutoConfiguration {
    @Override
    Collection<String> packageNames() {
        super.packageNames() + ['my.additional.package']
    }

… }

Registering Additional Beans

The Application class can also be used as a source for Spring bean definitions, simply define a method annotated with the Bean and the returned object will become a Spring bean. The name of the method is used as the bean name:

class Application extends GrailsAutoConfiguration {
    @Bean
    MyType myBean() {
        return new MyType()
    }

… }

4.2.3 The Application LifeCycle

The Application class also implements the GrailsApplicationLifeCycle interface which all plugins implement.

This means that the Application class can be used to perform the same functions as a plugin. You can override the regular plugins hooks such as doWithSpring, doWithApplicationContext and so on by overriding the appropriate method:

class Application extends GrailsAutoConfiguration {
    @Override
    Closure doWithSpring() {
        {->
            mySpringBean(MyType)
        }
    }

… }

4.3 Environments

Per Environment Configuration

Grails supports the concept of per environment configuration. The application.yml and application.groovy files in the grails-app/conf directory can use per-environment configuration using either YAML or the syntax provided by ConfigSlurper. As an example consider the following default application.yml definition provided by Grails:

environments:
    development:
        dataSource:
            dbCreate: create-drop
            url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    test:
        dataSource:
            dbCreate: update
            url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
    production:
        dataSource:
            dbCreate: update
            url: jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE
        properties:
           jmxEnabled: true
           initialSize: 5
        ...

The above can be expressed in Groovy syntax in application.groovy as follows:

dataSource {
    pooled = false
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
}
environments {
    development {
        dataSource {
            dbCreate = "create-drop"
            url = "jdbc:h2:mem:devDb"
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:mem:testDb"
        }
    }
    production {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:prodDb"
        }
    }
}

Notice how the common configuration is provided at the top level and then an environments block specifies per environment settings for the dbCreate and url properties of the DataSource.

Packaging and Running for Different Environments

Grails' command line has built in capabilities to execute any command within the context of a specific environment. The format is:

grails [environment] [command name]

In addition, there are 3 preset environments known to Grails: dev, prod, and test for development, production and test. For example to create a WAR for the test environment you wound run:

grails test war

To target other environments you can pass a grails.env variable to any command:

grails -Dgrails.env=UAT run-app

Programmatic Environment Detection

Within your code, such as in a Gant script or a bootstrap class you can detect the environment using the Environment class:

import grails.util.Environment

...

switch (Environment.current) { case Environment.DEVELOPMENT: configureForDevelopment() break case Environment.PRODUCTION: configureForProduction() break }

Per Environment Bootstrapping

It's often desirable to run code when your application starts up on a per-environment basis. To do so you can use the grails-app/conf/BootStrap.groovy file's support for per-environment execution:

def init = { ServletContext ctx ->
    environments {
        production {
            ctx.setAttribute("env", "prod")
        }
        development {
            ctx.setAttribute("env", "dev")
        }
    }
    ctx.setAttribute("foo", "bar")
}

Generic Per Environment Execution

The previous BootStrap example uses the grails.util.Environment class internally to execute. You can also use this class yourself to execute your own environment specific logic:

Environment.executeForCurrentEnvironment {
    production {
        // do something in production
    }
    development {
        // do something only in development
    }
}

4.4 The DataSource

Since Grails is built on Java technology setting up a data source requires some knowledge of JDBC (the technology that doesn't stand for Java Database Connectivity).

If you use a database other than H2 you need a JDBC driver. For example for MySQL you would need Connector/J.

Drivers typically come in the form of a JAR archive. It's best to use the dependency resolution to resolve the jar if it's available in a Maven repository, for example you could add a dependency for the MySQL driver like this:

dependencies {
    runtime 'mysql:mysql-connector-java:5.1.29'
}

If you can't use dependency resolution then just put the JAR in your project's lib directory.

Once you have the JAR resolved you need to get familiar with how Grails manages its database configuration. The configuration can be maintained in either grails-app/conf/application.groovy or grails-app/conf/application.yml. These files contain the dataSource definition which includes the following settings:

  • driverClassName - The class name of the JDBC driver
  • username - The username used to establish a JDBC connection
  • password - The password used to establish a JDBC connection
  • url - The JDBC URL of the database
  • dbCreate - Whether to auto-generate the database from the domain model - one of 'create-drop', 'create', 'update' or 'validate'
  • pooled - Whether to use a pool of connections (defaults to true)
  • logSql - Enable SQL logging to stdout
  • formatSql - Format logged SQL
  • dialect - A String or Class that represents the Hibernate dialect used to communicate with the database. See the org.hibernate.dialect package for available dialects.
  • readOnly - If true makes the DataSource read-only, which results in the connection pool calling setReadOnly(true) on each Connection
  • transactional - If false leaves the DataSource's transactionManager bean outside the chained BE1PC transaction manager implementation. This only applies to additional datasources.
  • persistenceInterceptor - The default datasource is automatically wired up to the persistence interceptor, other datasources are not wired up automatically unless this is set to true
  • properties - Extra properties to set on the DataSource bean. See the Tomcat Pool documentation. There is also a Javadoc format documentation of the properties.
  • jmxExport - If false, will disable registration of JMX MBeans for all DataSources. By default JMX MBeans are added for DataSources with jmxEnabled = true in properties.

A typical configuration for MySQL in application.groovy may be something like:

dataSource {
    pooled = true
    dbCreate = "update"
    url = "jdbc:mysql://localhost:3306/my_database"
    driverClassName = "com.mysql.jdbc.Driver"
    dialect = org.hibernate.dialect.MySQL5InnoDBDialect
    username = "username"
    password = "password"
    properties {
       jmxEnabled = true
       initialSize = 5
       maxActive = 50
       minIdle = 5
       maxIdle = 25
       maxWait = 10000
       maxAge = 10 * 60000
       timeBetweenEvictionRunsMillis = 5000
       minEvictableIdleTimeMillis = 60000
       validationQuery = "SELECT 1"
       validationQueryTimeout = 3
       validationInterval = 15000
       testOnBorrow = true
       testWhileIdle = true
       testOnReturn = false
       jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
       defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED
    }
}

When configuring the DataSource do not include the type or the def keyword before any of the configuration settings as Groovy will treat these as local variable definitions and they will not be processed. For example the following is invalid:

dataSource {
    boolean pooled = true // type declaration results in ignored local variable
    …
}

Example of advanced configuration using extra properties:

dataSource {
    pooled = true
    dbCreate = "update"
    url = "jdbc:mysql://localhost:3306/my_database"
    driverClassName = "com.mysql.jdbc.Driver"
    dialect = org.hibernate.dialect.MySQL5InnoDBDialect
    username = "username"
    password = "password"
    properties {
       // Documentation for Tomcat JDBC Pool
       // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Common_Attributes
       // https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/tomcat/jdbc/pool/PoolConfiguration.html
       jmxEnabled = true
       initialSize = 5
       maxActive = 50
       minIdle = 5
       maxIdle = 25
       maxWait = 10000
       maxAge = 10 * 60000
       timeBetweenEvictionRunsMillis = 5000
       minEvictableIdleTimeMillis = 60000
       validationQuery = "SELECT 1"
       validationQueryTimeout = 3
       validationInterval = 15000
       testOnBorrow = true
       testWhileIdle = true
       testOnReturn = false
       ignoreExceptionOnPreLoad = true
       // http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#JDBC_interceptors
       jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
       defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED // safe default
       // controls for leaked connections 
       abandonWhenPercentageFull = 100 // settings are active only when pool is full
       removeAbandonedTimeout = 120
       removeAbandoned = true
       // use JMX console to change this setting at runtime
       logAbandoned = false // causes stacktrace recording overhead, use only for debugging
       // JDBC driver properties
       // Mysql as example
       dbProperties {
           // Mysql specific driver properties
           // http://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
           // let Tomcat JDBC Pool handle reconnecting
           autoReconnect=false
           // truncation behaviour 
           jdbcCompliantTruncation=false
           // mysql 0-date conversion
           zeroDateTimeBehavior='convertToNull'
           // Tomcat JDBC Pool's StatementCache is used instead, so disable mysql driver's cache
           cachePrepStmts=false
           cacheCallableStmts=false
           // Tomcat JDBC Pool's StatementFinalizer keeps track
           dontTrackOpenResources=true
           // performance optimization: reduce number of SQLExceptions thrown in mysql driver code
           holdResultsOpenOverStatementClose=true
           // enable MySQL query cache - using server prep stmts will disable query caching
           useServerPrepStmts=false
           // metadata caching
           cacheServerConfiguration=true
           cacheResultSetMetadata=true
           metadataCacheSize=100
           // timeouts for TCP/IP
           connectTimeout=15000
           socketTimeout=120000
           // timer tuning (disable)
           maintainTimeStats=false
           enableQueryTimeouts=false
           // misc tuning
           noDatetimeStringSync=true
       }
    }
}

More on dbCreate

Hibernate can automatically create the database tables required for your domain model. You have some control over when and how it does this through the dbCreate property, which can take these values:

  • create - Drops the existing schema and creates the schema on startup, dropping existing tables, indexes, etc. first.
  • create-drop - Same as create, but also drops the tables when the application shuts down cleanly.
  • update - Creates missing tables and indexes, and updates the current schema without dropping any tables or data. Note that this can't properly handle many schema changes like column renames (you're left with the old column containing the existing data).
  • validate - Makes no changes to your database. Compares the configuration with the existing database schema and reports warnings.
  • any other value - does nothing

You can also remove the dbCreate setting completely, which is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like Liquibase (the Database Migration plugin uses Liquibase and is tightly integrated with Grails and GORM).

4.4.1 DataSources and Environments

The previous example configuration assumes you want the same config for all environments: production, test, development etc.

Grails' DataSource definition is "environment aware", however, so you can do:

dataSource {
    pooled = true
    driverClassName = "com.mysql.jdbc.Driver"
    dialect = org.hibernate.dialect.MySQL5InnoDBDialect
    // other common settings here
}

environments { production { dataSource { url = "jdbc:mysql://liveip.com/liveDb" // other environment-specific settings here } } }

4.4.2 Automatic Database Migration

The dbCreate property of the DataSource definition is important as it dictates what Grails should do at runtime with regards to automatically generating the database tables from GORM classes. The options are described in the DataSource section:
  • create
  • create-drop
  • update
  • validate
  • no value

In development mode dbCreate is by default set to "create-drop", but at some point in development (and certainly once you go to production) you'll need to stop dropping and re-creating the database every time you start up your server.

It's tempting to switch to update so you retain existing data and only update the schema when your code changes, but Hibernate's update support is very conservative. It won't make any changes that could result in data loss, and doesn't detect renamed columns or tables, so you'll be left with the old one and will also have the new one.

Grails supports migrations with Flyway or Liquibase using the same mechanism provided by Spring Boot.

4.4.3 Transaction-aware DataSource Proxy

The actual dataSource bean is wrapped in a transaction-aware proxy so you will be given the connection that's being used by the current transaction or Hibernate Session if one is active.

If this were not the case, then retrieving a connection from the dataSource would be a new connection, and you wouldn't be able to see changes that haven't been committed yet (assuming you have a sensible transaction isolation setting, e.g. READ_COMMITTED or better).

The "real" unproxied dataSource is still available to you if you need access to it; its bean name is dataSourceUnproxied.

You can access this bean like any other Spring bean, i.e. using dependency injection:

class MyService {

def dataSourceUnproxied … }

or by pulling it from the ApplicationContext:

def dataSourceUnproxied = ctx.dataSourceUnproxied

4.4.4 Database Console

The H2 database console is a convenient feature of H2 that provides a web-based interface to any database that you have a JDBC driver for, and it's very useful to view the database you're developing against. It's especially useful when running against an in-memory database.

You can access the console by navigating to http://localhost:8080/dbconsole in a browser. The URI can be configured using the grails.dbconsole.urlRoot attribute in application.groovy and defaults to '/dbconsole'.

The console is enabled by default in development mode and can be disabled or enabled in other environments by using the grails.dbconsole.enabled attribute in application.groovy. For example, you could enable the console in production like this:

environments {
    production {
        grails.serverURL = "http://www.changeme.com"
        grails.dbconsole.enabled = true
        grails.dbconsole.urlRoot = '/admin/dbconsole'
    }
    development {
        grails.serverURL = "http://localhost:8080/${appName}"
    }
    test {
        grails.serverURL = "http://localhost:8080/${appName}"
    }
}

If you enable the console in production be sure to guard access to it using a trusted security framework.

Configuration

By default the console is configured for an H2 database which will work with the default settings if you haven't configured an external database - you just need to change the JDBC URL to jdbc:h2:mem:devDB. If you've configured an external database (e.g. MySQL, Oracle, etc.) then you can use the Saved Settings dropdown to choose a settings template and fill in the url and username/password information from your application.groovy.

4.4.5 Multiple Datasources

By default all domain classes share a single DataSource and a single database, but you have the option to partition your domain classes into two or more DataSources.

Configuring Additional DataSources

The default DataSource configuration in grails-app/conf/application.yml looks something like this:

---
dataSource:
    pooled: true
    jmxExport: true
    driverClassName: org.h2.Driver
    username: sa
    password:

environments: development: dataSource: dbCreate: create-drop url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE test: dataSource: dbCreate: update url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE production: dataSource: dbCreate: update url: jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE properties: jmxEnabled: true initialSize: 5

This configures a single DataSource with the Spring bean named dataSource. To configure extra DataSources, add a dataSources block (at the top level, in an environment block, or both, just like the standard DataSource definition) with a custom name. For example, this configuration adds a second DataSource, using MySQL in the development environment and Oracle in production:

---
dataSources:
    dataSource:
        pooled: true
        jmxExport: true
        driverClassName: org.h2.Driver
        username: sa
        password:
    lookup:
        dialect: org.hibernate.dialect.MySQLInnoDBDialect
        driverClassName: com.mysql.jdbc.Driver
        username: lookup
        password: secret
        url: jdbc:mysql://localhost/lookup
        dbCreate: update

environments: development: dataSources: dataSource: dbCreate: create-drop url: jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE test: dataSources: dataSource: dbCreate: update url: jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE production: dataSources: dataSource: dbCreate: update url: jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE properties: jmxEnabled: true initialSize: 5 … lookup: dialect: org.hibernate.dialect.Oracle10gDialect driverClassName: oracle.jdbc.driver.OracleDriver username: lookup password: secret url: jdbc:oracle:thin:@localhost:1521:lookup dbCreate: update

You can use the same or different databases as long as they're supported by Hibernate.

Configuring Domain Classes

If a domain class has no DataSource configuration, it defaults to the standard 'dataSource'. Set the datasource property in the mapping block to configure a non-default DataSource. For example, if you want to use the ZipCode domain to use the 'lookup' DataSource, configure it like this:

class ZipCode {

String code

static mapping = { datasource 'lookup' } }

A domain class can also use two or more DataSources. Use the datasources property with a list of names to configure more than one, for example:

class ZipCode {

String code

static mapping = { datasources(['lookup', 'auditing']) } }

If a domain class uses the default DataSource and one or more others, use the special name 'DEFAULT' to indicate the default DataSource:

class ZipCode {

String code

static mapping = { datasources(['lookup', 'DEFAULT']) } }

If a domain class uses all configured DataSources use the special value 'ALL':

class ZipCode {

String code

static mapping = { datasource 'ALL' } }

Namespaces and GORM Methods

If a domain class uses more than one DataSource then you can use the namespace implied by each DataSource name to make GORM calls for a particular DataSource. For example, consider this class which uses two DataSources:

class ZipCode {

String code

static mapping = { datasources(['lookup', 'auditing']) } }

The first DataSource specified is the default when not using an explicit namespace, so in this case we default to 'lookup'. But you can call GORM methods on the 'auditing' DataSource with the DataSource name, for example:

def zipCode = ZipCode.auditing.get(42)
…
zipCode.auditing.save()

As you can see, you add the DataSource to the method call in both the static case and the instance case.

Hibernate Mapped Domain Classes

You can also partition annotated Java classes into separate datasources. Classes using the default datasource are registered in grails-app/conf/hibernate.cfg.xml. To specify that an annotated class uses a non-default datasource, create a hibernate.cfg.xml file for that datasource with the file name prefixed with the datasource name.

For example if the Book class is in the default datasource, you would register that in grails-app/conf/hibernate.cfg.xml:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          '-//Hibernate/Hibernate Configuration DTD 3.0//EN'
          'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
<hibernate-configuration>
   <session-factory>
      <mapping class='org.example.Book'/>
   </session-factory>
</hibernate-configuration>

and if the Library class is in the "ds2" datasource, you would register that in grails-app/conf/ds2_hibernate.cfg.xml:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          '-//Hibernate/Hibernate Configuration DTD 3.0//EN'
          'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'>
<hibernate-configuration>
   <session-factory>
      <mapping class='org.example.Library'/>
   </session-factory>
</hibernate-configuration>

The process is the same for classes mapped with hbm.xml files - just list them in the appropriate hibernate.cfg.xml file.

Services

Like Domain classes, by default Services use the default DataSource and PlatformTransactionManager. To configure a Service to use a different DataSource, use the static datasource property, for example:

class DataService {

static datasource = 'lookup'

void someMethod(...) { … } }

A transactional service can only use a single DataSource, so be sure to only make changes for domain classes whose DataSource is the same as the Service.

Note that the datasource specified in a service has no bearing on which datasources are used for domain classes; that's determined by their declared datasources in the domain classes themselves. It's used to declare which transaction manager to use.

What you'll see is that if you have a Foo domain class in dataSource1 and a Bar domain class in dataSource2, and WahooService uses dataSource1, a service method that saves a new Foo and a new Bar will only be transactional for Foo since they share the datasource. The transaction won't affect the Bar instance. If you want both to be transactional you'd need to use two services and XA datasources for two-phase commit, e.g. with the Atomikos plugin.

Transactions across multiple datasources

Grails uses the Best Efforts 1PC pattern for handling transactions across multiple datasources.

The Best Efforts 1PC pattern is fairly general but can fail in some circumstances that the developer must be aware of. This is a non-XA pattern that involves a synchronized single-phase commit of a number of resources. Because the 2PC is not used, it can never be as safe as an XA transaction, but is often good enough if the participants are aware of the compromises.

The basic idea is to delay the commit of all resources as late as possible in a transaction so that the only thing that can go wrong is an infrastructure failure (not a business-processing error). Systems that rely on Best Efforts 1PC reason that infrastructure failures are rare enough that they can afford to take the risk in return for higher throughput. If business-processing services are also designed to be idempotent, then little can go wrong in practice.

The BE1PC implementation was added in Grails 2.3.6. . Before this change additional datasources didn't take part in transactions initiated in Grails. The transactions in additional datasources were basically in auto commit mode. In some cases this might be the wanted behavior. One reason might be performance: on the start of each new transaction, the BE1PC transaction manager creates a new transaction to each datasource. It's possible to leave an additional datasource out of the BE1PC transaction manager by setting transactional = false in the respective configuration block of the additional dataSource. Datasources with readOnly = true will also be left out of the chained transaction manager (since 2.3.7).

By default, the BE1PC implementation will add all beans implementing the Spring PlatformTransactionManager interface to the chained BE1PC transaction manager. For example, a possible JMSTransactionManager bean in the Grails application context would be added to the Grails BE1PC transaction manager's chain of transaction managers.

You can exclude transaction manager beans from the BE1PC implementation with the this configuration option:

grails.transaction.chainedTransactionManagerPostProcessor.blacklistPattern = '.*'
The exclude matching is done on the name of the transaction manager bean. The transaction managers of datasources with transactional = false or readOnly = true will be skipped and using this configuration option is not required in that case.

XA and Two-phase Commit

When the Best Efforts 1PC pattern isn't suitable for handling transactions across multiple transactional resources (not only datasources), there are several options available for adding XA/2PC support to Grails applications.

The Spring transactions documentation contains information about integrating the JTA/XA transaction manager of different application servers. In this case, you can configure a bean with the name transactionManager manually in resources.groovy or resources.xml file.

There is also Atomikos plugin available for XA support in Grails applications.

4.5 Versioning

Detecting Versions at Runtime

You can detect the application version using Grails' support for application metadata using the GrailsApplication class. For example within controllers there is an implicit grailsApplication variable that can be used:

def version = grailsApplication.metadata.getApplicationVersion()

You can retrieve the version of Grails that is running with:

def grailsVersion = grailsApplication.metadata.getGrailsVersion()

or the GrailsUtil class:

import grails.util.GrailsUtil
…
def grailsVersion = GrailsUtil.grailsVersion

4.6 Project Documentation

Since Grails 1.2, the documentation engine that powers the creation of this documentation has been available for your own Grails projects.

The documentation engine uses a variation on the Textile syntax to automatically create project documentation with smart linking, formatting etc.

Creating project documentation

To use the engine you need to follow a few conventions. First, you need to create a src/docs/guide directory where your documentation source files will go. Then, you need to create the source docs themselves. Each chapter should have its own gdoc file as should all numbered sub-sections. You will end up with something like:

+ src/docs/guide/introduction.gdoc
+ src/docs/guide/introduction/changes.gdoc
+ src/docs/guide/gettingStarted.gdoc
+ src/docs/guide/configuration.gdoc
+ src/docs/guide/configuration/build.gdoc
+ src/docs/guide/configuration/build/controllers.gdoc

Note that you can have all your gdoc files in the top-level directory if you want, but you can also put sub-sections in sub-directories named after the parent section - as the above example shows.

Once you have your source files, you still need to tell the documentation engine what the structure of your user guide is going to be. To do that, you add a src/docs/guide/toc.yml file that contains the structure and titles for each section. This file is in YAML format and basically represents the structure of the user guide in tree form. For example, the above files could be represented as:

introduction:
  title: Introduction
  changes: Change Log
gettingStarted: Getting Started
configuration:
  title: Configuration
  build:
    title: Build Config
    controllers: Specifying Controllers

The format is pretty straightforward. Any section that has sub-sections is represented with the corresponding filename (minus the .gdoc extension) followed by a colon. The next line should contain title: plus the title of the section as seen by the end user. Every sub-section then has its own line after the title. Leaf nodes, i.e. those without any sub-sections, declare their title on the same line as the section name but after the colon.

That's it. You can easily add, remove, and move sections within the toc.yml to restructure the generated user guide. You should also make sure that all section names, i.e. the gdoc filenames, should be unique since they are used for creating internal links and for the HTML filenames. Don't worry though, the documentation engine will warn you of duplicate section names.

Creating reference items

Reference items appear in the Quick Reference section of the documentation. Each reference item belongs to a category and a category is a directory located in the src/docs/ref directory. For example, suppose you have defined a new controller method called renderPDF. That belongs to the Controllers category so you would create a gdoc text file at the following location:

+ src/docs/ref/Controllers/renderPDF.gdoc

Configuring Output Properties

There are various properties you can set within your grails-app/conf/application.groovy file that customize the output of the documentation such as:

  • grails.doc.title - The title of the documentation
  • grails.doc.subtitle - The subtitle of the documentation
  • grails.doc.authors - The authors of the documentation
  • grails.doc.license - The license of the software
  • grails.doc.copyright - The copyright message to display
  • grails.doc.footer - The footer to use

Other properties such as the version are pulled from your project itself. If a title is not specified, the application name is used.

You can also customise the look of the documentation and provide images by setting a few other options:

  • grails.doc.css - The location of a directory containing custom CSS files (type java.io.File)
  • grails.doc.js - The location of a directory containing custom JavaScript files (type java.io.File)
  • grails.doc.style - The location of a directory containing custom HTML templates for the guide (type java.io.File)
  • grails.doc.images - The location of a directory containing image files for use in the style templates and within the documentation pages themselves (type java.io.File)

One of the simplest ways to customise the look of the generated guide is to provide a value for grails.doc.css and then put a custom.css file in the corresponding directory. Grails will automatically include this CSS file in the guide. You can also place a custom-pdf.css file in that directory. This allows you to override the styles for the PDF version of the guide.

Generating Documentation

Add the plugin in your build.gradle:

apply plugin: "org.grails.grails-doc"

Once you have created some documentation (refer to the syntax guide in the next chapter) you can generate an HTML version of the documentation using the command:

gradle docs

This command will output an docs/manual/index.html which can be opened in a browser to view your documentation.

Documentation Syntax

As mentioned the syntax is largely similar to Textile or Confluence style wiki markup. The following sections walk you through the syntax basics.

Basic Formatting

Monospace: monospace

@monospace@

Italic: italic

_italic_

Bold: bold

*bold*

Image:

!http://grails.org/images/new/grailslogo_topNav.png!

You can also link to internal images like so:

!someFolder/my_diagram.png!

This will link to an image stored locally within your project. There is currently no default location for doc images, but you can specify one with the grails.doc.images setting in application.groovy like so:

grails.doc.images = new File("src/docs/images")

In this example, you would put the my_diagram.png file in the directory 'src/docs/images/someFolder'.

Linking

There are several ways to create links with the documentation generator. A basic external link can either be defined using confluence or textile style markup:

[Pivotal|http://www.pivotal.io/oss]

or

"Pivotal":http://www.pivotal.io/oss

For links to other sections inside the user guide you can use the guide: prefix with the name of the section you want to link to:

[Intro|guide:introduction]

The section name comes from the corresponding gdoc filename. The documentation engine will warn you if any links to sections in your guide break.

To link to reference items you can use a special syntax:

[renderPDF|controllers]

In this case the category of the reference item is on the right hand side of the | and the name of the reference item on the left.

Finally, to link to external APIs you can use the api: prefix. For example:

[String|api:java.lang.String]

The documentation engine will automatically create the appropriate javadoc link in this case. To add additional APIs to the engine you can configure them in grails-app/conf/application.groovy. For example:

grails.doc.api.org.hibernate=
            "http://docs.jboss.org/hibernate/stable/core/javadocs"

The above example configures classes within the org.hibernate package to link to the Hibernate website's API docs.

Lists and Headings

Headings can be created by specifying the letter 'h' followed by a number and then a dot:

h3.<space>Heading3
h4.<space>Heading4

Unordered lists are defined with the use of the * character:

* item 1
** subitem 1
** subitem 2
* item 2

Numbered lists can be defined with the # character:

# item 1

Tables can be created using the table macro:

NameNumber
Albert46
Wilma1348
James12

{table}
 *Name* | *Number*
 Albert | 46
 Wilma | 1348
 James | 12
{table}

Code and Notes

You can define code blocks with the code macro:

class Book {
    String title
}

{code}
class Book {
    String title
}
{code}

The example above provides syntax highlighting for Java and Groovy code, but you can also highlight XML markup:

<hello>world</hello>

{code:xml}
<hello>world</hello>
{code}

There are also a couple of macros for displaying notes and warnings:

Note:

This is a note!

{note}
This is a note!
{note}

Warning:

This is a warning!

{warning}
This is a warning!
{warning}

4.7 Dependency Resolution

Dependency resolution is handled by the Gradle build tool, all dependencies are defined in the build.gradle file. Refer to the Gradle user guide for more information.