Table of Contents

1. Introduction
2. Getting Started
2.1 Downloading and Installing
2.2 Creating an Application
2.3 A Hello World Example
2.4 Getting Set-up in an IDE
2.5 Convention over Configuration
2.6 Running an Application
2.7 Testing an Application
2.8 Deploying an Application
2.9 Supported Java EE Containers
2.10 Creating Artefacts
2.11 Generating an Application
3. Configuration
3.1 Basic Configuration
3.1.1 Built in options
3.1.2 Logging
3.2 Environments
3.3 The DataSource
3.3.1 DataSources and Environments
3.3.2 JNDI DataSources
3.3.3 Automatic Database Migration
3.4 Externalized Configuration
3.5 Versioning
4. The Command Line
4.1 Creating Gant Scripts
4.2 Re-using Grails scripts
4.3 Hooking into Events
4.4 Ant and Maven
5. Object Relational Mapping (GORM)
5.1 Quick Start Guide
5.1.1 Basic CRUD
5.2 Domain Modelling in GORM
5.2.1 Association in GORM
5.2.1.1 One-to-one
5.2.1.2 One-to-many
5.2.1.3 Many-to-many
5.2.2 Composition in GORM
5.2.3 Inheritance in GORM
5.2.4 Sets, Lists and Maps
5.3 Persistence Basics
5.3.1 Saving and Updating
5.3.2 Deleting Objects
5.3.3 Understanding Cascading Updates and Deletes
5.3.4 Eager and Lazy Fetching
5.3.5 Pessimistic and Optimistic Locking
5.4 Querying with GORM
5.4.1 Dynamic Finders
5.4.2 Criteria
5.4.3 Hibernate Query Language (HQL)
5.5 Advanced GORM Features
5.5.1 Events and Auto Timestamping
5.5.2 Custom ORM Mapping
5.5.2.1 Table and Column Names
5.5.2.2 Caching Strategy
5.5.2.3 Inheritance Strategies
5.5.2.4 Custom Database Identity
5.5.2.5 Composite Primary Keys
5.5.2.6 Database Indices
5.5.2.7 Optimistic Locking and Versioning
5.5.2.8 Eager and Lazy Fetching
5.5.2.9 Custom Cascade Behaviour
5.6 Programmatic Transactions
5.7 GORM and Constraints
6. The Web Layer
6.1 Controllers
6.1.1 Understanding Controllers and Actions
6.1.2 Controllers and Scopes
6.1.3 Models and Views
6.1.4 Redirects and Chaining
6.1.5 Controller Interceptors
6.1.6 Data Binding
6.1.7 XML and JSON Responses
6.1.8 Uploading Files
6.1.9 Command Objects
6.2 Groovy Server Pages
6.2.1 GSP Basics
6.2.1.1 Variables and Scopes
6.2.1.2 Logic and Iteration
6.2.1.3 Page Directives
6.2.1.4 Expressions
6.2.2 GSP Tags
6.2.2.1 Variables and Scopes
6.2.2.2 Logic and Iteration
6.2.2.3 Search and Filtering
6.2.2.4 Links and Resources
6.2.2.5 Forms and Fields
6.2.2.6 Tags as Method Calls
6.2.3 Views and Templates
6.2.4 Layouts with Sitemesh
6.3 Tag Libraries
6.3.1 Simple Tags
6.3.2 Logical Tags
6.3.3 Iterative Tags
6.3.4 Tag Namespaces
6.4 URL Mappings
6.4.1 Mapping to Controllers and Actions
6.4.2 Embedded Variables
6.4.3 Mapping to Views
6.4.4 Mapping to Response Codes
6.4.5 Mapping to HTTP methods
6.4.6 Mapping Wildcards
6.4.7 Automatic Link Re-Writing
6.4.8 Applying Constraints
6.5 Web Flow
6.5.1 Start and End States
6.5.2 Action States and View States
6.5.3 Flow Execution Events
6.5.4 Flow Scopes
6.5.5 Data Binding and Validation
6.5.6 Subflows and Conversations
6.6 Filters
6.6.1 Applying Filters
6.6.2 Filter Types
6.6.3 Filter Capabilities
6.7 Ajax
6.7.1 Ajax using Prototype
6.7.1.1 Remoting Linking
6.7.1.2 Updating Content
6.7.1.3 Remote Form Submission
6.7.1.4 Ajax Events
6.7.2 Ajax with Dojo
6.7.3 Ajax with GWT
6.7.4 Ajax on the Server
6.8 Content Negotiation
7. Validation
7.1 Declaring Constraints
7.2 Validating Constraints
7.3 Validation on the Client
7.4 Validation and Internationalization
8. The Service Layer
8.1 Declarative Transactions
8.2 Scoped Services
8.3 Dependency Injection and Services
8.4 Using Services from Java
9. Testing
9.1 Unit Testing
9.2 Integration Testing
9.3 Functional Testing
10. Internationalization
10.1 Understanding Message Bundles
10.2 Changing Locales
10.3 Reading Messages
11. Security
11.1 Securing Against Attacks
11.2 Encoding and Decoding Strings
11.3 Authentication
11.4 Security Plug-ins
11.4.1 Acegi
11.4.2 JSecurity
12. Plug-ins
12.1 Creating and Installing Plug-ins
12.2 Understanding a Plug-ins Structure
12.3 Providing Basic Artefacts
12.4 Evaluating Conventions
12.5 Hooking into Build Events
12.6 Hooking into Runtime Configuration
12.7 Adding Dynamic Methods at Runtime
12.8 Participating in Auto Reload Events
12.9 Understanding Plug-in Load Order
13. Web Services
13.1 REST
13.2 SOAP
13.3 RSS and Atom
14. Grails and Spring
14.1 The Underpinnings of Grails
14.2 Configuring Additional Beans
14.3 Runtime Spring with the Beans DSL
14.4 Property Placeholder Configuration
14.5 Property Override Configuration
15. Grails and Hibernate
15.1 Mapping with Hibernate Annotations
15.2 Further Reading
16. Scaffolding
17. Deployment

1. Introduction

Java web development as it stands today is dramatically more complicated than it needs to be. Most modern web frameworks in the Java space are over complicated and don't embrace the Don't Repeat Yourself (DRY) principals.

Dynamic frameworks like Rails, Django and TurboGears helped pave the way to a more modern way of thinking about web applications. Grails builds on these concepts and dramatically reduces the complexity of building web applications on the Java platform. What makes it different, however, is that it does so by building on already established Java technology like Spring & Hibernate.

Grails is a full stack framework and attempts to solve as many pieces of the web development puzzle through the core technology and it's associated plug-ins. Included out the box are things like:

All of these are made easy to use through the power of the Groovy language and the extensive use of Domain Specific Languages (DSLs)

This documentation will take you through getting started with Grails and building web applications with the Grails framework.

2. Getting Started

2.1 Downloading and Installing

The first step to getting up and running with Grails is to install the distribution. To do so follow these steps:

If Grails is working correctly you should now be able to type grails in the terminal window and see output similar to the below:


Welcome to Grails 1.0 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: /Developer/grails-1.0
No script name specified. Use 'grails help' for more info

2.2 Creating an Application

To create a Grails application you first need to familiarize yourself with the usage of the grails command which is used in the following manner:

grails [command name]

In this case the command you need to execute is create-app:


grails create-app helloworld

This will create a new directory inside the current one that contains the project. You should now navigate to this directory in terminal:


cd helloworld

2.3 A Hello World Example

To implement the typical "hello world!" example run the create-controller command:


grails create-controller hello  

This will create a new controller (Refer to the section on Controllers for more information) in the grails-app/controllers directory called HelloController.groovy.

Controllers are capable of dealing with web requests and to fulfil the "hello world!" use case our implementation needs to look like the following:

class HelloController {
	def world = {
		render "Hello World!"
	}
}

Job done. Now start-up the container with another new command called run-app:


grails run-app

This will start-up a server on port 8080 and you should now be able to access your application with the URL: http://localhost:8080/helloworld

The result will look something like the following screenshot:

This is the Grails intro page which is rendered by the web-app/index.gsp file. You will note it has a detected the presence of your controller and clicking on the link to our controller we can see the text "Hello World!" printed to the browser window.

2.4 Getting Set-up in an IDE

IntelliJ IDEA

Currently by far the most mature and comprehensive Groovy & Grails IDE is IntelliJ IDEA 7.0 and the JetGroovy plug-in. The Grails team recommends IDEA over other IDE environments for large projects.

TextMate

Since Grails' focus is on simplicity it is often possible to utilize more simple editors and TextMate on the Mac has an excellent Groovy/Grails bundle available from the Texmate bundles SVN.

Eclipse

For Eclipse there is also the Groovy Eclipse Plugin that offers syntax highlighting, code completion and so on.

There are some quirks with the Groovy Eclipse plug-in which are covered in detail on the Grails wiki.

Grails automatically creates Eclipse .project and classpath files for you, so to import a Grails project just right-click in the "Package Explorer" and select "Import" then "Existing project into Workspace" and "Browse" to the location of your project.

Then immediately click "Ok" followed by "Finish" and your project will be set-up.

Grails will also automatically set-up an appropriate Eclipse "Run Configuration", that can be accessed from the "Run" menu in Eclipse.

2.5 Convention over Configuration

Grails uses "convention over configuration" to configure itself. This typically means that the name and location of files is used instead of explicit configuration, hence you need to familiarize yourself with the directory structure provided by Grails.

Here is a breakdown and links to the relevant sections:

2.6 Running an Application

Grails applications can be run with the built in Jetty server using the run-app command which will load a server on port 8080 by default:

grails run-app

You can specify a different port by using the server.port argument:

grails -Dserver.port=8090 run-app

More information on the run-app command can be found in the reference guide.

2.7 Testing an Application

The create-* commands in Grails automatically create integration tests for you within the test/integration directory. It is of course up to you to populate these tests with valid test logic, information on which can be found in the section on Testing. However, if you wish to execute tests you can run the test-app command as follows:

grails test-app

Grails also automatically generates an Ant build.xml which can also run the tests by delegating to Grails' test-app command:

ant test

This is useful when you need to build Grails applications as part of a continuous integration platform such as CruiseControl.

2.8 Deploying an Application

Grails applications are deployed as Web Application Archives (WAR files), and Grails includes the war command for performing this task:

grails war

This will produce a WAR file in the root of your project which can then be deployed as per your containers instructions.

NEVER deploy Grails using the run-app command as this command sets Grails up for auto-reloading at runtime which has a severe performance and scalability implication

When deploying Grails you should always run your containers JVM with the -server option and with sufficient memory allocation. A good set of VM flags would be:

-server -Xmx512M

2.9 Supported Java EE Containers

Grails supports a pretty wide range of containers including:

Some containers have bugs however, which in most cases can be worked around. A list of known deployment issues can be found on the Grails wiki.

2.10 Creating Artefacts

Grails ships with a few convenience targets such as create-controller, create-domain-class and so on that will create Controllers and different artefact types for you.
These are merely for your convenience and you can just as easily use an IDE or your favourite text editor.
For example to create the basis of an application you typically need a domain model:

grails create-domain-class book

This will result in the creation of a domain class at grails-app/domain/Book.groovy such as:

class Book {	
}

There are many such create-* commands that can be explored in the command line reference guide.

2.11 Generating an Application

To get started quickly with Grails it is often useful to use a feature called Scaffolding to generate the skeleton of an application. To do this use one of the generate-* commands such as generate-all, which will generate a controller and the relevant views:

grails generate-all Book

3. Configuration

It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now, but since what configuration there is typically a one off, it is best to get it out the way.

With Grails' default settings you can actually develop and application without doing any configuration whatsoever. Grails ships with an embedded container and in-memory HSQLDB meaning there isn't even a database to set-up.

However, typically you want to set-up a real database at some point and the way you do that is described in the following section.

3.1 Basic Configuration

For general configuration Grails provides a file called grails-app/conf/Config.groovy. This file uses Groovy's ConfigSlurper which is very similar to Java properties files except it is pure Groovy hence you can re-use variables and use proper Java types!

You can add your own configuration in here, for example:

foo.bar.hello = "world"

Then later in your application you can access these settings in one of two ways. The most common is via the GrailsApplication object, which is available as a variable in controllers and tag libraries:

assert "world" == grailsApplication.config.foo.bar.hello

The other way involves getting a reference to the ConfigurationHolder class that holds a reference to the configuration object:

import org.codehaus.groovy.grails.commons.*
…
def config = ConfigurationHolder.config
assert "world" == config.foo.bar.hello

3.1.1 Built in options

Grails also provides the following configuration options:

War generation

For more information on using these options, see the section on deployment

3.1.2 Logging

Logging Basics

Grails uses its common configuration mechanism to configure the underlying Log4j log system. To configure logging you must modify the file Config.groovy located in the grails-app/conf directory. This single Config.groovy file allows you to specify separate logging configurations for development, test, and production environments. Grails processes the Config.groovy file and generates the appropriate log4j.properties file in the web-app/WEB-INF/classes directory.

An example of a typical Log4j configuration in Grails is as follows:

log4j {
    appender.stdout = "org.apache.log4j.ConsoleAppender"
	appender.'stdout.layout'="org.apache.log4j.PatternLayout"
    rootLogger="error,stdout"
    logger {
        grails="info,stdout"
        org {
            grails.spring="info,stdout"
            codehaus.groovy.grails.web="info,stdout"
            codehaus.groovy.grails.commons="info,stdout"
            …
        }
}
}

If you prefer to use standard Log4j properties file style configuration you can use a Groovy multiline String instead:

log4j = '''
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# ...remaining configuration
'''

Some useful loggers include:

Full stacktraces

When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Grails filters these typically irrelevant details and restricts traces to non-core Grails/Groovy class packages.

When this happens, the full trace is always written to the StackTrace logger. This logs to a file called stacktrace.log - but you can change this in your Config.groovy to do anything you like. For example if you prefer full stack traces to go to standard out you can change the line:

StackTrace="error,stacktraceLog"

To:

StackTrace="error,stdout"

You can completely disable stacktrace filtering by setting the grails.full.stacktrace VM property to true:

grails -Dgrails.full.stacktrace=true run-app

Logging by Convention

All application artefacts have a dynamically added log property. This includes domain classes, controllers, tag libraries and so on. Below is an example of its usage:

def foo = "bar"
log.debug "The value of foo is $foo"

Logs are named using the convention grails.app.<artefactType>.ClassName. Below is an example of how to configure logs for different Grails artefacts:

# Set level for all application artefacts
log4j.logger.grails.app="info, stdout"

# Set for a specific controller log4j.logger.grails.app.controller.YourController="debug, stdout"

# Set for a specific domain class log4j.logger.grails.app.domain.Book="debug, stdout"

# Set for a specific taglib log4j.logger.grails.app.tagLib.FancyAjax="debug, stdout"

# Set for all taglibs log4j.logger.grails.app.tagLib="info, stdout"

The artefacts names are dictated by convention, some of the common ones are listed below:

3.2 Environments

Per Environment Configuration

Grails supports the concept of per environment configuration. Both the Config.groovy file and the DataSource.groovy file within the grails-app/conf directory can take advantage of per environment configuration using the syntax provided by ConfigSlurper As an example consider the following default DataSource definition provided by Grails:

dataSource {
    pooled = false                          
    driverClassName = "org.hsqldb.jdbcDriver"	
    username = "sa"
    password = ""				
}
environments {
    development {
        dataSource {
            dbCreate = "create-drop" // one of 'create', 'createeate-drop','update'
            url = "jdbc:hsqldb:mem:devDB"
        }
    }   
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:hsqldb:mem:testDb"
        }
    }   
    production {
        dataSource {
            dbCreate = "update"
            url = "jdbc:hsqldb:file:prodDb;shutdown=true"
        }
    }
}

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. This syntax can also be used within Config.groovy.

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 could do:

grails test war

If you have other environments that you need to target 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 GrailsUtil class:

import grails.util.GrailsUtil

...

switch(GrailsUtil.environment) { case "development": configureForDevelopment() break case "production": configureForProduction() break }

3.3 The DataSource

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

Essentially, if you are using another database other than HSQLDB you need to have a JDBC driver. For example for MySQL you would need Connector/J

Drivers typically come in the form of a JAR archive. Drop the JAR into your projects lib directory.

Once you have the JAR in place you need to get familiar Grails' DataSource descriptor file located at grails-app/conf/DataSource.groovy. This file contains the dataSource definition which includes the following settings:

A typical configuration for MySQL may be something like:

dataSource {
	pooled = true
	dbCreate = "update"
	url = "jdbc:mysql://localhost/yourDB"
	driverClassName = "com.mysql.jdbc.Driver"
	username = "yourUser"
	password = "yourPassword"	
}

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 local variable
	…
}

3.3.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 {
	// common settings here
}                     
environments {
  production {
     dataSource {
          url = "jdbc:mysql://liveip.com/liveDb"					
     }			
  }
}

3.3.2 JNDI DataSources

Since many Java EE containers typically supply DataSource instances via the Java Naming and Directory Interface (JNDI). Sometimes you are required to look-up a DataSource via JNDI.

Grails supports the definition of JNDI data sources as follows:

dataSource {
    jndiName = "java:comp/env/myDataSource"
}

The format on the JNDI name may vary from container to container, but the way you define the DataSource remains the same.

3.3.3 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:

Both create-drop and create will destroy all existing data hence use with caution!

In development mode dbCreate is by default set to "create-drop":

dataSource {
	dbCreate = "create-drop" // one of 'create', 'create-drop','update'
}

What this does is automatically drop and re-create the database tables on each restart of the application. Obviously this may not be what you want in production.

Although Grails does not currently support Rails-style Migrations out of the box, there are currently two plug-ins that provide similar capabilities to Grails: The LiquiBase plug-in and the DbMigrate plug-in both of which are available via the grails list-plugins command

3.4 Externalized Configuration

The default configuration file Config.groovy in grails-app/conf is fine in the majority of cases, but there may be circumstances where you want to maintain the configuration in a file outside the main application structure. For example if you are deploying to a WAR some administrators prefer the configuration of the application to be externalized to avoid having to re-package the WAR due to a change of configuration.

In order to support deployment scenarios such as these the configuration can be externalized. To do so you need to point Grails at the locations of the configuration files Grails should be using by adding a grails.config.locations setting in Config.groovy:

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

In the above example we're loading configuration files (both Java properties files and ConfigSlurper configurations) from different places on the classpath and files located in USER_HOME.

Ultimately all configuration files get merged into the config property of the GrailsApplication object and are hence obtainable from there.

Grails also supports the concept of property place holders and property override configurers as defined in Spring For more information on these see the section on Grails and Spring

3.5 Versioning

Versioning Basics

Grails has built in support for application versioning. When you first create an application with the create-app command the version of the application is set to 0.1. The version is stored in the application meta data file called application.properties in the root of the project.

To change the version of your application you can run the set-version command:

grails set-version 0.2

The version is used in various commands including the war command which will append the application version to the end of the created WAR file.

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['app.version']

If it is the version of Grails you need you can use:

def grailsVersion = grailsApplication.metadata['app.grails.version']

or the GrailsUtil class:

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

4. The Command Line

Grails' command line system is built on Gant - a simple Groovy wrapper around Apache Ant.

However, Grails takes it a bit further through the use of convention and the grails command. When you type:

grails [command name]
Grails does a search in the following directories for Gant scripts to execute:

Grails will also convert command names that are in lower case form such as run-app into camel case. So typing

grails run-app

Results in a search for the following files:

If multiple matches are found Grails will give you a choice of which one to execute. When the Gant script is executed the "default" target is executed.

To get a list and some help about the available commands type:

grails help

Which outputs usage instructions and the list of commands Grails is aware of:

Usage (optionals marked with *): 
grails [environment]* [target] [arguments]*

Examples: grails dev run-app grails create-app books

Available Targets (type grails help 'target-name' for more info): grails bootstrap grails bug-report grails clean grails compile ...

Refer to the Command Line reference in left menu of the reference guide for more information about individual commands

4.1 Creating Gant Scripts

You can create your own Gant scripts by running the create-script command from the root of your project. For example the following command:

grails create-script compile-sources

Will create a script called scripts/CompileSources.groovy. A Gant script itself is similar to a regular Groovy script except that it supports the concept of "targets" and dependencies between them:

target(default:"The default target is the one that gets executed by Grails") {
	depends(clean, compile)
}
target(clean:"Clean out things") {
	Ant.delete(dir:"output")
}
target(compile:"Compile some sources") {
	Ant.mkdir(dir:"mkdir")
	Ant.javac(srcdir:"src/java", destdir:"output")
}

As demonstrated in the script above, there is an implicit Ant variable that allows access to the Apache Ant API.

You can also "depend" on other targets using the depends method demonstrated in the default target above.

4.2 Re-using Grails scripts

Grails ships with a lot of command line functionality out of the box which is useful to re-use (See the command line reference in the reference guide for info on all the commands). Some of the most useful are the compile, package and bootstrap scripts.

The bootstrap script for example allows you to bootstrap a Spring ApplicationContext instance to get access to the data source and so on:

Ant.property(environment:"env")                             
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"

includeTargets << new File ( "${grailsHome}/scripts/Bootstrap.groovy" )

target ('default': "Load the Grails interactive shell") { depends( configureProxy, packageApp, classpath, loadApp, configureApp )

Connection c try { // do something with connection c = appCtx.getBean('dataSource').getConnection() } finally { c?.close() } }

4.3 Hooking into Events

Grails provides the ability to hook into scripting events. These are events triggered during execution of Grails target and plugin scripts.

The mechanism is deliberately simple and loosely specified. The list of possible events is not fixed in any way, so it is possible to hook into events triggered by plugin scripts, for which there is no equivalent event in the core target scripts.

Defining event handlers

Event handlers are defined in scripts called Events.groovy. Grails searches for these scripts in the following locations:

Whenever an event is fired, all the registered handlers for that event are executed. Note that the registration of handlers is performed automatically by Grails, so you just need to declare them in the relevant Events.groovy file.

Event handlers are blocks defined in Events.groovy, with a name beginning with "event". The following example can be put in your /scripts directory to demonstrate the feature:

eventCreatedArtefact = { type, name ->
   println "Created $type $name"
}

eventStatusUpdate = { msg -> println msg }

eventStatusFinal = { msg -> println msg }

You can see here the three handlers eventCreatedArtefact, eventStatusUpdate, eventStatusFinal. Grails provides some standard events, which are documented in the command line reference guide. For example the compile command fires the following events:

Triggering events

To trigger an event simply include the Init.groovy script and call the event() closure:

Ant.property(environment:"env")
grailsHome = Ant.antProject.properties."env.GRAILS_HOME"
includeTargets << new File ( "${grailsHome}/scripts/Init.groovy" )

event("StatusFinal", ["Super duper plugin action complete!"])

Common Events

Below is a table of some of the common events that can be leveraged:

EventParametersDescription
StatusUpdatemessagePassed a string indicating current script status/progress
StatusErrormessagePassed a string indicating an error message from the current script
StatusFinalmessagePassed a string indicating the final script status message, i.e. when completing a target, even if the target does not exit the scripting environment
CreatedArtefactartefactType,artefactNameCalled when a create-xxxx script has completed and created an artefact
CreatedFilefileNameCalled whenever a project source filed is created, not including files constantly managed by Grails
ExitingreturnCodeCalled when the scripting environment is about to exit cleanly
PluginInstalledpluginNameCalled after a plugin has been installed
CompileStartkindCalled when compilation starts, passing the kind of compile - source or tests
CompileEndkindCalled when compilation is finished, passing the kind of compile - source or tests
DocStartkindCalled when documentation generation is about to start - javadoc or groovydoc
DocEndkindCalled when documentation generation has ended - javadoc or groovydoc
SetClasspathrootLoaderCalled during classpath initialization so plugins can augment the classpath with rootLoader.addURL(...). Note that this augments the classpath after event scripts are loaded so you cannot use this to load a class that your event script needs to import, although you can do this if you load the class by name.
PackagingEndnoneCalled at the end of packaging (which is called prior to the Jetty server being started and after web.xml is generated)
ConfigureJettyJetty Server objectCalled after initial configuration of the Jetty web server.

4.4 Ant and Maven

Ant Integration

When you create a Grails application via the create-app command, Grails automatically creates an Apache Ant build.xml file for you containing the following targets:

Each of these can be run by Ant, for example:

ant war

The build.xml calls into Grails' normal commands and can be used to integrate Grails with a continuous integration server such as CruiseControl or Hudson

Maven Integration

Grails does not provide Maven support out of the box, but there is an external project called Maven Tools for Grails that does provide integration which allows you to create a POM out of an existing Grails project as well as providing hooks into the Maven lifecycle for Grails.

For more information refer to the Maven Tools for Grails site.

5. Object Relational Mapping (GORM)

Domain classes are core to any business application. They hold state about business processes and hopefully also implement behavior. They are linked together through relationships, either one-to-one or one-to-many.

GORM is Grails' object relational mapping (ORM) implementation. Under the hood it uses Hibernate 3 (an extremely popular and flexible open source ORM solution) but because of the dynamic nature of Groovy, the fact that it supports both static and dynamic typing, and the convention of Grails there is less configuration involved in creating Grails domain classes.

You can also write Grails domain classes in Java. See the section on Hibernate Integration for how to write Grails domain classes in Java but still use dynamic persistent methods. Below is a preview of GORM in action:

def book = Book.findByTitle("Groovy in Action")

book .addToAuthors(name:"Dierk Koenig") .addToAuthors(name:"Guillaume LaForge") .save()

5.1 Quick Start Guide

A domain class can be created with the create-domain-class command:

grails create-domain-class Person

This will create a class at the location grails-app/domain/Person.groovy such as the one below:

class Person {	
}

If you have the dbCreate property set to "update", "create" or "create-drop" on your DataSource, Grails will automatically generated/modify the database tables for you.

You can customize the class by adding properties:

class Person {	
	String name
	Integer age
	Date lastVisit
}

Once you have a domain class try and manipulate it via the shell or console by typing:

grails console

This loads an interactive GUI where you can type Groovy commands.

5.1.1 Basic CRUD

Try performing some basic CRUD (Create/Read/Update/Delete) operations.

Create

To create a domain class use the Groovy new operator, set its properties and call save:

def p = new Person(name:"Fred", age:40, lastVisit:new Date())
p.save()

The save method will persist your class to the database using the underlying Hibernate ORM layer.

Read

Grails transparently adds an implicit id property to your domain class which you can use for retrieval:

def p = Person.get(1)
assert 1 == p.id

This uses the get method that expects a database identifier to read the Person object back from the db.

Update

To update an instance, set some properties and then simply call save again:

def p = Person.get(1)
p.name = "Bob"
p.save()

Delete

To delete an instance use the delete method:

def p = Person.get(1)
p.delete()

5.2 Domain Modelling in GORM

When building Grails applications you have to consider the problem domain you are trying to solve. For example if you were building an Amazon bookstore you would be thinking about books, authors, customers and publishers to name a few.

These are modeled in GORM as Groovy classes so a Book class may have a title, a release date, an ISBN number and so on. The next few sections show how to model the domain in GORM.

To create a domain class you can run the create-domain-class target as follows:

grails create-domain-class Book

The result will be a class at grails-app/domain/Book.groovy:

class Book {	
}

If you wish to use packages you can move the Book.groovy class into a sub directory under the domain directory and add the appropriate package declaration as per Groovy (and Java's) packaging rules.

The above class will map automatically to a table in the database called book (the same name as the class). This behaviour is customizable through the ORM Domain Specific Language

Now that you have a domain class you can define its properties as Java types. For example:

class Book {
	String title
	Date releaseDate
	String ISBN
}

Each property is mapped to a column in the database, where the convention for column names is all lower case separated by underscores. For example releaseDate maps onto a column release_date. The SQL types are auto-detected from the Java types, but can be customized via Constraints or the ORM DSL.

5.2.1 Association in GORM

Relationships define how domain classes interact with each other. Unless specified explicitly at both ends, a relationship exists only in the direction it is defined.

5.2.1.1 One-to-one

A one-to-one relationship is the simplest kind, and is defined trivially using a property of the type of another domain class. Consider this example:

Example A

class Face {
    Nose nose
}
class Nose {	
}

In this case we have unidirectional one-to-one relationship from Face to Nose. To make this relationship bidirectional define the other side as follows:

Example B

class Face {
    Nose nose
}
class Nose {	
	Face face
}

This is bidirectional relationship. However, in this case no updates are cascading from either side of the relationship.

Consider this variation:

Example C

class Face {
    Nose nose
}
class Nose {	
	static belongsTo = [face:Face]
}

In this case we use the belongsTo setting to say that Nose "belongs to" Face. The result of this is that we can create a Face and save it and the database updates/inserts will be cascaded down to Nose:

new Face(nose:new Nose()).save()

The example above will save both face and nose. Note that the inverse is not true and will result in an error due to a transient Face:

new Nose(face:new Face()).save() // will cause an error

Another important implication of belongsTo is that if you delete a Face instance the Nose will be deleted too:

def f = Face.get(1)
f.delete() // both Face and Nose deleted

Without belongsTo deletes would not be cascading and you would get a foreign key constraint error unless you explicitly deleted the Nose:

// error here without belongsTo
def f = Face.get(1)
f.delete()

// no error as we explicitly delete both def f = Face.get(1) f.nose.delete() f.delete()

You could keep the previous relationship as unidirectional and allow saves/updates to cascade down by doing the following:

class Face {
    Nose nose
}
class Nose {	
	static belongsTo = Face
}

Note in this case because we are not using the map syntax in the belongsTo declaration and explicitly naming the association. Grails will assume it is unidirectional. The diagram below summarizes the 3 examples:

5.2.1.2 One-to-many

A one-to-many relationship is when one class, example Author, has many instances of a another class, example Book. With Grails you define such a relationship with the hasMany setting:

class Author {
    static hasMany = [ books : Book ]

String name } class Book { String title }

In this case we have a unidirectional one-to-many. Grails will, by default, map this kind of relationship with a join table.

The ORM DSL allows mapping unidirectional relationships using a foreign key association instead

Grails will automatically inject a property of type java.util.Set into the domain class based on the hasMany setting. This can be used to iterate over the collection:

def a = Author.get(1)

a.books.each { println it.title }

The default fetch strategy used by Grails is "lazy", which means that the collection will be lazily initialized. This can lead to the n+1 problem if you are not careful.

If you need "eager" fetching you can use the ORM DSL or specify eager fetching as part of a query

The default cascading behaviour is to cascade saves and updates, but not deletes unless a belongsTo is also specified:

class Author {
    static hasMany = [ books : Book ]

String name } class Book { static belongsTo = [author:Author] String title }

If you have two properties of the same type on the many side of a one-to-many you have to use mappedBy to specify which the collection is mapped:

class Airport {
	static hasMany = [flights:Flight]
	static mappedBy = [flights:"departureAirport"]
}
class Flight {
	Airport departureAirport
	Airport destinationAirport
}

This is also true if you have multiple collections that map to different properties on the many side:

class Airport {
	static hasMany = [outboundFlights:Flight, inboundFlights:Flight]
	static mappedBy = [outboundFlights:"departureAirport", inboundFlights:"destinationAirport"]
}
class Flight {
	Airport departureAirport
	Airport destinationAirport
}

5.2.1.3 Many-to-many

Grails supports many-to-many relationships by defining a hasMany on both sides of the relationship and having a belongsTo on the side that owns the relationship:

class Book {
   static belongsTo = Author
   static hasMany = [authors:Author]
   String title
}
class Author {
   static hasMany = [books:Book]
   String name
}

Grails maps a many-to-many using a join table at the database level. The owning side of the relationship, in this case Author, takes responsibility for persisting the relationship and is the only side that can cascade saves across.

For example this will work and cascade saves:

new Author(name:"Stephen King")
		.addToBooks(new Book(title:"The Stand"))
		.addToBooks(new Book(title:"The Shining"))		
		.save()

However the below will only save the Book and not the authors!

new Book(name:"Groovy in Action")
		.addToAuthors(new Author(name:"Dierk Koenig"))
		.addToAuthors(new Author(name:"Guillaume Laforge"))		
		.save()

This is the expected behaviour as, just like Hibernate, only one side of a many-to-many can take responsibility for managing the relationship.

Grails' Scaffolding feature does not currently support many-to-many relationship and hence you must write the code to manage the relationship yourself

5.2.2 Composition in GORM

As well as association, Grails supports the notion of composition. In this case instead of mapping classes onto separate tables a class can be "embedded" within the current table. For example:

class Person {
	Address homeAddress
	Address workAddress
	static embedded = ['homeAddress', 'workAddress']
}
class Address {
	String number
	String code
}

The resulting mapping would looking like this:

If you define the Address class in a separate Groovy file in the grails-app/domain directory you will also get an address table. If you don't want this to happen use Groovy's ability to define multiple classes per file and include the Address class below the Person class in the grails-app/domain/Person.groovy file

5.2.3 Inheritance in GORM

GORM supports inheritance both from abstract base classes and concrete persistent GORM entities. For example:

class Content {
     String author
}
class BlogEntry extends Content {
    URL url
}
class Book extends Content {
    String ISBN
}
class PodCast extends Content {
    byte[] audioStream
}

In the above example we have a parent Content class and then various child classes with more specific behaviour.

Considerations

At the database level Grails by default uses table-per-hierarchy mapping with a discriminator column called class so the parent class (Content) and its sub classes (BlogEntry, Book etc.), share the same table.

Table-per-hierarchy mapping has a down side in that you cannot have non-nullable properties with inheritance mapping. An alternative is to use table-per-subclass which can be enabled via the ORM DSL

However, excessive use of inheritance and table-per-subclass can result in poor query performance due to the excessive use of join queries. In general our advice is if you're going to use inheritance, don't abuse it and don't make your inheritance hierarchy too deep.

Polymorphic Queries

The upshot of inheritance is that you get the ability to polymorphically query. For example using the list method on the Content super class will return all sub classes of Content:

def content = Content.list() // list all blog entries, books and pod casts
content = Content.findAllByAuthor('Joe Bloggs') // find all by author

def podCasts = PodCast.list() // list only pod casts

5.2.4 Sets, Lists and Maps

Sets of objects

By default when you define a relationship with GORM it is a java.util.Set which is an unordered collection that cannot contain duplicates. In other words when you have:

class Author {
   static hasMany = [books:Book]
}

The books property that GORM injects is a java.util.Set. The problem with this is there is no ordering when accessing the collection, which may not be what you want. To get custom ordering you can say that the set is a SortedSet:

class Author {
   SortedSet books
   static hasMany = [books:Book]
}

In this case a java.util.SortedSet implementation is used which means you have to implement java.lang.Comparable in your Book class:

class Book implements Comparable {
   String title
   Date releaseDate = new Date()

int compareTo(obj) { releaseDate.compareTo(obj.releaseDate) } }

The result of the above class is that the Book instances in the books collections of the Author class will be ordered by their release date.

Lists of objects

If you simply want to be able to keep objects in the order which they were added and to be able to reference them by index like an array you can define your collection type as a List:

class Author {
   List books
   static hasMany = [books:Book]
}

In this case when you add new elements to the books collection the order is retained in a sequential list indexed from 0 so you can do:

author.books[0] // get the first book

The way this works at the database level is Hibernate creates a books_idx column where it saves the index of the elements in the collection in order to retain this order at the db level.

When using a List, elements must be added to the collection before being saved, otherwise Hibernate will throw an exception (org.hibernate.HibernateException: null index column for collection):

// This won't work!
def book = new Book(title: 'The Shining')
book.save()
author.addToBooks(book)

// Do it this way instead. def book = new Book(title: 'Misery') author.addToBooks(book) author.save()

Maps of Objects

If you want a simple map of string/value pairs GORM can map this with the following:

class Author {
   Map books // map of ISBN:book names
}

def a = new Author() a.books = ["1590597583":"Grails Book"] a.save()

In this case the key and value of the map MUST be strings.

If you want a Map of objects then you can do this:

class Book {
  Map authors
  static hasMany = [authors:Author]
}

def a = new Author(name:"Stephen King")

def book = new Book() book.authors = [stephen:a] book.save()

The static hasMany property defines the type of the elements within the Map. The keys for the map must be strings.

5.3 Persistence Basics

A key thing to remember about Grails is that under the surface Grails is using Hibernate for persistence. If you are coming from a background of using ActiveRecord or iBatis Hibernate's "session" model may feel a little strange.

Essentially, Grails automatically binds a Hibernate session to the currently executing request. This allows you to use the save and delete methods as well as other GORM methods transparently.

5.3.1 Saving and Updating

An example of using the save method can be seen below:

def p = Person.get(1)
p.save()

A major difference with Hibernate is when you call save it does not necessarily perform any SQL operations at that point. Hibernate typically batches up SQL statements and executes them at the end. This is typically done for you automatically by Grails, which manages your Hibernate session.

There are occasions, however, when you may want to control when those statements are executed or, in Hibernate terminology, when the session is "flushed". To do so you can use the flush argument to the save method:

def p = Person.get(1)
p.save(flush:true)

Note that in this case all pending SQL statements including previous saves will be synchronized with the db. This also allows you to catch any exceptions thrown, which is typically useful in highly concurrent scenarios involving optimistic locking:

def p = Person.get(1)
try {
	p.save(flush:true)
}
catch(Exception e) {
	// deal with exception
}

5.3.2 Deleting Objects

An example of the delete method can be seen below:

def p = Person.get(1)
p.delete()

The delete method also allows control over flushing via a flush argument:

def p = Person.get(1)
p.delete(flush:true)

Note that Grails does not supply a deleteAll method as deleting data is discouraged and can often be avoided through boolean flags/logic.

If you really need to batch delete data you can use the executeUpdate method to do batch DML statements:

Customer.executeUpdate("delete Customer c where c.name = :oldName", [oldName:"Fred"])

5.3.3 Understanding Cascading Updates and Deletes

It is critical that you understand how cascading updates and deletes work when using GORM. The key part to remember is the belongsTo setting which controls which class "owns" a relationship.

Whether it is a one-to-one, one-to-many or many-to-many if you define belongsTo updates and deletes will cascade from the owning class to its possessions (the other side of the relationship).

If you do not define belongsTo than no cascades will happen and you will have to manually save each object.

Here is an example:

class Airport {
	String name
	static hasMany = [flights:Flight]
}
class Flight {
	String number
	static belongsTo = [airport:Airport]
}

If I now create an Airport and add some Flights to it I can save the Airport and have the updates cascaded down to each flight, hence saving the whole object graph:

new Airport(name:"Gatwick")
	 .addToFlights(new Flight(number:"BA3430"))
	 .addToFlights(new Flight(number:"EZ0938"))
	 .save()

Conversely if I later delete the Airport all Flights associated with it will also be deleted:

def airport = Airport.findByName("Gatwick")
airport.delete()

However, if I were to remove belongsTo then the above cascading deletion code would not work. To understand this better take a look at the summaries below that describe the default behaviour of GORM with regards to specific associations.

Bidirectional one-to-many with belongsTo

class A { static hasMany = [bees:B] }
class B { static belongsTo = [a:A] }

In the case of a bidirectional one-to-many where the many side defines a belongsTo then the cascade strategy is set to "ALL" for the one side and "NONE" for the many side.

Unidirectional one-to-many

class A { static hasMany = [bees:B] }
class B {  }

In the case of a unidirectional one-to-many where the many side defines no belongsTo then the cascade strategy is set to "SAVE-UPDATE".

Bidirectional one-to-many no belongsTo

class A { static hasMany = [bees:B] }
class B { A a }

In the case of a bidirectional one-to-many where the many side does not define a belongsTo then the cascade strategy is set to "SAVE-UPDATE" for the one side and "NONE" for the many side.

Unidirectional One-to-one with belongsTo

class A {  }
class B { static belongsTo = [a:A] }

In the case of a unidirectional one-to-one association that defines a belongsTo then the cascade strategy is set to "ALL" for the owning side of the relationship (A->B) and "NONE" from the side that defines the belongsTo (B->A)

Note that if you need further control over cascading behaviour, you can use the ORM DSL.

5.3.4 Eager and Lazy Fetching

Associations in GORM are by default lazy. This is best explained by example:

class Airport {
	String name
	static hasMany = [flights:Flight]
}
class Flight {
	String number
	static belongsTo = [airport:Airport]
}

Given the above domain classes and the following code:

def airport = Airport.findByName("Gatwick")
airport.flights.each {
	println it.name
}

GORM will execute a single SQL query to fetch the Airport instance and then 1 extra query for each iteration over the flights association. In other words you get N+1 queries.

This can sometimes be optimal depending on the frequency of use of the association as you may have logic that dictates the associations is only accessed on certain occasions.

An alternative is to use eager fetching which can specified as follows:

class Airport {
	String name
	static hasMany = [flights:Flight]
	static fetchMode = [flights:"eager"]
}

In this case the association will be Airport instance and the flights association will be loaded all at once (depending on the mapping). This has the benefit of requiring fewer queries, however should be used carefully as you could load your entire database into memory with too many eager associations.

Associations can also be declared non-lazy using the ORM DSL

5.3.5 Pessimistic and Optimistic Locking

Optimistic Locking

By default GORM classes are configured for optimistic locking. Optimistic locking essentially is a feature of Hibernate which involves storing a version number in a special version column in the database.

The version column gets read into a version property that contains the current versioned state of persistent instance which you can access:

def airport = Airport.get(10)

println airport.version

When you perform updates Hibernate will automatically check the version property against the version column in the database and if they differ will throw a StaleObjectException and the transaction will be rolled back.

This is useful as it allows a certain level of atomicity without resorting to pessimistic locking that has an inherit performance penalty. The downside is that you have to deal with this exception if you have highly concurrent writes. This requires flushing the session:

def airport = Airport.get(10)

try { airport.name = "Heathrow" airport.save(flush:true) } catch(org.springframework.dao.OptimisticLockingFailureException e) { // deal with exception }

The way you deal with the exception depends on the application. You could attempt a programmatic merge of the data or go back to the user and ask them to resolve the conflict.

Alternatively, if it becomes a problem you can resort to pessimistic locking.

Pessimistic Locking

Pessimistic locking is equivalent to doing a SQL "SELECT * FOR UPDATE" statement and locking a row in the database. This has the implication that other read operations will be blocking until the lock is released.

In Grails pessimistic locking is performed on an existing instance via the lock method:

def airport = Airport.get(10)
airport.lock() // lock for update
airport.name = "Heathrow"
airport.save()

Grails will automatically deal with releasing the lock for you once the transaction has been committed. However, in the above case what we are doing is "upgrading" from a regular SELECT to a SELECT..FOR UPDATE and another thread could still have updated the record in between the call to get() and the call to lock().

To get around this problem you can use the static lock method that takes an id just like get:

def airport = Airport.lock(10) // lock for update
airport.name = "Heathrow"
airport.save()

In this case only SELECT..FOR UPDATE is issued.

Though Grails, through Hibernate, supports pessimistic locking, the embedded HSQLDB shipped with Grails which is used as the default in-memory database does not. If you need to test pessimistic locking you will need to do so against a database that does have support such as MySQL.

5.4 Querying with GORM

GORM supports a number of powerful ways to query from dynamic finders, to criteria to Hibernate's object oriented query language HQL.

Groovy's ability to manipulate collections via GPath and methods like sort, findAll and so on combined with GORM results in a powerful combination.

However, let's start with the basics.

Listing instances

If you simply need to obtain all the instances of a given class you can use the list method:

def books = Book.list()

The list method supports arguments to perform pagination:

def books = Book.list(offset:10, max:20)

as well as sorting:

def books = Book.list(sort:"title", order:"asc")

Here, the sort argument is the name of the domain class property that you wish to sort on, and the order argument is either asc for ascending or desc for descending.

Retrieval by Database Identifier

The second basic form of retrieval is by database identifier using the get method:

def book = Book.get(23)

You can also obtain a list of instances for a set of identifiers using getAll:

def books = Book.getAll(23, 93, 81)

5.4.1 Dynamic Finders

GORM supports the concept of dynamic finders. A dynamic finder looks like a static method invocation, but the methods themselves don't actually exist in any form at the code level.

Instead, a method is auto-magically generated using code synthesis at runtime, based on the properties of a given class. Take for example the Book class:

class Book {
	String title
	Date releaseDate
	Author author
}                
class Author {
	String name
}

The Book class has properties such as title, releaseDate and author. These can be used by the findBy and findAllBy methods in the form of "method expressions":

def book = Book.findByTitle("The Stand")

book = Book.findByTitleLike("Harry Pot%")

book = Book.findByReleaseDateBetween( firstDate, secondDate )

book = Book.findByReleaseDateGreaterThan( someDate )

book = Book.findByTitleLikeOrReleaseDateLessThan( "%Something%", someDate )

Method Expressions

A method expression in GORM is made up of the prefix such as findBy followed by an expression that combines one or more properties. The basic form is:

Book.findBy([Property][Comparator][Boolean Operator])?[Property][Comparator]

The tokens marked with a '?' are optional. Each comparator changes the nature of the query. For example:

def book = Book.findByTitle("The Stand")

book = Book.findByTitleLike("Harry Pot%")

In the above example the first query is equivalent to equality whilst the latter, due to the Like comparator, is equivalent to a SQL like expression.

The possible comparators include:

Notice that the last 3 require different numbers of method arguments compared to the rest, as demonstrated in the following example:

def now = new Date()
def lastWeek = now - 7
def book = Book.findByReleaseDateBetween( lastWeek, now )

books = Book.findAllByReleaseDateIsNull() books = Book.findAllByReleaseDateIsNotNull()

Boolean logic (AND/OR)

Method expressions can also use a boolean operator to combine two criteria:

def books = 
    Book.findAllByTitleLikeAndReleaseDateGreaterThan("%Java%", new Date()-30)

In this case we're using And in the middle of the query to make sure both conditions are satisfied, but you could equally use Or:

def books = 
    Book.findAllByTitleLikeOrReleaseDateGreaterThan("%Java%", new Date()-30)

At the moment, you can only use dynamic finders with a maximum of two criteria, i.e. the method name can only have one boolean operator. If you need to use more, you should consider using either Criteria or the HQL.

Querying Associations

Associations can also be used within queries:

def author = Author.findByName("Stephen King")

def books = author ? Book.findAllByAuthor(author) : []

In this case if the Author instance is not null we use it in a query to obtain all the Book instances for the given Author.

Pagination & Sorting

The same pagination and sorting parameters available on the list method can also be used with dynamic finders by supplying a map as the final parameter:

def books = 
  Book.findAllByTitleLike("Harry Pot%", [max:3, 
                                         offset:2, 
                                         sort:"title",
                                         order:"desc"])

5.4.2 Criteria

Criteria is a type safe, advanced way to query that uses a Groovy builder to construct potentially complex queries. It is a much better alternative to using StringBuffer.

Criteria can be used either via the createCriteria or withCriteria methods. The builder uses Hibernate's Criteria API, the nodes on this builder map the static methods found in the Restrictions class of the Hibernate Criteria API. Example Usage:

def c = Account.createCriteria()
def results = c {
	like("holderFirstName", "Fred%")
	and {
		between("balance", 500, 1000)
		eq("branch", "London")
	}
	maxResults(10)
	order("holderLastName", "desc")
}

Conjunctions and Disjunctions

As demonstrated in the previous example you can group criteria in a logical AND using a and { } block:

and {
	between("balance", 500, 1000)
	eq("branch", "London")
}

This also works with logical OR:

or {
	between("balance", 500, 1000)
	eq("branch", "London")
}

And you can also negate using logical NOT:

not {
	between("balance", 500, 1000)
	eq("branch", "London")
}

Querying Associations

Associations can be queried by having a node that matches the property name. For example say the Account class had many Transaction objects:

class Account {
    …
    def hasMany = [transactions:Transaction]
    Set transactions
    …
}

We can query this association by using the property name transaction as a builder node:

def c = Account.createCriteria()
def now = new Date()
def results = c.list {
       transactions {
            between('date',now-10, now)
       }
}

The above code will find all the Account instances that have performed transactions within the last 10 days. You can also nest such association queries within logical blocks:

def c = Account.createCriteria()
def now = new Date()
def results = c.list {
     or {
        between('created',now-10,now)
        transactions {
             between('date',now-10, now)
        }
     }
}

Here we find all accounts that have either performed transactions in the last 10 days OR have been recently created in the last 10 days.

Querying with Projections

Projections to be used to customise the results. To use projections you need to define a "projections" node within the criteria builder tree. There are equivalent methods within the projections node to the methods found in the Hibernate Projections class:

def c = Account.createCriteria()

def numberOfBranches = c.get { projections { countDistinct('branch') } }

Using Scrollable Results

You can use Hibernate's ScrollableResults feature by calling the scroll method:

def results = crit.scroll {
      maxResults(10)
}
def f = results.first()
def l = results.last()
def n = results.next()
def p = results.previous()

def future = results.scroll(10) def accountNumber = results.getLong('number')

To quote the documentation of Hibernate ScrollableResults:

A result iterator that allows moving around within the results by arbitrary increments. The Query / ScrollableResults pattern is very similar to the JDBC PreparedStatement/ ResultSet pattern and the semantics of methods of this interface are similar to the similarly named methods on ResultSet.

Contrary to JDBC, columns of results are numbered from zero.

Setting properties in the Criteria instance

If a node within the builder tree doesn't match a particular criterion it will attempt to set a property on the Criteria object itself. Thus allowing full access to all the properties in this class. The below example calls setMaxResults and setFirstResult on the Criteria instance: