You are on page 1of 292

Space Details

Key: GRAILS
Name: Grails
Description:
Grails web application framework

Creator (Creation Date): bwalding (Aug 12, 2005)


Last Modifier (Mod. Date): hansamann (Oct 24, 2006)

Available Pages
• Troubleshooting
• Community
• Contribute
• Developer Blogs
• Mailing lists
• User Groups
• Who we are
• Developer Documentation
• Compile Time Injection
• Developer - Dynamic Method Injection
• Developer - Groovy Server Pages
• Developer - Hibernate Integration
• Developer - Spring MVC Integration
• General Architecture
• Runtime Configuration
• Developer Guidelines
• Documentation
• Quick Start
• Reference
• Artifact Reference
• Builders Reference
• Hibernate Criteria Builder
• Spring Bean Builder
• Command Line
• Dynamic Methods Reference
• Controller Dynamic Methods
• DomainClass Dynamic Methods
• OperatorNamesInDynamicMethods
• Tag Library Reference
• GSP Tag Reference
• GSP Tag - collect
• GSP Tag - def

Document generated by Confluence on May 01, 2007 11:37 Page 1


• GSP Tag - each
• GSP Tag - else
• GSP Tag - elseif
• GSP Tag - findAll
• GSP Tag - grep
• GSP Tag - if
• GSP Tag - layoutBody
• GSP Tag - layoutHead
• GSP Tag - layoutTitle
• GSP Tag - pageProperty
• GSP Tag - paginate
• GSP Tag - set
• GSP Tag - sortableColumn
• GSP Tag - while
• Tag - actionSubmit
• Tag - actionSubmitImage
• Tag - checkBox
• Tag - createLink
• Tag - createLinkTo
• Tag - currencySelect
• Tag - datePicker
• Tag - eachError
• Tag - form
• Tag - formRemote
• Tag - hasErrors
• Tag - hiddenField
• Tag - link
• Tag - localeSelect
• Tag - message
• Tag - remoteField
• Tag - remoteFunction
• Tag - remoteLink
• Tag - render
• Tag - renderBean
• Tag - renderErrors
• Tag - richTextEditor
• Tag - select
• Tag - submitToRemote
• Tag - textArea
• Tag - textField
• Tag - timeZoneSelect
• Tag - validate
• JSP Tag Reference
• Validation Reference
• Constraints Influencing Schema Generation

Document generated by Confluence on May 01, 2007 11:37 Page 2


• Success Stories
• User guide
• Advanced Topics
• Ajax
• Artifact and Scaffolding Templates
• Auto Reloading
• Builders
• Command Line Scripting
• Command Line Tools
• Command objects and Form Validation
• Configuration
• Controllers
• Dynamic Encoding Methods
• Dynamic Tag Libraries
• Functional Testing
• GORM
• GORM - Collection Types
• GORM - Creating a domain class
• GORM - CRUD
• GORM - Defining relationships
• GORM - Managing Relationships
• GORM - Mapping inheritance
• GORM - Querying
• GSP Reference
• Hibernate Integration
• Many-to-Many Mapping with Hibernate XML
• HTTP Method Restrictions
• IDE Integration
• Installation
• Introduction
• Job Scheduling (Quartz)
• Logging
• Scaffolding
• Scripting events
• Security
• Services
• Spring Integration
• The Plug-in Developers Guide
• Auto Reloading Plugins
• Contribute a Plugin
• Creating Plugins
• Plugin Basics
• Plugin Dependencies
• Plugin Dynamic Methods
• ExpandoMetaClass

Document generated by Confluence on May 01, 2007 11:37 Page 3


• DynamicMethodsExpandoMetaClass
• Runtime Configuration Plugins
• Understanding Plugins
• Unit Testing
• Validation
• Views and Layouts
• 0.5 Release Notes
• FAQ
• Checking Projects into SVN
• Frequently Asked Questions

Document generated by Confluence on May 01, 2007 11:37 Page 4


Troubleshooting

This page last changed on Mar 22, 2006 by mittie.

Find hints how to avoid common pitfalls below.

grails clean

In case your Grails application has been screwed and comes up with mysterious error messages try

grails clean

This may be needed after done the following operations:

• tbd
• tbd

restart the (jetty) server

Grails does a best effort to avoid the necessity of server restarts.

However, under these circumstances, a server restart is required:

• tbd
• tbd

In general, changes to the domain model do not require a server restart.


When running with the internal HSQL database in 'in-memory' mode, changes to domain models force
Grails
to reload the classes, which will invevitably lead to all instances of the old
classes being unavailable. This effectivly deletes the runtime objects of the
HSQL DB. This does not happen with persistent DBs.

Problems with saving objects transparently

In case you have a bi-directional dependency, you need to care about proper synchronization
of both sides, see XXX

Document generated by Confluence on May 01, 2007 11:37 Page 5


Community

This page last changed on Oct 13, 2006 by graeme.rocher@gmail.com.

Get Involved!

Grails has a growing following and if you want to get involved the developers are all nice people
(promise!) who are keen to have ideas, code and just about anything contributed. There are a number of
ways to get involved with the Grails community, you can:

• Take a look at the Mailing lists archives and post new questions/ideas to the commnity!
• Head over to the Grails Wiki an ever growing knowledge base of information about Grails. Actually,
you're already at the Wiki, just click the "Edit" button at the bottom of this page!
• Get involved in the User Groups, the place where people meet to talk about Groovy and Grails.
• Come and chat to us on IRC at irc.codehaus.org where most Grails developers can be found in the
#groovy room
• Write a Blog post about Grails, or even a Tutorial! Just talking about your experiences with Grails
can either help others get involved or provide constructive feedback to the Grails team.
• Follow what is happening with Grails now and in the future with the Grails Issue Tracker and on the
Roadmap. Or even better checkout the latest commits!
• Contribute your own Custom Tags that could eventually be included in Grails core!
• Post some ideas for new Grails features in the development Sandbox. This is the area we where
play around with ideas before they are promoted into JIRA issues.
• Add one of the Grails buttons on the left to your site or blog to help spread the word about Grails
• Contribute yourself by becoming part of the Grails Team !

Document generated by Confluence on May 01, 2007 11:37 Page 6


Contribute

This page last changed on Feb 24, 2006 by graeme.rocher@gmail.com.

How to Contribute

We're always on the lookout for people who can contribute to Grails so if you have new ideas, patches to
submit, code to contribute anything let us know via the Mailing lists or contact Graeme the Grails project
lead.

Document generated by Confluence on May 01, 2007 11:37 Page 7


Developer Blogs

This page last changed on Mar 12, 2007 by marceloverdijk.

Developer Blogs

Many of the Grails developers are active bloggers, see below for a list of developers and their blogs:

• Graeme's Blog
• Guillaume's Blog
• Dierk's WebTest Blog and Groovy in Action Blog
• Steven Devijver's Blog
• Marc Palmer's Blog
• Jeff Brown's Blog
• Jason Rudolph's Blog
• Marcel Overdijk's Blog

Document generated by Confluence on May 01, 2007 11:37 Page 8


Mailing lists

This page last changed on Apr 23, 2007 by jason@jasonrudolph.com.

Here are the mailing lists that have been established for this project. For each list, there is a subscribe,
unsubscribe, and an archive link. If you have trouble subscribing via email you can go to
http://xircles.codehaus.org/manage_email and register an e-mail to subscribe.

NOTE: If you are using gmail to subscribe and you are using an alternate "send mail as" address, it will
not work. Use your actual gmail address to subscribe, and make sure you send messages from your
gmail account when you send messages to the list.

Once you've done that you can then choose which mailing lists you want to subscribe to on the Grails
project page:

http://xircles.codehaus.org/projects/grails

List name Subscribe Unsubscribe Archive

Grails developer list subscribe unsubscribe http://www.nabble.com/grails---dev-f1

Grails user list subscribe unsubscribe http://www.nabble.com/grails---user-f

Grails SCM and JIRA list subscribe unsubscribe http://archive.grails.codehaus.org/scm

Grails JIRA Activity RSS

German Grails list Yahoo

Document generated by Confluence on May 01, 2007 11:37 Page 9


User Groups

This page last changed on Jun 05, 2006 by mittie.

The first user group so far

• The London Groovy and Grails User Group

Document generated by Confluence on May 01, 2007 11:37 Page 10


Who we are

This page last changed on Mar 15, 2007 by lataupe.

Meet the team!

Grails was started by a small group of keen followers of the Groovy language and inspired by the "code
by convention" paradigm of frameworks like Ruby on Rails.

The project was initiated by Guillaume LaForge and founded by Steven Devijver and Graeme Rocher
(graemerocher@yahoo.co.uk) - who is the current Project Lead. Below the current active members on the
project and their roles:

Name Role Bio Photo


Moment!

Graeme Project As well as


Rocher Lead/Committer
being project
lead of
Grails,
Graeme is
CTO at a
company
called
SkillsMatter
where he
provides
strategic
direction,
training and
mentoring
on Skills
Matters
array of
Open Source
and
Technology
based
courseware.
Graeme is
the
co-founder
and current
project lead
on Grails.
Blog at
http://graemerocher.blogspot.com .

Document generated by Confluence on May 01, 2007 11:37 Page 11


Marc Palmer Committer Marc is a
freelance
Java/Web
contractor
who is sick
of forever
creating yet
another web
framework
and is
overjoyed
that Grails
has arrived.
He is slowly
getting more
into the code
base and
committing
more
features.
He's also a
JIRA
obsessive
and loves
having a well
defined
release
roadmap.
Blog at
http://www.anyware.co.uk

Dierk Koenig Committer Dierk


focusses on
the
functional
testing
aspect of
Grails and
provided
provided the
open-source
Canoo
WebTest
integration.
Dierk works
for Canoo
Engineering
in Basel,
Switzerland.
He is lead

Document generated by Confluence on May 01, 2007 11:37 Page 12


Groovy in
Action.

Steven Committer Steven


Devijver co-founded
Grails
together
with
Graeme,
Guillaume
Laforge and
Dierk. Blog.

Sven Haiges Evangelist / Sven is


Patcher responsible
for the Grails
Podcast and
Grails
Screencasts
and is an
active Grails
evangelist.
He is
working at
Actionality
and his
responsibilities
include the
evolution of
their web
platforms as
well as J2ME
development
for their
mobile
advertisement
solutions.
Check out
his blog at
svenhaiges.de
for further
information.

Jason Committer / Jason has


Rudolph Evangelist written a
number of
articles
about Grails
and
committed a

Document generated by Confluence on May 01, 2007 11:37 Page 13


handful of
patches.
Jason is an
Application
Architect at
Railinc,
where he
develops
software
that helps
trains move
more
efficiently
throughout
North
America.
Jason's
interests
include
dynamic
languages,
lightweight
development
methodologies,
improving
developer
productivity,
and a quest
to keep
programming
fun. It's
these
interests
that led
Jason to
become a
Grails
committer
and
evangelist.
You can find
Jason online
at
http://jasonrudolph.com.

Jeff Brown Committer Jeff Brown is


a Principal
Software
Engineer
with Object
Computing
Inc. based in
St. Louis,
Missouri.
OCI is a

Document generated by Confluence on May 01, 2007 11:37 Page 14


software
engineering
company
founded
upon the
principles of
Object
Oriented
Technology
to produce
quality
software.
OCI is the
largest Java
training
company in
the mid-west
and the
largest
CORBA
training
company in
the United
States. OCI
is a leading
provider of
open source
services to
organizations
building
mission
critical
infrastructure
systems.
For over 10
years Jeff
has been
involved in
designing
and building
object
oriented
systems.
Jeff currently
teaches a
number of
Java and
object
oriented
training
courses in
addition to
doing
consulting

Document generated by Confluence on May 01, 2007 11:37 Page 15


and
mentoring
work for
industries
including
Aerospace,
Financial and
Medical.
Areas of
expertise
include Java,
agile web
development
with Groovy
and Grails,
distributed
computing,
object
database
systems,
object
oriented
analysis and
design and
agile
development.
Jeff became
a Grails
committer in
2006 and
will continue
to be an
active
contributor.
Blog at
javajeff.blogspot.com.

Marcel Committer Marcel is a


Overdijk Technical
Consultant
at Valid ICT
based in The
Netherlands.
From origin
he is an
Oracle
developer
building
client/server
database
applications
using
Oracle's
productive
4GL tooling.

Document generated by Confluence on May 01, 2007 11:37 Page 16


After 5 years
as Oracle
developer he
needed a
new
challenge
and as a
result he
switched to
Java at the
end of 2003.
Since then
he is always
looking for a
highly
productive,
standards-based
and industry
accepted
development
framework
for designing
and building
database
applications.
With Grails,
he thinks a
true
candidate
has arrived.
Blog at
http://marceloverdijk.blogspot.com.

Sergey Committer Sergey is a


Nebolsin freelance
Java
contractor
from Russia
who has
done a
number of
projects for
Tradition
and Sytech.
He primarily
focusses on
developing
server-side
of enterprise
applications
and one day
he was
delighted by
Grails magic.
Now he have

Document generated by Confluence on May 01, 2007 11:37 Page 17


got an offing
to
concentrate
on real work
and not
spend time
for writing
boilerplate
code. He
decided to
use this
released
time for
improving
Grails itself
and this led
him to
become
Grails
committer.

You could also locate Grails people on a Frappr Map

Document generated by Confluence on May 01, 2007 11:37 Page 18


Developer Documentation

This page last changed on Feb 27, 2007 by wangjammer5.

Developer Documentation

These pages are designed to help new committers on the Grails project get up to speed on the various
parts of Grails and how they function:

General Architecture
Runtime Configuration
Artefact API
Dynamic Method Injection
Compile Time Injection
Spring MVC Integration
Hibernate Integration
SiteMesh Integration
Groovy Server Pages
Tag Libraries
Scaffolding Architecture
Command Line

UML class model (0.4)

Document generated by Confluence on May 01, 2007 11:37 Page 19


Compile Time Injection

This page last changed on Apr 04, 2007 by jnicho02.

Compile Time Injection

You might be better served by using the ExpandoMetaClass

Grails contains an architecture to implement compile time injection of properties, methods etc. This is
built on functionality provided by the GroovyClassLoader and is important when used in conjunction with
Java libraries because they are not aware of the Groovy runtime environment and hence dynamic
property injection does not work.

The core classes for compile time injection are found in the org.codehaus.groovy.grails.injection package.
As of this writing only injection of properties into domain classes is supported (sorry if this is out-of-date
when you read it). To do this create a class that implements the
org.codehaus.groovy.grails.injection.GrailsDomainClassInjector and add it as a bean definition to the
applicationContext.xml file.

The org.codehaus.groovy.grails.injection.GrailsInjectionOperation class will automatically look up


implementors of the GrailsDomainClassInjector interface and execute them at which point you have the
oppurtunity to add new properties before compilation occurs. Remember to check if they already exist
otherwise you will get weird ClassFormatError errors. An example of injecting a property called id can be
seen below:

import org.codehaus.groovy.grails.injection.*;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.control.SourceUnit;

public class ExampleDomainClassInjector implements


GrailsDomainClassInjector {

public void performInjection(SourceUnit source, GeneratorContext context,


ClassNode classNode) {
if(classNode.getGetterMethod("getId") != null) {
classNode.addProperty("id", ClassNode.ACC_PUBLIC,
ClassHelper.long_TYPE,null,null,null);
}
}

If you want to add methods, this process can become tricky. The groovy AST (Abstract Syntax Tree)
MethodNode is a dom-like tree of command blocks, return blocks, etc. and can be tiresome to construct
(unless someone has created an editor, if so please say!). I got round this by using the SourceUnit to
parse and compile a String of groovy code into the MethodNode for me.

import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.classgen.GeneratorContext;

Document generated by Confluence on May 01, 2007 11:37 Page 20


import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.grails.injection.GrailsASTUtils;
import org.codehaus.groovy.grails.injection.GrailsDomainClassInjector;

public class RandomInjector implements GrailsDomainClassInjector {

private static final Log LOG = LogFactory.getLog(GrailsDomainClassInjector.class);

public void performInjection(SourceUnit source, GeneratorContext context, ClassNode


classNode) {
injectRandom(classNode);
}

private void injectRandom(ClassNode classNode) {


final boolean hasRandom = GrailsASTUtils.implementsZeroArgMethod(classNode,
"random");
if (\!hasRandom) {
String source = "public static "
+ classNode.getNameWithoutPackage() + " random(){"
+ "def ran = new Random()\n "
+ ".get(ran.nextInt("
+ ".count())+1)" + "}";
SourceUnit su = SourceUnit.create("mine", source);
su.parse();
su.completePhase();
su.convert();
List l = su.getAST().getMethods();
if (l.size() > 0) {
MethodNode mn = (MethodNode) l.get(0);
if (LOG.isDebugEnabled()) {
LOG.debug("\[RandomInjector\] Adding method
\["+mn.getName()+"()\] to class \["+ classNode.getName() + "\] : ");
}
classNode.addMethod(mn);
}
}
}

Some other discussion on the ast can be read on


http://blackdragsview.blogspot.com/2006/11/chitchat-with-groovy-compiler.html&nbsp ;

Document generated by Confluence on May 01, 2007 11:37 Page 21


Developer - Dynamic Method Injection

This page last changed on Jul 26, 2006 by graeme.rocher@gmail.com.

Dynamic Method Injection

The core classes that make up the Grails dynamic method injection architecture are found in the
org.codhaus.groovy.grails.commons.metaclass package. The
org.codhaus.groovy.grails.commons.metaclass.ProxyMetaClass class extends the Groovy MetaClass to
allow constructor, method and property interceptors to be set on the MetaClass which "intercept" calls.

A Groovy MetaClass is what Groovy uses to dispatch method, constructor and property calls to objects
with. These could be real methods or dynamically injected methods. Grails' ProxyMetaClass allows you to
intercept calls to methods that may be real or not and choose whether to invoke the target "real" method
at runtime. ProxyMetaClass tends to be used with instances and the setMetaClass method of
GroovyObject as opposed to being registered within the MetaClassRegistry:

GroovyObject go = ..// some object


ProxyMetaClass pmc = ProxyMetaClass.getInstance(go.getClass());
go.setMetaClass(pmc)

Once you have a ProxyMetaClass instance registered as the objects MetaClass you can then set an
interceptor on the ProxyMetaClass to handle the interception. There are three interfaces for this:

• Interceptor - For intercepting method calls


• PropertyAccessInterceptor - For intercepting property getters/setters
• ConstructorInterceptor - For intercepting constructors

Fortunately, Grails provides an abstract implementation of these that makes life easier called
AbstractDynamicMethodsInterceptor. This abstract class implements the DynamicMethods interface that
allows you to add dynamic methods, contructors and properties as objects. For example the following
code will register an anonymous AbstractDynamicMethodsInterceptor as the interceptor:

DynamicMethods dm = new AbstractDynamicMethodsInterceptor(){};


pmc.setInterceptor(dm);

You can then add dynamic methods, constructors and properties to the interceptor which implement
either the DynamicMethodInvocation, DynamicConstructor or DynamicProperty interfaces. Fortunately
there are abstract implementations of these all:

dm.addDynamicMethodInvocation( new AbstractDynamicMethodInvocation("hello") {


public Object invoke(Object target, Object[] arguments) {
System.out.println("world!");
}
});

Once the above has been added to my previously defined "go" object invoking the method from groovy
will print "world!" to standard out:

Document generated by Confluence on May 01, 2007 11:37 Page 22


go.hello() // prints "world!"

This mechanism is uses in several places including for controller and tag lib in the classes:

• ControllerDynamicMethods
• TagLibDynamicMethods

To make this even easier Grails provides a class called GroovyDynamicMethodsInterceptor which takes a
GroovyObject in the constructor, registers a ProxyMetaClass on it and sets itself as the interceptor
allowing you to shorten the above code example to:

GroovyObject go = //.. created from somewhere


GroovyDynamicMethodsInterceptor i = new GroovyDynamicMethodsInterceptor(go);
i.addDynamicMethodInvocation( new AbstractDynamicMethodInvocation("hello") {
public Object invoke(Object target, Object[] arguments) {
System.out.println("world!");
}
});

The proxy/interception mechanism is best used on instances of GroovyObject, but Grails provides another
MetaClass called DelegatingMetaClass which takes an instance of the DynamicMethods interface in its
constructor and delegates to it hence not requiring any interceptors to be set on it. Essentially it attempts
to call a dynamic method first and if it fails falls back to trying to invoke a real method. This MetaClass is
used by domain classes in conjunction with the DomainClassMethods class which is an instance of
DynamicMethods.

Document generated by Confluence on May 01, 2007 11:37 Page 23


Developer - Groovy Server Pages

This page last changed on Jul 20, 2006 by graeme.rocher@gmail.com.

Groovy Server Pages

The GSP implementation in Grails was forked from the original GSP, but has been heavily refactored and
is now based around the TemplateEngine pattern found in the rest of Groovy. The core classes for GSP
can be found in the org.codehaus.groovy.grails.web.pages package.

There is a servlet that maps to *.gsp that handles all GSP request called GroovyPagesServlet. This class
uses the GroovyPagesTemplateEngine class to process a GSP request.

As mentioned the API for the GroovyPagesTemplateEngine is very similar to the other TemplateEngine's
in Groovy, making GSP into a re-usable component. General API usage is as follows:

groovy.text.Template t = engine.createTemplate(context,request,response);
if(t != null) {
groovy.lang.Writable w = t.make();
Writer out = ..// get writer from somewhere
w.writeTo(out);
}

Thanks to the refactoring into a TemplateEngine the GroovyPagesTemplateEngine is re-used in several


places including in the GSP servlet, in tags libraries and in the render method of controllers.

The Parse, Reverse, Scan, Strip and Tokens classes in the org.codehaus.groovy.grails.web.pages are
used to convert a GSP into a Groovy class that extends the GroovyPage class which in turn extends
groovy.lang.Script.

Document generated by Confluence on May 01, 2007 11:37 Page 24


Developer - Hibernate Integration

This page last changed on Jul 20, 2006 by graeme.rocher@gmail.com.

Hibernate Integration

Configuration

Grails uses Hibernate for ORM, but implements it's own configuration strategy for Hibernate to use
convention to perform ORM mapping. The result is GORM. The core Hibernate integration classes can be
found within the org.codehaus.groovy.grails.orm.hibernate directory. Within this package resides a Spring
factory bean called ConfigurableLocalSessionFactoryBean that extends the Spring factory bean for
creating Hibernate session factories allowing a custom hibernate Configuration class to be set.

Grails then provides its own configuration class within the org.codehaus.groovy.grails.orm.hibernate.cfg
package called DefaultGrailsDomainConfiguration this class extends the Hibernate Configuration the
implication of which means it will still read in a regular hibernate.cfg.xml file if you want to use Hibernate
XML mapping instead.

Grails provides a second Configuration class called GrailsAnnotationConfiguration that extends the
Hibernate AnnotationConfiguration class to allow EJB3 annotation mapping in Grails.

Both configuration classes delegate to a class called


org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder that performs the object relational
mapping. It "binds" the Grails domain class conventions to the Hibernate meta model.

Persistence Methods

The dynamic methods that magically appear on domain classes such as "save" and "delete" can be found
in the package org.codehaus.groovy.grails.orm.hibernate.metaclass . They use the architecture described
in the section on Dynamic Method Injection.

The class which these methods are added to is called


org.codehaus.groovy.grails.metaclass.DomainClassMethods so essentially adding a new method to a
domain class would involve creating a new one in the aformentioned package and adding a line such as:

addDynamicMethodInvocation(new MyBrandNewMethod(sessionFactory, classLoader,application));

Or for static methods:

addStaticMethodInvocation(new MyNewStaticMethod(sessionFactory, classLoader));

Document generated by Confluence on May 01, 2007 11:37 Page 25


Developer - Spring MVC Integration

This page last changed on Jul 20, 2006 by graeme.rocher@gmail.com.

Spring MVC Integration

Grails uses Spring MVC as the underlying web application framework. Spring MVC might not be the
simplist framework to use but it is most definitely one of the most extensible making it perfect for Grails.
The Grails servlet extends Spring's DispatcherServlet to bootstrap the Grails environment, there is then a
single Spring MVC controller called org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsController
that handles all Grails controller requests.

The SimpleGrailsController delegates to a class called


org.codehaus.groovy.grails.web.servlet.mvc.SimpleGrailsControllerHelper that actually handles the
request. This class breaks the handling of the request down into a number of steps. The entry point for
the class is the handleUri method which:

1. Parses the URI into its components (controller name, action name, id etc.)
2. Looks up a GrailsControllerClass instance for the URI
3. Creates a new Grails controller instance
4. Configures the controller instance's dynamic methods and properties
5. Retrieves a scaffolder if is scaffolding is enabled for the controller
6. Gets a reference to the closure action to execute for the URI
7. Increments flash scope moving it on to its next state
8. Gets the view name for the URI
9. Executes any before inteceptors registered
10. Executes the closure that is the controller action if the before interceptor didn't return false
11. Creates a Spring MVC ModelAndView instance from the view name and the model returned by the
closure action
12. Executes any after interceptors registered passing returned model
13. Returns the Spring MVC ModelAndView instance

Document generated by Confluence on May 01, 2007 11:37 Page 26


General Architecture

This page last changed on Feb 27, 2007 by wangjammer5.

General Architecture

The commons package

The core Grails classes that make up the foundation of Grails can be found in the
org.codehaus.groovy.grails.commons package. The classes within this package deal with the conventions
and most implement the interface org.codehaus.groovy.grails.commons.GrailsClass which defines
methods for retrieving various representations of the class name based on the convention.

The classes themselves are loaded into an instance of


org.codehaus.groovy.grails.commons.GrailsApplication the default implementation for which can be found
here.

The DefaultGrailsApplication class defines two constructors one which takes an array of Spring resources.
The resources are a set of the set of .groovy files that resides within the grails-app directory and are
loaded by the Spring applicationContext.xml file found in the WEB-INF directory. The
DefaultGrailsApplication class also defines a constructor that takes an array of classes which is mainly
used in test cases for example:

GroovyClassLoader gcl = new GroovyClassLoader();


Class domainClass = gcl.parseClass("class Test { Long id; Long version; }" );
Class controller = gcl.parseClass("class TestController { def list = {} }");
GrailsApplication app = new DefaultGrailsApplication( new Class[] {
domainClass, controller } );

The above code creates an GrailsApplication instance with a domain class called Test and a controller
called TestController. The domain class is encapsulated by an instance of
org.codehaus.groovy.grails.commons.GrailsDomainClass and the controller by an instance of
org.codehaus.groovy.grails.commons.GrailsControllerClass

Utility Classes for the commons package

There are a number of utility classes for working with the commons package. The class
org.codehaus.groovy.grails.commons.GrailsClassUtils provides methods for evaluating the conventions of
classes and retrieving different naming representations. Since 0.5 these convention evaluation methods
are removed and are available on GrailsApplication via the Developer - Artefact API.

org.codehaus.groovy.grails.commons.GrailsResourceUtils provides methods for working with Grails


resources before they are loaded into classes (ie the .groovy files themselves and where they reside in
the app structure).

The org.codehaus.groovy.grails.commons.GrailsResourceLoader class is an instance of

Document generated by Confluence on May 01, 2007 11:37 Page 27


groovy.lang.ResourceLoader. This class is set on the GroovyClassLoader instance and ensures that
classes can be loaded from Spring Resource instances.

Document generated by Confluence on May 01, 2007 11:37 Page 28


Runtime Configuration

This page last changed on Jul 23, 2006 by graeme.rocher@gmail.com.

Runtime Configuration

Grails automatically configures itself at runtime using the conventions within the classes and Spring. The
class that performs the runtime configuration is called
org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator which takes a GrailsApplication
and produces a bunch of bean references which can be used to create a Spring application context.

The GrailsRuntimeConfigurator class does many things including, but not limited to:

• Configuring the data source


• Setting up the Hibernate session factory
• Creating the handler mappings for the Spring MVC servlet
• Setting up any Quartz scheduled tasks
• Configuring Grails service classes for transaction demarcation

An example of its usage can be seen in the grails.util.GrailsUtil class which is used when running unit
tests and scaffolding. It essentially bootstraps the Grails environment using the
GrailsRuntimeConfigurator class and an applicationContext.xml on the classpath:

ApplicationContext parent = new ClassPathXmlApplicationContext("applicationContext.xml");


DefaultGrailsApplication application =
(DefaultGrailsApplication)parent.getBean("grailsApplication", DefaultGrailsApplication.class);
GrailsRuntimeConfigurator config = new GrailsRuntimeConfigurator(application,parent);

ApplicationContext appCtx = config.configure(new MockServletContext());

When a Grails web application is executed this configuration takes place in the
org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet class which is a class that extends Spring
MVC's DispatcherServlet to bootstrap the Grails environment

Document generated by Confluence on May 01, 2007 11:37 Page 29


Developer Guidelines

This page last changed on Jul 20, 2006 by graeme.rocher@gmail.com.

Overview

If you're looking for documentation about the Grails source code see the Developer Documentation, this
page serves as a guideline to the processes for committers working on Grails. As Grails takes on more
developers it is important that a process is followed so that that Grails maintains a high level of quality.
This section details that process.

The Change Approval Process

Clearly not every great idea should be added directly to Grails, as a commiter you have a responsibility to
inform others of new ideas before touching the codebase. The following process should be followed as a
general rule:

• Send an email to the developer list with proposals of the change/new feature
• If the change is agreed (and ultimately the final decision is down to the Grails project lead Graeme)
add a new JIRA issue.
• When committing the changes refer to the JIRA issue number in the commit comments, e.g.
GRAILS-001
• Make sure you only do minor commits without approval

Testing and Continuous Integration

Testing is seen as crucial to the success of the project and Grails aims for maximum coverage. Before
even thinking of committing anything make sure you have implemented sufficient unit tests to cover the
code.

It doesn't matter how complicated your unit tests become (and they're often more complicated than the
code itself with Grails) they must exist and they must cover as much as possible.

Before committing to Grails make sure you run the entire test suite against Grails and only commit once
the test suite is passing.

Directly following your commit monitor the Continuous Integration build server and ensure the build
completes successfully. A broken build must be immediately corrected.

The continuous integration compiles and tests with JDK 1.4. Make sure not to use any Java 5 specifics.

Notes on current state of coverage

At the moment not every aspect of Grails is covered by a unit test. This will be corrected over time, but
these guidelines are in place so the situation doesn't degrade as we are still in a position to be able to
ensure Grails has a solid foundation for the future.

Document generated by Confluence on May 01, 2007 11:37 Page 30


Document generated by Confluence on May 01, 2007 11:37 Page 31
Documentation

This page last changed on Mar 19, 2007 by graemerocher@yahoo.co.uk.

Documentation

Below is a list of documentation currently available for Grails:

1. Installation - General installation notes


2. Quick Start - Help to get up and running quickly
3. User Guide - Comprehensive user guide
4. Reference - Method, tag and builder references for more detailed API info
5. Tutorials - Loads of info here including screencasts, podcasts, tutorials, articles and more!!
6. Plugins - A list of available plug-ins for Grails
7. Success Stories - List of sites known or suspected to be based on Grails
8. Tips n Tricks - Little nice to know things

Document generated by Confluence on May 01, 2007 11:37 Page 32


Quick Start

This page last changed on Mar 10, 2007 by jason@jasonrudolph.com.

Quick Start

The following makes it simple to start a grails project. There's also a screencast that follows these steps
for creating a small app.

Create a Grails project

Once you have installed Grails you can use the built-in target for creating new projects:

grails create-app

The target will prompt you for the name of your project and create the project structure below:

%PROJECT_HOME%
+ grails-app
+ conf --->location of configuration artifacts like data sources
+ controllers --->location of controller artifacts
+ domain --->location of domain classes
+ i18n --->location of message bundles for i18n
+ services --->location of services
+ taglib --->location of tag libraries
+ util --->location of special utility classes (e.g., codecs, etc.)
+ views --->location of views
+ layouts ---> location of layouts
+ hibernate ---> optional hibernate config
+ lib
+ spring ---> optional spring config
+ src
+ groovy ---> optional; location for Groovy source files
(of types other than those in grails-app/*)
+ java ---> optional; location for Java source files
+ war
+ WEB-INF

Configure a Data Source (Optional)

The "create-app" target created several Grails data source artifacts for you in the "<..>/grails-app/conf"
directory, one for each of the standard environments: DevelopmentDataSource, TestDataSource, and
ProductionDataSource. All the examples that follow operate on the development environment. For more
information on environments see Configuration#environments.

By default, each data source is configured with an in-memory HSQLDB database (great for testing, but
probably not that useful for live deployment) so this step is optional:

class DevelopmentDataSource {
boolean pooling = true

Document generated by Confluence on May 01, 2007 11:37 Page 33


String dbCreate = "create-drop" // one of 'create', 'create-drop','update'
String url = "jdbc:hsqldb:mem:testDB"
String driverClassName = "org.hsqldb.jdbcDriver"
String username = "sa"
String password = ""
}

Configuring the data source is a simple matter of changing the values for the desired database and driver
and placing the driver jar file in the <..>/lib directory

Create a Domain Class

Make sure you are in the root directory of your project (for argument sake "my-project) by typing

cd my-project
grails create-domain-class

The target will prompt you for the name of your domain class. A domain class is a persistent artifact and
all properties are by default persisted to the database (Go the the section on GORM (Grails Object
Relational Mapping) for more info):

class Book {
String title
String author
}

At this point you may want to create some test data. An easy way to do this is to build and save the
domain objects in the "init" closure of the Grails application bootstrap class found in
"<..>/grails-app/conf/ApplicationBootStrap.groovy":

class ApplicationBootStrap {

def init = { servletContext ->


// Create some test data
new Book(author:"Stephen King",title:"The Shining").save()
new Book(author:"James Patterson",title:"Along Came a Spider").save()
}
def destroy = {
}
}

(Note that you can build and save domain objects here the same as in controllers or other parts of Grails
applications; see Grails Object Relational Mapping (GORM) for more on domain objects.)

Create a controller

Controllers are central to Grails applications they handle web requests and URLs of the request map to a
controller class and a closure within the class.

Run the "grails generate-all" target and type in the name of the controller. In our example we type
"Book" which generates a controller called grails-app/controllers/BookController.groovy. Open up

Document generated by Confluence on May 01, 2007 11:37 Page 34


this controller and change it as follows to use dynamic Scaffolding which dynamically generates your
application at runtime:

class BookController {
def scaffold = Book
}

Make sure that you typed "Book" with a capital B.

Alternatively, you could also have left the generated controller alone, instead of replacing it with the
default scaffolding. It might be worth learning from.

Start Grails

To start your Grails app run the following target

grails run-app

This will startup in instance of the Jetty servlet engine running on port 8080. In order to start in on a
different port like e.g. 9090 use grails -Dserver.port=9090 run-app. To access the list of books open
up a browser and type:

http://localhost:8080/my-project/book/list

Or, as the "list" closure is the default action for the BookController you can type:

http://localhost:8080/my-project/book

Document generated by Confluence on May 01, 2007 11:37 Page 35


Reference

This page last changed on Apr 04, 2007 by chanwit@gmail.com.

Reference Guide

1. Command Line
2. Dynamic Methods & Properties
3. Artifact Reference
4. Tag Library
5. Validation
6. Builders

Quick References (Cheat Sheet)

PDF

Document generated by Confluence on May 01, 2007 11:37 Page 36


Artifact Reference

This page last changed on Feb 24, 2007 by takamori.

These are special properties and closures used to configure Grails artifacts.

• ApplicationBootstrap
• Codecs
• Controllers
• DataSources
• Domains
• Jobs
• Services

ApplicationBootstrap

Since: <= 0.2


Properties: none.
Closures:

• destroy
• init

Usage:

• configuration
• domain class creation

Codecs

Since: 0.4
Properties: none.
Closures:

• encode

Usage:

• Dynamic Encoding Methods

Controllers

Since: <= 0.2


Properties:

Document generated by Confluence on May 01, 2007 11:37 Page 37


• allowedMethods
• scaffold

Closures:

• beforeInterceptor
• index

Usage:

• ..

DataSources

Since: <= 0.2


Properties:

• configClass
• dbCreate
• dialect
• driverClassName
• logSql
• password
• pooling
• url
• username

Closures: none.
Usage:

• Configuration

Domains

Since: <= 0.2


Properties:

• belongsTo
• constraints
• hasMany
• mappedBy
• optionals
• transients
• withTable

Closures: none.
Usage:

Document generated by Confluence on May 01, 2007 11:37 Page 38


• ...

Jobs

Since: <= 0.3


Properties:

• cronExpression
• group
• name
• startDelay
• timeout

Closures: none.
Usage:

• ...

Services

Since: <= 0.3


Properties:

• available
• byName
• transactional

Closures: none.
Usage:

• ...

Document generated by Confluence on May 01, 2007 11:37 Page 39


Builders Reference

This page last changed on Nov 24, 2006 by graeme.rocher@gmail.com.

Grails Builders.

Introduction

Grails uses many Groovy builders to provide mini-DSL like constructs for an array of different things. This
page details the builders with in Grails and provides a reference to the syntax.

• Hibernate Criteria Builder


• Domain Class Constraints Builder
• Spring Bean Builder

Document generated by Confluence on May 01, 2007 11:37 Page 40


Hibernate Criteria Builder

This page last changed on Mar 26, 2007 by masukomi.

Hibernate Criteria Builder

Description

A builder for creating criteria-based queries analogous to those found in the Hibernate Criteria API, the
nodes on this builder map the 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")
}

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:

import org.hibernate.FetchMode as FM
....
def results = c.list {
maxResults(10)
firstResult(50)
fetchMode("aRelationship", FM.EAGER)
}

If you invoke the builder with no method name such as:

c { ... }

It defaults to the 'list' call, if this is not desired use the specific methods 'list','get' and 'scroll' which return
a list, a unique result and a scrollable result set respectively.

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 {

Document generated by Confluence on May 01, 2007 11:37 Page 41


...
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 accounts 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)

Document generated by Confluence on May 01, 2007 11:37 Page 42


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.

Node Reference

Node Description Example

and Logical AND operator


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

between Where the property value is


between to distinct values between("balance", 500,
1000)

eq Where a property equals a


particular value eq("branch", "London")

eqProperty Where one property must equal


another eqProperty("lastTransaction","firstTransa

gt Where a property is greater than


a particular value gt("balance",1000)

gtProperty Where a one property must be


greater than another gtProperty("balance","overdraft")

ge Where a property is greater than


or equal to a particular value ge("balance",1000)

geProperty Where a one property must be


greater than or equal to another geProperty("balance","overdraft")

idEq Where an objects id equals the


specified value idEq(1)

ilike A case-insensitive 'like'


expression ilike("holderFirstName","Steph%")

Document generated by Confluence on May 01, 2007 11:37 Page 43


in Where a one property is
contained within the specified list 'in'("holderAge",[18..65])
of values
note: 'in' is a groovy reserve
word, we must escape it by
quotes.

isEmpty Where a collection property is


empty isEmpty("transactions")

isNotEmpty Where a collection property is


not empty isNotEmpty("transactions")

isNull Where a property is null


isNull("holderGender")

isNotNull Where a property is not null


isNotNull("holderGender")

lt Where a property is less than a


particular value lt("balance",1000)

ltProperty Where a one property must be


less than another ltProperty("balance","overdraft")

le Where a property is less than or


equal to a particular value le("balance",1000)

leProperty Where a one property must be


less than or equal to another leProperty("balance","overdraft")

like Equivalent to SQL like expression


like("holderFirstName","Steph%")

ne Where a property does not


equals a particular value ne("branch", "London")

neProperty Where one property does not


equal another neProperty("lastTransaction","firstTransa

not Negates an expression, logical


NOT not {
between("balance", 500,
1000)
}

or Logical OR operator
or {
between("balance", 500,
1000)
eq("branch", "London")

Document generated by Confluence on May 01, 2007 11:37 Page 44


}

order Order the results by a particular


property order("holderLastName",
"desc")

sizeEq Where a collection property's


size equals a particular value sizeEq("transactions", 10)

Document generated by Confluence on May 01, 2007 11:37 Page 45


Spring Bean Builder

This page last changed on Apr 19, 2007 by pledbrook.

The Spring Bean Builder (Since 0.4)

Motivation

Spring is very powerful, but the XML based syntax is very verbose and violates DRY at multiple levels
even with the recent additions to Spring 2.0. This Bean builder in Grails aims to provide a simplified way
of wiring together dependencies that uses Spring at its core.

In addition, Spring's regular way of configuration (via XML) is essentially static and very difficult to
modify and configure at runtime other than programmatic XML creation which is both error prone and
verbose. Grails' BeanBuilder changes all that by making it possible to programmatically wire together
components at runtime thus allowing you to adapt the logic based on system properties or environment
variables.

This enables the code to adapt to its environment and avoids unnecessary duplication of code (having
different Spring configs for test, development and production environments)

The BeanBuilder class

Grails provides a grails.spring.BeanBuilder class that uses dynamic Groovy to construct bean
definitions. The basics are as follows:

import org.apache.commons.dbcp.BasicDataSource
import org.codehaus.groovy.grails.orm.hibernate.ConfigurableLocalSessionFactoryBean;
import org.springframework.context.ApplicationContext;

def bb = new grails.spring.BeanBuilder()

bb.beans {
dataSource(BasicDataSource) {
driverClassName = "org.hsqldb.jdbcDriver"
url = "jdbc:hsqldb:mem:grailsDB"
username = "sa"
password = ""
}
sessionFactory(ConfigurableLocalSessionFactoryBean) {
dataSource = dataSource
hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop",
"hibernate.show_sql":true ]
}

ApplicationContext appContext = bb.createApplicationContext()

The above example shows how you would configure Hibernate with an appropriate data source with the
BeanBuilder class.

Basically what is happening here is the name of each method call (in this case "dataSource" and

Document generated by Confluence on May 01, 2007 11:37 Page 46


"sessionFactory" maps to the name of the bean in Spring. The first argument to the method is the beans
class, whilst the last argument is a closure. Within the body of the closure you can set properties on the
bean using standard Groovy syntax

Bean references are resolved automatically be using the name of the bean. This can be seen in the
example above with the way the sessionFactory bean resolves the dataSource reference.

Certain special properties related to bean management can also be set by the builder, as seen in the
following code:

sessionFactory(ConfigurableLocalSessionFactoryBean) { bean ->


bean.autowire = 'byName' // Autowiring behaviour. The other option is 'byType'.
[autowire]
bean.initMethod = 'init' // Sets the initialisation method to 'init'. [init-method]
bean.destroyMethod = 'destroy' // Sets the destruction method to 'destroy'.
[destroy-method]
dataSource = dataSource
hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop",
"hibernate.show_sql":true ]
}

The strings in square brackets are the names of the equivalent bean attributes in Spring's XML definition.

Using Constructor arguments

Constructor arguments can be defined using parameters to each method that reside between the class of
the bean and the last closure:

bb.beans {
exampleBean(MyExampleBean, "firstArgument", 2) {
someProperty = [1,2,3]
}
}

Configuring the BeanDefinition (Using factory methods)

The first argument to the closure is a reference to the bean configuration instance, which you can use to
configure factory methods and invoke any method on the AbstractBeanDefinition class:

bb.beans {
exampleBean(MyExampleBean) { bean ->
bean.factoryMethod = "getInstance"
bean.singleton = false
someProperty = [1,2,3]
}
}

As an alternative you can also use the return value of the bean defining method to configure the bean:

bb.beans {
def example = exampleBean(MyExampleBean) {
someProperty = [1,2,3]

Document generated by Confluence on May 01, 2007 11:37 Page 47


}
example.factoryMethod = "getInstance"
}

Using Factory beans

Spring defines the concept of factory beans and often a bean is created not from a class, but from one of
these factories. In this case the bean has no class and instead you must pass the name of the factory
bean to the bean:

bb.beans {
myFactory(ExampleFactoryBean) {
someProperty = [1,2,3]
}
myBean(myFactory) {
name = "blah"
}
}

Note in the example above instead of a class we pass a reference to the myFactory bean into the bean
defining method. Another common task is provide the name of the factory method to call on the factory
bean. This can be done using Groovy's named parameter syntax:

bb.beans {
myFactory(ExampleFactoryBean) {
someProperty = [1,2,3]
}
myBean(myFactory:"getInstance") {
name = "blah"
}
}

Here the getInstance method on the ExampleFactoryBean bean will be called in order to create the
myBean bean.

Creating bean references at runtime

Sometimes you don't know the name of the bean to be created until runtime. In this case you can use a
GString to invoke a bean defining method dynamically:

def beanName = "example"


bb.beans {
"${beanName}Bean"(MyExampleBean) {
someProperty = [1,2,3]
}
}

In this case the beanName variable defined earlier is used when invoking a bean defining method.

Referencing beans dynamically and from a Parent ApplicationContext

Furthermore, because sometimes bean names are not known until runtime you may need to reference

Document generated by Confluence on May 01, 2007 11:37 Page 48


them by name when wiring together other beans. In this case using the "ref" method:

def beanName = "example"


bb.beans {
"${beanName}Bean"(MyExampleBean) {
someProperty = [1,2,3]
}
anotherBean(AnotherBean) {
example = ref("${beanName}Bean")
}
}

Here the example property of AnotherBean is set using a runtime reference to the "exampleBean". The
"ref" method can also be used to refer to beans from a parent ApplicationContext that is provided in the
constructor of the BeanBuilder:

ApplicationContext parent = ...//


der bb = new BeanBuilder(parent)
bb.beans {
anotherBean(AnotherBean) {
example = ref("${beanName}Bean", true)
}
}

Here the second parameter "true" specifies that the reference will look for the bean in the parent context.

Using anonymous (inner) beans

You can use anonymous inner beans by setting a property of the bean to a closure that takes an
argument that is the bean type:

bb.beans {
marge(Person.class) {
name = "marge"
husband = { Person p ->
name = "homer"
age = 45
props = [overweight:true, height:"1.8m"] }
children = [bart, lisa]
}
bart(Person) {
name = "Bart"
age = 11
}
lisa(Person) {
name = "Lisa"
age = 9
}
}

In the above example we set the "marge" bean's husband property to a closure that creates an inner
bean reference. Alternatively if you have a factory bean you can ommit the type and just use passed
bean definition instead to setup the factory:

bb.beans {
personFactory(PersonFactory.class)
marge(Person.class) {
name = "marge"

Document generated by Confluence on May 01, 2007 11:37 Page 49


husband = { bean ->
bean.factoryBean = "personFactory"
bean.factoryMethod = "newInstance"
name = "homer"
age = 45
props = [overweight:true, height:"1.8m"] }
children = [bart, lisa]
}
}

Adding variables to the Binding (context)

TODO

Loading Bean definitions from the file system

You can use the BeanBuilder class to load external Groovy scripts that define beans using the same path
matching syntax defined here. Example:

def bb = new BeanBuilder("classpath:*SpringBeans.groovy")

def applicationContext = bb.createApplicationContext()

Here the BeanBuilder will load all Groovy files on the classpath ending with SpringBeans.groovy and parse
them into bean definitions. An example script can be seen below:

beans = {
dataSource(BasicDataSource) {
driverClassName = "org.hsqldb.jdbcDriver"
url = "jdbc:hsqldb:mem:grailsDB"
username = "sa"
password = ""
}
sessionFactory(ConfigurableLocalSessionFactoryBean) {
dataSource = dataSource
hibernateProperties = [ "hibernate.hbm2ddl.auto":"create-drop",
"hibernate.show_sql":true ]
}

Document generated by Confluence on May 01, 2007 11:37 Page 50


Command Line

This page last changed on Apr 30, 2007 by wangjammer5.

Command Line Reference

Usage:

For Grails 0.3 and earlier - grails [options] (target name)


For Grails 0.4 and later - grails [options] (target name) (target parameters)

Target Description

bug-report (since 0.4) Generates a ZIP containing your source


artifacts for attaching to a JIRA issue

clean Cleans the current app 'tmp' directory, can be


combined with other commands eg. grails clean
run-app

create-app Creates a new Grails application

create-controller Convenience target for creating a controller

create-domain-class Convenience target for creating domain classes

create-data-source Convenience target for creating data sources

create-job Convenience target for creating jobs

create-service Convenience target for creating services

create-taglib Convenience target for creating tag libraries

create-test-suite Convenience target for creating test suites

create-webtest Convenience target for creating functional web


tests

generate-controller Generates a controller for a specified domain class

generate-views Generates CRUD views for a specified domain


class

generate-all Generates both a controller and the views for a


specified domain class

get-dependencies Get project's dependencies with Ivy

install-ivy Install ivy dependency resolution tool

install-templates Installs the artifact and scaffolding templates

run-app Runs a grails app using the default Jetty container

run-webtest Runs the functional web tests contained within the


app

test-app Runs the unit tests contained within the app

Document generated by Confluence on May 01, 2007 11:37 Page 51


war Creates a JEE Web Application Archive (WAR) file
from the current grails app

Options can be given in the format -Dname=value

name value

server.port the port number to start the server on,


default:8080

See also: Command Line Tools

Document generated by Confluence on May 01, 2007 11:37 Page 52


Dynamic Methods Reference

This page last changed on Mar 13, 2007 by lataupe.

Dynamic Methods Reference

Grails uses special features of Groovy to provide dynamic methods and properties that are accessible
from your classes without you defining them or inheriting from a base class.

This is extremely convenient and contributes to having far less "code noise" in your applications.

The dynamic features available vary depending on the type of class you are calling from.

Controllers

Properties

• actionUri
• controllerUri
• actionName
• controllerName
• flash
• grailsApplication
• grailsAttributes
• log 0.3
• params
• session
• request
• response
• servletContext

Methods

• bindData
• chain
• render
• redirect
• getViewUri
• getTemplateUri

Domain Classes

Properties

Document generated by Confluence on May 01, 2007 11:37 Page 53


• errors
• constraints
• properties

Methods

• add
• add*
• delete
• discard
• hasErrors
• ident
• merge
• refresh
• save
• validate

Static Methods

• count
• countBy*
• createCriteria
• executeQuery
• executeUpdate
• exists
• find
• findAll
• findBy*
• findAllBy*
• findWhere
• findAllWhere
• get
• getAll
• list
• listOrderBy*
• withCriteria
• withTransaction

Document generated by Confluence on May 01, 2007 11:37 Page 54


Controller Dynamic Methods

This page last changed on Mar 01, 2007 by hansamann.

Controller Dynamic Methods & Properties

Properties

actionUri

Description

The relative Uri of the action

controllerUri

Description

The relative Uri of the controller

actionName

Description

The name of the current action

controllerName

Description

The name of the current controller

flash

Description

A map that allows temporary storage of objects for the next request and the next request only. The
subequent request will clear the storage of any variables stored in the first
request. This is a convenience map that allows you to store information temporarily, which is very
convenient when using redirection or chaining.

Document generated by Confluence on May 01, 2007 11:37 Page 55


Example

flash['message'] = 'hello world!'

grailsApplication

Description

An instance of org.codehaus.groovy.grails.commons.GrailsApplication that provides information about the


grails application

Example

return [controllers : grailsApplication.controllers]

grailsAttributes

Description

An instance of org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes that provides


convenience methods for the current grails request

Example

def templateUri = grailsAttributes.getTemplateUri("myTemplate",request)

log

Description

An instance of the Log4J logger for the controller. Grails creates a log per controller, which you can call
on at any time to perform logging. When configuring Log4J using WEB-INF/log4j.properties you should
use properties of the form:

log4j.logger.TestController=debug, stdout

Where "TestController" is the fully qualified class name of your controller class.

Example

You simply use the standard Log4J logging methods:

Document generated by Confluence on May 01, 2007 11:37 Page 56


log.trace('Doing something')
log.debug('Debug info here')
log.error('Something went wrong')
log.error('Something went wrong', someException)

params

Description

A map of the available request parameters and/or controller parameters

Example

def a = Account.get( params["id"] )

request

Description

The HttpServletRequest instance for the request. Request attributes can be accessed with the Map syntax
provided by groovy

Example

request['anAttribute']
request.getHeader("user-agent")

response

Description

The HttpServletResponse instance

Example

response.setHeader("myheader", "myvalue")

servletContext

Description

The ServletContext instance as per the servlet API

Document generated by Confluence on May 01, 2007 11:37 Page 57


Example

def myUrl = servletContext.getResource("/path/to/url")

session

Description

Provides access to a map of the HttpSession instance

Example

def loggedUser = session["loggedUser"]

Methods

bindData

Description

Binds data to a target instance performing type conversion if necessary. Useful for binding request
parameters to properties of objects. Since 0.4 this has been modified to never assign values for the
special ORM properties "id" or "version", nor the special Groovy properties (for Groovy classes)
'metaClass' and 'properties'. Note that this only operates on the top-level object currently, nested object
id/version etc assignments must be suppressed explicitly using the "excludes" parameter.

Parameters

• target - The target object to bind to


• params - The parameters to bind to the target object
• excludes (optional) - A list of property names to exclude from the binding, with dot-notation
support. Use to suppress values being assigned from form data.

Examples

bindData(target, this.params) // binds request parameters to a target object


bindData(target, this.params, ['firstName', 'lastName']) // exclude firstName and lastName
(since 0.4)

chain

Description

Document generated by Confluence on May 01, 2007 11:37 Page 58


Chains the model (The model is retained from one action to the next) from one action to the next
allowing you to build up the model from an action chain.

Parameters

• uri - The full uri to redirect to (example /book/list, book/show/2)


• controller - The controller to redirect to, defaults to the current controller if not specified
• action - The action to redirect to, either a string name or a reference to an action within the current
controller
• id - The id to use in redirection
• model (required) - The model to chain to the next action
• params (optional) - Parameters to pass to the action chained to.

Examples

chain(action:"details",model:[book:new Book(title:'The Shawshank Redemption')])

getViewUri

Description

Retrieves the relative uri of a named view within the Grails application. If the view contains a '/' at the
start it will be resolved relative to the views folder as a shared view otherwise it will be relative to the
current controller

Parameters

• name (required) - The name of the view

Examples

assert getViewUri('myView') == /WEB-INF/grails-app/views/controllerName/myView.gsp


assert getViewUri('/mySharedView') == /WEB-INF/grails-app/views/mySharedView.gsp

getTemplateUri

Description

Retrieves the relative uri of a named template within the Grails application. If the template contains a '/'
at the start it will be resolved relative to the views folder as a shared template otherwise it will be relative
to the current controller

Parameters

Document generated by Confluence on May 01, 2007 11:37 Page 59


• name (required) - The name of the template

Examples

assert getTemplateUri('myTemplate') == /WEB-INF/grails-app/views/controllerName/_myTemplate.gsp


assert getTemplateUri('/mySharedTemplate') == /WEB-INF/grails-app/views/_mySharedTemplate.gsp

redirect

Description

Redirects the current action to another action, optionally passing parameters and/or errors

Parameters

• uri - The full uri to redirect to (example /book/list, book/show/2)


• controller - The controller to redirect to, defaults to the current controller if not specified
• action - The action to redirect to, either a string name or a reference to an action within the current
controller
• id - The id to use in redirection
• params - Parameters to pass to the action redirected to.

Examples

redirect(uri:"book/list")
redirect(action:"show")
redirect(controller:"book",action:"list")
redirect(action:"show",id:4, params:[author:"Stephen King"])

render

Description

A multi-purpose method for rendering responses to the client which is best illustrated with a few
examples!

Parameters

• text (optional) - The text to render


• builder (optional) - The builder to use when rendering markup
• view (optional) - The view to delegate the rendering to
• template (optional) - The template to render
• var (optional) - The name of the variable to be passed into a template, defaults to the groovy
default argument 'it' if not specified
• bean (optional) - The beanto use in rendering
• model (optional) - The model to use in rendering

Document generated by Confluence on May 01, 2007 11:37 Page 60


• collection (optional) - For rendering a template against each item in a collection
• contentType (optional) - The contentType of the response
• encoding (optional) - The encoding of the response

Examples

// renders text to response


render "some text"

// renders text for a specified content-type/encoding


render(text:"<xml>some xml</xml>",contentType:"text/xml",encoding:"UTF-8")

// render a template to the response for the specified model


render(template:"book",model:[book:new Book(title:'The Shining',author:'Stephen King')])

// render each item in the collection using the specified template


render(template:"book",collection:[b1, b2, b3])

// render a template to the response for the specified bean


render(template:"book",bean:new Book(title:'The Shining',author:'Stephen King'))

// render the view with the specified model


render(view:"viewName",model:[book:new Book(author:'Stephen King')])

// render the view with the controller as the model


render(view:"viewName"
)
// render some markup to the response
render {
div(id:"myDiv", "some text inside the div")
}

// render some XML markup to the response


render(contentType:"text/xml") {
books {
for(b in books) {
book(title:b.title,author:b.author)
}
}
}

// render an OpenRico (http://www.openrico.org) response with the builder attribute:


def b = new Book(title:"Kiss the Girls", author:"James Patterson")
render(builder:"rico") {
object(id:"bookUpdater") {
book(title:b.title,author:b.author)
}
}

// render a JSON ( http://www.json.org ) response with the builder attribute:


render(builder:"json") {
book(title:b.title,author:b.author)

Document generated by Confluence on May 01, 2007 11:37 Page 61


DomainClass Dynamic Methods

This page last changed on Apr 28, 2007 by lataupe.

Domain Class Dynamic Methods & Properties

Properties

errors

Description

A list of errors from the last call to the "validate" or "save" method

Example

def b = new Book(title:"The Shining")


if(!b.validate()) {
b.errors.each {
println it
}
}

constraints

Description

A list of org.codehaus.groovy.grails.validation.ConstrainedProperty instances applied against the domain


class by the constraints property (see Validation)

Example

def b = new Book(title:"The Shining")


b.constraints.each {
println it.name
println it.maxLength
}

properties

Description

Document generated by Confluence on May 01, 2007 11:37 Page 62


Allows access to the domain class properties as a map and perform types conversion when set allowing
properties to be set from request parameters for example.

Example

def b = new Book(title:"The Shining")


b.properties = this.params

Methods

add

Description

Adds a domain class relationship to a specific one-to-many or many-to-many relationship.

Parameters

• to - specifies the hasMany relationship name to which the object is being added

Example

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


.add(to:"fiction",
new Book(title:"IT"))
.add(to:"non-fiction",
new Book(title:"On Writing: A Memoir of the Craft"))
.save()

add*

Description

Adds a domain class relationship for one-to-many or many-to-many relationship, where the relationship
is indicated by the class used as the suffix to the method.

Example

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


.addBook(new Book(title:"IT"))
.addBook(new Book(title:"The Stand"))

Document generated by Confluence on May 01, 2007 11:37 Page 63


.save()

delete

Description

Deletes a domain class instance from the database

Example

def b = Book.get(1)
b.delete()

discard

Description

Discards any changes that have been made during an update. Note that this method will not clean or
reset the object with the original values it will just prevent it from being automatically saved by Grails.

Example

def b = Book.get(1)
b.title = "Blah"
b.discard() // changes won't be applied now

hasErrors

Description

True if the domain class instance has errors following a call to "validate" or "save"

Example

def b = new Book(title:"The Shining")


b.validate()
if(b.hasErrors()) {
b.errors.each {
println it
}
}

Document generated by Confluence on May 01, 2007 11:37 Page 64


ident

Description

Returns the value of the identity property of the domain class regardless of the name of the identity
property itself

Example

def b = new Book(title:"The Shining")


b.save()

println b.ident()

merge

Description

see Hibernate3's merge

refresh

Description

Refreshes a domain classes state from the database

Example

def b = Book.get(1)
b.refresh()

save

Description

Saves a domain class instance to the database cascading updates to any child instances if required.
Returns false if validation failed and the instance was not saved

Parameters

Document generated by Confluence on May 01, 2007 11:37 Page 65


• validate (optional) - Set to false if validation should be skipped

Example

def b = new Book(title:"The Shining")


if( !b.save() ) {
b.errors.each {
println it
}
}

validate

Description

Validates a domain class against the applied constraints (see Validation)

Example

def b = new Book(title:"The Shining")


if( !b.validate() ) {
b.errors.each {
println it
}
}

Static Methods

count

Description

Counts the number of instances in the database and returns the result

Parameters

None

Example

def noOfBooks = Book.count()

Document generated by Confluence on May 01, 2007 11:37 Page 66


countBy

Description

Dynamic method that uses the properties of the domain class to allow the creation of Grails query
method expressions that count the number of records returned

Examples

class Book {
Long id
Long version
String title
Date releaseDate
String author
}

def c = Book.countByTitle("The Shining")


c = Book.countByTitleAndAuthor("The Sum of All Fears", "Tom Clancy")
c = Book.countByReleaseDateBetween(firstDate, new Date())
c = Book.countByReleaseDateGreaterThanEquals(firstDate)
c = Book.countByTitleLike("%Hobbit%")
c = Book.countByTitleNotEqual("Harry Potter")
c = Book.countByReleaseDateIsNull()
c = Book.countByReleaseDateIsNotNull()

see also OperatorNamesInDynamicMethods

createCriteria

Description

Creates a grails.orm.HibernateCriteriaBuilder instance for the domain class. (see Builders)

Example

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

exists

Description

Document generated by Confluence on May 01, 2007 11:37 Page 67


Checks whether an instance exists for the specified id and returns true if it does

Parameters

• id (required) - The id of the instance

Example

if(Account.exists(1)) {
// do something
}

executeQuery

Description

Allows the execution of HQL queries against a domain class

Parameters

• query (required) - A query in HQL


• params (optional) - A single object or a List of parameters for a positional parametrized HQL query
• (Since 0.5) params also could be a Map of HQL named parameters and could contain 'max' and
'offset' pagination params
• (Since 0.5) paginationParams (optional) - A map which might contain 'max' and 'offset' pagination
params

Example

// using with single parameter


Account.executeQuery( "select distinct a.number from Account a where a.branch = ?", 'London' );
// using with single parameter and pagination params (since 0.5)
Account.executeQuery( "select distinct a.number from Account a where a.branch = ?", 'London',
[max:10,offset:5] );
// using with list (or array) of parameters
Account.executeQuery( "select distinct a.number from Account a where a.branch = ? and a.created
> ?", ['London',lastMonth] );
// using with Map of named parameters (since 0.5)
Account.executeQuery( "select distinct a.number from Account a where a.branch = :branch",
[branch:'London'] );
// using with Map of named parameters and pagination params (since 0.5)
Account.executeQuery( "select distinct a.number from Account a where a.branch = :branch",
[branch:'London', max:10, offset:5] );

find

Description

Document generated by Confluence on May 01, 2007 11:37 Page 68


Finds and returns the first result for the given query or null if no instance was found

Parameters

• query (required) - Either an HQL query or a instance of the domain class for query by example
• params (optional) - A List of parameters for a positional parametrized HQL query
• (Since 0.5) params also could be a Map of HQL named parameters

Example

// Dan brown's first book


Book.find("from Book as b where b.author='Dan Brown'")
// with a positional parameter
Book.find("from Book as b where b.author=?",['Dan Brown'])
// with a named parameter (since 0.5)
Book.find("from Book as b where b.author=:author",[author:'Dan Brown'])

def b = new Book(author:"Dan Brown")


Book.find(b) // query by example

findAll

Description

Finds all of the domain class instances for the specified query

Syntax

Book.findAll()
Book.findAll(example)
Book.findAll(query,params)
Book.findAll(query,params,pageMap)
Book.findAll(query,params,max)
Book.findAll(query,params,max,offset) // (since 0.5)

Parameters

• query (optional) - Either an HQL query or a instance of the domain class for query by example
• example (optional) - The instance of requested domain object for query by example
• params (optional) - A List of parameters for a positional parametrized HQL query
• (Since 0.5) params also could be a Map of HQL named parameters
• pageMap (optional) - The Map containing parameters 'max' or/and 'offset' (see examples below)
• max (optional) - The maximum number of results to retrieve
• (Since 0.5) offset (optional) - The offset from the first result to find from

Examples

Document generated by Confluence on May 01, 2007 11:37 Page 69


// everything
Book.findAll()
// with a positional parameter
Book.findAll("from Book as b where b.author=?",['Dan Brown'])
// 10 books from Dan Brown staring from 5th book ordered by release date (since 0.5)
Book.findAll("from Book as b where b.author=? order by b.releaseDate",['Dan Brown'],10,5)

// examples with max/offset usage


def query = "from Book as b where b.author='Dan Brown' order by b.releaseDate"
// first 10 books
Book.findAll(query,10)
// 10 books starting from 5th (since 0.5)
Book.findAll(query,10,5)
// the same as previous, but have more clarity
Book.findAll(query,[max:10,offset:5])

// examples with named parameters (since 0.5)


Book.findAll("from Book as b where b.author=:author", [author:'Dan Brown'])
Book.findAll("from Book as b where b.author=:author", [author:'Dan Brown'], [max:10, offset:5])
Book.findAll("from Book as b where b.author in (:authors)", [authors:['Dan Brown','Jack
London']])

def b = new Book(author:"Dan Brown")


Book.findAll(b) // query by example

findBy

Description

Dynamic method that uses the properties of the domain class to allow the creation of Grails query
method expressions that return the first result of the query

Examples

class Book {
Long id
Long version
String title
Date releaseDate
String author
}

def b = Book.findByTitle("The Shining")


b = Book.findByTitleAndAuthor("The Sum of All Fears", "Tom Clancy")
b = Book.findByReleaseDateBetween(firstDate, new Date())
b = Book.findByReleaseDateGreaterThanEquals(firstDate)
b = Book.findByReleaseDateLessThanEquals(firstDate)
b = Book.findByTitleLike("%Hobbit%")
b = Book.findByTitleIlike("%Hobbit%") // (since 0.5) - ignorecase
b = Book.findByTitleNotEqual("Harry Potter")
b = Book.findByReleaseDateIsNull()
b = Book.findByReleaseDateIsNotNull()

see also OperatorNamesInDynamicMethods

findAllBy

Description

Document generated by Confluence on May 01, 2007 11:37 Page 70


Dynamic method that uses the properties of the domain class to allow the creation of Grails query
method expressions that return all instances of the domain class

Examples

class Book {
Long id
Long version
String title
Date releaseDate
String author
}

def results = Book.findAllByTitle("The Shining", [max:10, sort:"title", order:"desc",


offset:100] )
results = Book.findAllByTitleAndAuthor("The Sum of All Fears", "Tom Clancy")
results = Book.findAllByReleaseDateBetween(firstDate, new Date())
results = Book.findAllByReleaseDateGreaterThanEquals(firstDate)
results = Book.findAllByTitleLike("%Hobbit%")
results = Book.findAllByTitleIlike("%Hobbit%") // (since 0.5) - ignorecase
results = Book.findAllByTitleNotEqual("Harry Potter")
results = Book.findAllByReleaseDateIsNull()
results = Book.findAllByReleaseDateIsNotNull()

see also OperatorNamesInDynamicMethods

findWhere

Description

Uses named arguments that match the property names of the domain class to produce a query that
returns the first result.

Examples

class Book {
Long id
Long version
String title
Date releaseDate
String author
}

def b = Book.findWhere(title:"The Shining", author:"Stephen King")

findAllWhere

Description

Document generated by Confluence on May 01, 2007 11:37 Page 71


Uses named arguments that match the property names of the domain class to produce a query that
returns all of the matching results.

Examples

class Book {
Long id
Long version
String title
Date releaseDate
String author
}

def books = Book.findAllWhere(author:"Stephen King")

get

Description

Retrieves an instance of the domain class for the specified id, otherwise returns null

Examples

def b = Book.get(1)

getAll

Description

(Since 0.5) Retrieves an instances of the domain class for the specified ids and returns a list of these
instances, ordered by the original ids list. If some of provided ids are null or there are no instances with
these ids, then result list will contain null values on corresponding positions.

Examples

// get a list which contains Book instances with ids 2, 1, 3 respectively


def bookList = Book.getAll(2,1,3)
// can take a list of ids as only argument, extremely useful when ids list calculated in code
def bookList = Book.getAll([1,2,3])
// when called without arguments returns list of all objects
def bookList = Book.getAll()

list

Document generated by Confluence on May 01, 2007 11:37 Page 72


Description

Lists all of the instances of the domain class.

Parameters

• max - The maximum number to list


• offset - The offset from the first result to list from
• order - The order to list by, either "desc" or "asc"
• sort - The property name to sort by

Examples

// list everything
def results = Book.list()
// list 10 results
def results = Book.list(max:10)
// list 10 results, offset by 100
def results = Book.list(max:10, offset:100)
// list 10 results, offset by 100, orderd by title in descending order
def results = Book.list(max:10, offset:100, sort:"title", order:"desc")

listOrderBy

Description

Lists all of the instances of the domain class ordered by the property in the method expression

Parameters

• max - The maximum number to list

Examples

def results = Book.listOrderByAuthor() // everything


def results = Book.listOrderByTitle(max:10) // 10 results
def results = Book.listOrderByTitle(max:10, offset:100, order:"desc") // 10 results, offset
from 100

withCriteria

Description

Allows inline execution of criteria with a closure. (Since 0.4)

Document generated by Confluence on May 01, 2007 11:37 Page 73


Parameters

• arguments (optional) - A map on named arguments that will be set on the criteria instance
• closure - A closure that defines the criteria

Examples

def results = Book.withCriteria {


def now = new Date()
between('releaseDate', now-7, now)
like('title', '%Groovy%')
}

withTransaction

Description

Uses Spring's TransactionTemplate combination with a closure. Since 0.4

Parameters

• closure - A closure that gets passed an instance of the Spring TransactionStatus to allow
programmatic management of savepoints (See SavepointManager) and transaction rollback

Examples

Book.withTransaction { tx ->
def b = new Book(title:"Groovy in Action")

b.save()

// some logic that goes wrong


tx.setRollbackOnly()

Document generated by Confluence on May 01, 2007 11:37 Page 74


OperatorNamesInDynamicMethods

This page last changed on Apr 13, 2007 by lataupe.

The following operator names can be used within the respective dynamic methods names (countBy*,
findBy*, findAllBy*)

• LessThan
• LessThanEquals
• GreaterThan
• GreaterThanEquals
• Between
• Like
• Ilike (i.e. ignorecase like)
• IsNotNull
• IsNull
• Not
• Equal
• NotEqual
• And
• Or (can sometimes be problematic as of 0.5-snap)

The above operator names can be considered keywords, i.e. you will run into problems when querying
domain classes that have one of these names used as property names.

Document generated by Confluence on May 01, 2007 11:37 Page 75


Tag Library Reference

This page last changed on Aug 08, 2006 by mercnboy3.

The Grails Custom Tag Library

Grails supports both GSP and JSP as view technologies. There are however some key differences between
the 2 view technologies which are listed below:

• GSP uses groovy inside scriptlets while JSP is Java


• GSP attribute values when surrounded with the ${..} (eg. test="${it=='true'}") syntax are Groovy
expressions, while in JSP these are JSTL expressions (and hence more limited)
• JSP supports custom tag libraries through the TLD while GSP supports custom tag libraries with
Grails Dynamic Tag Libraries and does not support JSTL
• GSP supports GString expressions inside the content whilst JSP requires you to use <c:out
value="${it}" />

There are many shared tags but some additional ones for both GSP (mainly groovy syntax tags) and JSP
hence we have 2 reference sections:

1. GSP Tag Reference


2. JSP Tag Reference

Document generated by Confluence on May 01, 2007 11:37 Page 76


GSP Tag Reference

This page last changed on Apr 20, 2007 by a.shneyderman.

GSP Tag Reference

Logical Tags

• if
• else
• elseif

Iterative Tags

• while
• each
• collect
• findAll
• grep

Assignment Tags

• def
• set

Linking Tags

• link
• createLink
• createLinkTo

Ajax Tags

• remoteField
• remoteFunction
• remoteLink
• formRemote
• submitToRemote

Form Tags

• actionSubmit
• actionSubmitImage
• checkBox
• currencySelect

Document generated by Confluence on May 01, 2007 11:37 Page 77


• form
• hiddenField
• datePicker
• select
• localeSelect
• textField
• textArea
• timeZoneSelect

UI Tags

• richTextEditor

Rendering & Layout Tags

• render
• renderErrors
• layoutHead
• layoutBody
• layoutTitle
• pageProperty
• paginate
• sortableColumn (Since 0.5)

Validation Tags

• eachError
• hasErrors
• message

Document generated by Confluence on May 01, 2007 11:37 Page 78


GSP Tag - collect

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - collect

Description

Uses the Groovy JDK collect method to iterate over each element of the specified object transforming the
result using the expression in the closure

Parameters

• in - The object to iterative over

Examples

Books titles:
<g:collect in="${books}" expr="it.title">
<p>Title: ${it}</p>
</g:collect>

Document generated by Confluence on May 01, 2007 11:37 Page 79


GSP Tag - def

This page last changed on Apr 20, 2007 by a.shneyderman.

Tag - def

Description

Defines a variable to be used on GSP page.

Parameters

• var - The name of the variable


• value - The initial value to be assgined

Examples

<g:def var="now" value="${new Date()}" />

Document generated by Confluence on May 01, 2007 11:37 Page 80


GSP Tag - each

This page last changed on Apr 21, 2007 by takamori.

Tag - each

Description

Uses the Groovy JDK each method to iterate over each element of the specified object

Parameters

• in - The object to iterate over


• status (optional) - The name of a variable to store the iteration index in. For the first iteration this
variable has a value of 0, for the next, 1, and so on. If this parameter is used, then var is required.
• var (optional) - The name of the item.

You can't use "it" within a GSP Dynamic tag!

Note that var must be specified when the iterator value is to be used from within the body of a
GSP Dynamic Tag , such as in g:link. See the example below.

Examples

<g:each in="${books}">
<p>Title: ${it.title}</p>
<p>Author: ${it.author}</p>
</g:each>

With a named item:

<g:each var="book" in="${books}">


<p>Title: ${book.title}</p>
<p>Author: ${book.author}</p>
</g:each>

Another example, where a named item is necessary (otherwise the access to the title property will fail):

<g:each in="${itemList}" var="item">


<g:link action="show" id="${item.id}">${item.title}</g:link>
</g:each>

Using the status parameter to alternate the coloring of a table's rows:

<tbody>
<g:each status="i" in="${itemList}" var="item">

Document generated by Confluence on May 01, 2007 11:37 Page 81


<!-- Alternate CSS classes for the rows. -->
<tr class="${ (i % 2) == 0 ? 'a' : 'b'}">
<td>${item.id?.encodeAsHTML()}</td>
<td>${item.parentId?.encodeAsHTML()}</td>
<td>${item.type?.encodeAsHTML()}</td>
<td>${item.status?.encodeAsHTML()}</td>
</tr>
</g:each>
</tbody>

Document generated by Confluence on May 01, 2007 11:37 Page 82


GSP Tag - else

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - else

Description

The logical else tag

Parameters

None

Examples

<g:if test="${name == 'fred'}">


Hello Fred!
</g:if>
<g:else>
Hello ${name}! Do I know you?
</g:else>

Document generated by Confluence on May 01, 2007 11:37 Page 83


GSP Tag - elseif

This page last changed on May 25, 2006 by jania902@gmail.com.

Tag - elseif

Description

The logical elseif tag

Parameters

• test - The expression to test

Examples

<g:if test="${name == 'fred'}">


Hello Fred!
</g:if>
<g:elseif test="${name == 'bob'}">
Hello bob!
</g:else>

Document generated by Confluence on May 01, 2007 11:37 Page 84


GSP Tag - findAll

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - findAll

Description

Uses the Groovy JDK findAll method to iterate over each element of the specified object that match the
GPath expression within the attribute "expr"

Parameters

• in - The object to iterative over


• expr - A GPath expression

Examples

Stephen King's Books:


<g:findAll in="${books}" expr="it.author == 'Stephen King'">
<p>Title: ${it.title}</p>
</g:findAll>

Document generated by Confluence on May 01, 2007 11:37 Page 85


GSP Tag - grep

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - grep

Description

Uses the Groovy JDK grep method to iterate over each element of the specified object that match the
specified "filter" attribute. The filter can be different instances such as classes, regex patterns etc.

Parameters

• in - The object to iterative over


• filter - The filter instance

Examples

Stephen King's non-fiction Books:


<g:grep in="${books}" filter="NonFictionBooks.class">
<p>Title: ${it.title}</p>
</g:grep>

Document generated by Confluence on May 01, 2007 11:37 Page 86


GSP Tag - if

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - if

Description

The logical if tag

Parameters

• test - The expression to test

Examples

<g:if test="${name == 'fred'}">


Hello ${name}!
</g:if>

Document generated by Confluence on May 01, 2007 11:37 Page 87


GSP Tag - layoutBody

This page last changed on Apr 19, 2006 by graeme.rocher@gmail.com.

Tag - layoutBody

Description

Used in layouts to output the contents of the body tag of the decorated page.

Parameters

None

Examples

Example decorated page:

<html>
<head>
<meta name="layout" content="myLayout" />
<script src="myscript.js" />
</head>
<body>Page to be decorated</body>
</html>

Example decorator layout:

<html>
<head>
<script src="global.js" />
<g:layoutHead />
</head>
<body><g:layoutBody /></body>
</html>

Results in:

<html>
<head>
<script src="global.js" />
<script src="myscript.js" />
</head>
<body>Page to be decorated</body>
</html>

Document generated by Confluence on May 01, 2007 11:37 Page 88


GSP Tag - layoutHead

This page last changed on Apr 19, 2006 by graeme.rocher@gmail.com.

Tag - layoutHead

Description

Used in layouts to output the contents of the head tag of the decorated page. Equivalent to the SiteMesh
<decorator:head /> tag.

Parameters

None

Examples

Example decorated page:

<html>
<head>
<meta name="layout" content="myLayout" />
<script src="myscript.js" />
</head>
<body>Page to be decorated</body>
</html>

Example decorator layout:

<html>
<head>
<script src="global.js" />
<g:layoutHead />
</head>
<body><g:layoutBody /></body>
</html>

Results in:

<html>
<head>
<script src="global.js" />
<script src="myscript.js" />
</head>
<body>Page to be decorated</body>
</html>

Document generated by Confluence on May 01, 2007 11:37 Page 89


GSP Tag - layoutTitle

This page last changed on Apr 19, 2006 by graeme.rocher@gmail.com.

Tag - layoutTitle

Description

Used in layouts to output the contents of the title tag of the decorated page. Equivalent to the SiteMesh
<decorator:title /> tag.

Parameters

None

Examples

Example decorated page:

<html>
<head>
<meta name="layout" content="myLayout" />
<title>Hello World!</title>
<script src="myscript.js" />
</head>
<body>Page to be decorated</body>
</html>

Example decorator layout:

<html>
<head>
<title><g:layoutTitle default="Some Title" /></title>
<script src="global.js" />
<g:layoutHead />
</head>
<body><g:layoutBody /></body>
</html>

Results in:

<html>
<head>
<title>Hello World!</title>
<script src="global.js" />
<script src="myscript.js" />
</head>
<body>Page to be decorated</body>
</html>

Document generated by Confluence on May 01, 2007 11:37 Page 90


GSP Tag - pageProperty

This page last changed on May 25, 2006 by jania902@gmail.com.

Tag - pageProperty

Description

Used in layouts to output the contents a property of the decorated page. Equivalent to the SiteMesh
<decorator:getProperty/> tag.

Parameters

None

Examples

Example decorated page:

<html>
<head>
<meta name="layout" content="myLayout" />
<script src="myscript.js" />
</head>
<body onload="alert('hello');">Page to be decorated</body>
</html>

Example decorator layout:

<html>
<head>
<script src="global.js" />
<g:layoutHead />
</head>
<body onload="${pageProperty(name:'body.onload')}"><g:layoutBody /></body>
</html>

Results in:

<html>
<head>
<script src="global.js" />
<script src="myscript.js" />
</head>
<body onload="alert('hello');">Page to be decorated</body>
</html>

Document generated by Confluence on May 01, 2007 11:37 Page 91


GSP Tag - paginate

This page last changed on Mar 05, 2007 by marceloverdijk.

Tag - paginate

Description

Creates next/previous buttons and a breadcrumb trail to allow pagination of results

Parameters

• total (required) - The total number of results to paginate


• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• params (optional) - A map containing request parameters
• prev (optional) - The text to display for the previous link (defaults to "Previous" as defined by
default.paginate.prev property in I18n messages.properties)
• next (optional) - The text to display for the next link (defaults to "Next" as defined by
default.paginate.next property in I18n messages.properties)
• breadcrumb (optional) - Whether to display a breadcrumb (defaults to "true") -->
Deprecated: Use maxsteps="0" instead
• max (optional) - The number of records displayed per page (defaults to 10). Used ONLY if
params.max is empty
• maxsteps [Since 0.5] (optional) - The number of steps displayed for pagination (defaults to 10).
Used ONLY if params.maxsteps is empty
• offset (optional) - Used ONLY if params.offset is empty

Examples

Example domain class:

class Book {
String title
String author
}

Example controller:

class BookController {
def list = {
[books: Book.list(params)]
}
}

Document generated by Confluence on May 01, 2007 11:37 Page 92


Paginate code:

<g:paginate controller="book" action="list" total="${Book.count()}" />

or

<g:paginate next="Forward" prev="Back"


maxsteps="0" controller="book"
action="list" total="${Book.count()}" />

Document generated by Confluence on May 01, 2007 11:37 Page 93


GSP Tag - set

This page last changed on Apr 20, 2007 by a.shneyderman.

Tag - set

Description

Set the value of a variable accessible with the GSP page.

Parameters

• var - The name of the variable


• value - The initial value to be assgined

Examples

<g:set var="tomorrow" value="${new Date(today.getTime() + 24L * 60 * 60 * 1000)}" />

<g:def var="counter" value="${1}" />


<g:each in="${list}">
${counter}.&nbsp; ${it} -> ${counter % 2 == 0 ? 'even' : 'odd'}
<g:set var="counter" value="${counter + 1}" /><br>
</g:each>

Document generated by Confluence on May 01, 2007 11:37 Page 94


GSP Tag - sortableColumn

This page last changed on Apr 01, 2007 by marceloverdijk.

Tag - sortableColumn (Since 0.5)

Description

Renders a sortable column to support sorting in tables.

Parameters

• property - name of the property relating to the field


• defaultOrder (optional) - default order for the property; choose between asc (default if not
provided) and desc
• title (optional*) - title caption for the column
• titleKey (optional*) - title key to use for the column, resolved against the message source
• params (optional) - a map containing request parameters

Attribute title or titleKey is required. When both attributes are specified then titleKey takes precedence,
resulting in the title caption to be resolved against the message source. In case when the message could
not be resolved, the title will be used as title caption.

Examples

<g:sortableColumn property="title" title="Title" />


<g:sortableColumn property="title" title="Title" style="width: 200px" />
<g:sortableColumn property="title" titleKey="book.title" />
<g:sortableColumn property="releaseDate" defaultOrder="desc" title="Release Date" />
<g:sortableColumn property="releaseDate" defaultOrder="desc" title="Release Date"
titleKey="book.releaseDate" />

Document generated by Confluence on May 01, 2007 11:37 Page 95


GSP Tag - while

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - while

Description

Executes a condition in a loop until the condition returns false

Parameters

• test - The conditional expression

Examples

<g:while test="${i < 5}">


<%i++%>
<p>Current i = ${i}</p>
</g:while>

Document generated by Confluence on May 01, 2007 11:37 Page 96


Tag - actionSubmit

This page last changed on Mar 05, 2007 by marceloverdijk.

Tag - actionSubmit

Description

Creates a submit button with the indicated value. Javascript event handlers can be added using the
same parameter names as in HTML.

Parameters

• value (required) - The title of the button and name of action when not explicitly defined.
• action [since 0.5] (optional) - The name of the action to be executed.

Examples

<g:actionSubmit value="Update" />


<g:actionSubmit value="Some update label" action="Update" /> // Update will be automatically
translated to update
<g:actionSubmit value="Delete" />
<g:actionSubmit value="DeleteAll" onclick="return confirm('Are you sure???')" />

Document generated by Confluence on May 01, 2007 11:37 Page 97


Tag - actionSubmitImage

This page last changed on Mar 09, 2007 by wangjammer5.

Tag - actionSubmitImage

Description

Creates a submit button using the input type="image" with the indicated value. Javascript event
handlers can be added using the same parameter names as in HTML.

Parameters

• value (required) - The title of the button and name of action when not explicitly defined.
• action [since 0.5] (optional) - The name of the action to be executed.
• src - The source of the image to use.

MS Internet Explorer Bug

Note that you cannot use multiple actionSubmitImage tags on the same form and have it work in
MS IE without adding some custom JavaScript. MS IE6 and IE7 do not send the value attribute to
the server when submitting, so the "action" attribute on this tag is not useful to you unless
targetting non-IE users or adding custom Javascript.

Info about this bug

Examples

<g:actionSubmitImage value="Update" src="/images/update.gif"/>


<g:actionSubmitImage value="Some update label" action="Update" src="/images/update.gif"/>

Document generated by Confluence on May 01, 2007 11:37 Page 98


Tag - checkBox

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - checkBox

Description

Creates a checkbox form field. All the usual HTML elements apply beyond the below:

Parameters

• name (optional) - The name of the checkbox


• value (optional) - The value of the checkbox, if evaluates to true sets to checkbox to checked

Examples

// a checked checkbox
<g:checkBox name="myCheckbox" value="${true}" />

Document generated by Confluence on May 01, 2007 11:37 Page 99


Tag - createLink

This page last changed on Jun 25, 2006 by glaforge.

Tag - createLink

Description

Creates a link that can be used where necessary (for example in an href, javascript, ajax call etc.)

Parameters

• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• url (optional) - A map containing the action,controller,id etc.

Examples

Example controller for an application called "shop":

class BookController {
def defaultAction="list"
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }
}

Example usages for above controller:

<g:createLink action="show" id="1" /> == /shop/book/show/1


<g:createLink controller="book" /> == /shop/book
<g:createLink controller="book" action="list" /> == /shop/book/list
<g:createLink url="[action:'list',controller:'book']" /> == /shop/book/list

Example as a method call in GSP only:

<a href="${createLink(action:'list')}">my link</a>

Results in:

<a href="/shop/book/list">my link</a>

Document generated by Confluence on May 01, 2007 11:37 Page 100


Tag - createLinkTo

This page last changed on May 25, 2006 by jania902@gmail.com.

Tag - createLinkTo

Description

Creates a link that can be used where necessary (for example in an href, javascript, ajax call etc.)

Parameters

• dir (optional) - the name of the directory within the grails app to link to
• file (optional) - the name of the file within the grails app to link to

Examples

Example usages for the "shop" app:

<g:createLinkTo dir="css" file="main.css" /> == /shop/css/main.css

Examle as a method call in GSP only:

<link type="text/css" href="${createLinkTo(dir:'css',file:'main.css')}" />

Results in:

<link type="text/css" href="/shop/css/main.css" />

Document generated by Confluence on May 01, 2007 11:37 Page 101


Tag - currencySelect

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - currencySelect

Description

Helper tag for creating HTML selects for selecting from a list of currency symbols (eg. 'EUR', 'USD' etc.).

Parameters

• from (optional) - The currency symbols to select from, defaults to the major ones if not specified
• value (optional) - The currency value as the currency code. Defaults to the currency for the current
Locale if not specified

Examples

// create a currency select


<g:currencySelect name="myCurrency" value="${currency}" />

Document generated by Confluence on May 01, 2007 11:37 Page 102


Tag - datePicker

This page last changed on Feb 02, 2007 by wangjammer5.

Tag - datePicker

Description

Creates a date picker which renders as selects for the day,month,year,hour and second of the day.

Parameters

• name (required) - The name of the date picker field set


• value (optional) - The current value of the date picker; defaults to now if not specified
• precision (optional) - The desired granularity of the date to be rendered
° Valid values are 'year', 'month', 'day', 'hour', or 'minute'
° Defaults to 'minute' if not specified
° Uses default values for the non-rendered date components. Default values...
- month = January
- day = 1st day of the month
- hour = 00
- minute = 00
• noSelection (optional) - A single-entry map detailing the key and value to use for the "no selection
made" choice in the select box. If there is no current selection this will be shown as it is first in the
list, and if submitted with this selected, the key that you provide will be submitted. Typically this will
be blank.
• years (optional) - A list or range of years to display, in the order specified. i.e. specify 2007..1900
for a reverse order list going back to 1900. If this attribute is not specified, a range of years from
the current year - 100 to current year + 100 will be shown.

Examples

Example usages:

<g:datePicker name="myDate" value="${new Date()}"


noSelection="['':'-Choose-']"/>

<g:datePicker name="myDate" value="${new Date()}" precision="day" years="${1930..1970}"/>


<g:datePicker name="myDate" value="${new Date()}" precision="day" years="[1930, 1940, 1950,
1960, 1970]"/>

Document generated by Confluence on May 01, 2007 11:37 Page 103


Tag - eachError

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - eachError

Description

Loops through each error of the specified bean or model. If no arguments are specified it will go through
all model attributes and check for errors.

Parameters

• bean (optional) - The name of the bean to check for errors


• model (optional) - The name of model, an map instance, to check for errors
• field (optional) - The field within the bean or model to check for errors for

Examples

Loop through each error in the "book" bean:

<g:eachError bean="${book}">
<li>${it}</li>
</g:eachError>

Loop through each error in the title field of the "book" bean:

<g:eachError bean="${book}" field="title">


<li>${it}</li>
</g:eachError>

Loop through each error in model:

<g:eachError bean="[book1:book1,book2:book2]" field="title">


<li>${it}</li>
</g:eachError>

Document generated by Confluence on May 01, 2007 11:37 Page 104


Tag - form

This page last changed on Jul 02, 2006 by ae6rt.

Tag - form

Description

Creates a form that submits to a controller, action, and/or id. Beyond what is below all the usual HTML
attributes apply.

Parameters

• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• url (optional) - A map containing the action,controller,id etc.

Examples

Example controller for an application called "shop":

class Book {
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }
}

Example usages for above controller:

<g:form name="myForm" action="myaction" id="1">...</g:form>


<g:form name="myForm" url="[action:'list',controller:'book']">...</g:form>

Document generated by Confluence on May 01, 2007 11:37 Page 105


Tag - formRemote

This page last changed on Jun 25, 2006 by glaforge.

Tag - formRemote

Description

Creates a form tag that uses a remote uri to execute an ajax call serializing the form elements falling
back to a normal form submit if javascript is not supported.

Parameters

• url - The url to submit to, either a map contraining keys for the action,controller and id or string
value
• action (optional) - The action to execute as a fallback, defaults to the url if non specified
• update (optional) - Either a map containing the elements to update for 'success' or 'failure' states,
or a string with the element to update in which cause failure events would be ignored
• before (optional) - The javascript function to call before the remote function call
• after (optional) - The javascript function to call after the remote function call
• asynchronous (optional) - Whether to do the call asynchronously or not (defaults to true)
• method (optional) - The method to use the execute the call (defaults to "post")

Events

• onSuccess (optional) - The javascript function to call if successful


• onFailure (optional) - The javascript function to call if the call failed
• on_ERROR_CODE (optional) - The javascript function to call to handle specified error codes (eg
on404="alert('not found!')")
• onUninitialized (optional) - The javascript function to call the a ajax engine failed to initialise
• onLoading (optional) - The javascript function to call when the remote function is loading the
response
• onLoaded (optional) - The javascript function to call when the remote function is completed loading
the response
• onComplete (optional) - The javascript function to call when the remote function is complete,
including any updates

Examples

Example controller for an application called "shop":

class Book {
def defaultAction="list"
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }
}

Document generated by Confluence on May 01, 2007 11:37 Page 106


Example usages for above controller:

<g:formRemote name="myForm" on404="alert('not found!')" update="updateMe" action="show">


Login: <input name="login" type="text"></input>
</g:formRemote>
<div id="updateMe">this div is updated by the form</div>

Document generated by Confluence on May 01, 2007 11:37 Page 107


Tag - hasErrors

This page last changed on Aug 08, 2006 by tomstrummer.

Tag - hasErrors

Description

Checks whether a bean, request scope, or model reference has any errors and if it does invokes the body
of the tag. Typically used in conjunction with either <g:eachError> or <g:renderErrors>

Parameters

• bean (optional) - The bean to check for errors


• model (optional) - The name of the model reference to check for errors
• field (optional) - Check if a field of the bean or model reference has errors

Examples

Checks whether there are any errors for any bean throughout the request scope:

<g:hasErrors>
<g:eachError><p>${it.defaultMessage}</p></g:eachError>
</g:hasErrors>

Checks whether there are any errors for the specified bean

<g:hasErrors bean="${book}">
<g:eachError><p>${it.defaultMessage}</p></g:eachError>
</g:hasErrors>

Checks whether there are any errors for the field "title" of the specified "book" bean:

<g:hasErrors bean="${book}" field="title">


<div class="errors">
<g:renderErrors bean="${book}" field="title" as="list" />
</div>
</g:hasErrors>

As a method call in GSP only. In this case we check for a field error on a particular field and set a CSS
class on the surround div thus allowing us to highlight the error with a red border for example:

<div class="prop ${hasErrors(bean:user,field:'login', 'errors')}">


<label for="login"><input type="text" name="login" />
</div>

Document generated by Confluence on May 01, 2007 11:37 Page 108


Tag - hiddenField

This page last changed on Aug 17, 2006 by graeme.rocher@gmail.com.

Tag - hiddenField

Description

Creates a input of type 'hidden' (a hidden field). All the usual HTML elements apply beyond the below:

Parameters

• name (required) - The name of the text field


• value (optional) - The value of the text field

Examples

<g:hiddenField name="myField" value="myValue" />

Document generated by Confluence on May 01, 2007 11:37 Page 109


Tag - link

This page last changed on Apr 21, 2007 by takamori.

Tag - link

Description

Creates a html anchor tag with the href set to based on the parameters specified

Parameters

• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• params (optional) - A map containing request parameters
• url (optional) - A map containing the action,controller,id etc.

Examples

Example controller for an application called "shop":

class BookController {
def defaultAction="list"
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }
}

Example usages for above controller:

<g:link action="show" id="1">Book 1</g:link><g:link action="show"


id="${currentBook.id}">${currentBook.name}</g:link>
<g:link controller="book">Book Home</g:link>
<g:link controller="book" action="list">Book List</g:link>
<g:link url="[action:'list',controller:'book']">Book List</g:link>
<g:link action="list" params="[sort:'title',order:'asc',author:currentBook.author]">Book
List</g:link>

Note that id takes a ${foo} parameter but ${foo} expansions will NOT work in the params
attribute.

Example as a method call in GSP only:

<%= link(action:'list',controller:'book') { 'Book List' }%>

Results in:

<a href="/shop/book/list">Book List</a>

Document generated by Confluence on May 01, 2007 11:37 Page 110


Don't use "it" variables in the body!

An "it" variable in the body of a nested tag (i.e. if you have a g:link nested in a g:each) generally
runs into compilation problems. This can be easily resolved by naming your parameter in the
g:each by passing a var parameter.

Document generated by Confluence on May 01, 2007 11:37 Page 111


Tag - localeSelect

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - localeSelect

Description

Creates a select to select from a list of available locales

Parameters

• value (optional) - The set locale, defaults to the current request locale if not specified

Examples

// create a locale select


<g:localeSelect name="myLocale" value="${locale}" />

Document generated by Confluence on May 01, 2007 11:37 Page 112


Tag - message

This page last changed on Jan 15, 2007 by marceloverdijk.

Tag - message

Description

Resolves a message from the given code or error. Normally used in conjunction with "eachError". One of
either the "error" attribute or the "code" attribute is required. Messages are resolved from the
"grails-app/i18n/messages.properties" bundle.

Parameters

• error (optional) - The error to resolve the message for. Used for built-in Grails messages.
• code (optional) - The code to resolve the message for. Used for custom application messages.
• default (optional) - The default message to output if the error or code cannot be found in
messages.properties.
• args (optional) - A list of argument values to apply to the message, when code is used.

Examples

Loop through each error and output the message:

<g:eachError bean="${book}">
<li><g:message error="${it}" /></li>
</g:eachError>

Note that this is typically used for built-in Grails messages, rather than user application messages. For
user application messages, use the code parameter, as illustrated below.

Output a message for a specific known code:

<g:message code="my.message.code" />

For a more complex example, to output your own message with parameters and a default message, you
might use the following code from your controller:

flash.message = "book.delete.message"
flash.args = [ "stupidbook" ]
flash.defaultMsg = "book deleted"

In the above, don't try to rename flash.defaultMsg as "flash.default". You'll get parser errors because
default is a reserved word (Note that on the other hand, you can specify it as flash['default'] because
then you are using it as a string key). You would then specify the following in messages.properties:

Document generated by Confluence on May 01, 2007 11:37 Page 113


book.delete.message="Book {0} deleted."

and specify the following from your view:

<g:message code="${flash.message}" args="${flash.args}" default="${flash.defaultMsg}"/>

which would result in the output "Book stupidbook deleted." If you had misnamed the message or not
specified it in messages.properties, your default message of "book deleted" would be output.

Document generated by Confluence on May 01, 2007 11:37 Page 114


Tag - remoteField

This page last changed on Aug 17, 2006 by graeme.rocher@gmail.com.

Tag - remoteField

Description

Creates a text field that sends its value to a remote link when it changes. By default the parameter name
sent is called 'value', this can be changed by specifying a 'paramName' attribute.

Parameters

• name (required) - the name of the field


• value (optional) - The initial value of the field
• paramName (optional) - The name of the parameter send to the server
• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• update (optional) - Either a map containing the elements to update for 'success' or 'failure' states,
or a string with the element to update in which cause failure events would be ignored
• before (optional) - The javascript function to call before the remote function call
• after (optional) - The javascript function to call after the remote function call
• asynchronous (optional) - Whether to do the call asynchronously or not (defaults to true)
• method (optional) - The method to use the execute the call (defaults to "post")

Events

• onSuccess (optional) - The javascript function to call if successful


• onFailure (optional) - The javascript function to call if the call failed
• on_ERROR_CODE (optional) - The javascript function to call to handle specified error codes (eg
on404="alert('not found!')")
• onUninitialized (optional) - The javascript function to call the a ajax engine failed to initialise
• onLoading (optional) - The javascript function to call when the remote function is loading the
response
• onLoaded (optional) - The javascript function to call when the remote function is completed loading
the response
• onComplete (optional) - The javascript function to call when the remote function is complete,
including any updates

Examples

Example controller for an application called "shop":

Document generated by Confluence on May 01, 2007 11:37 Page 115


class BookController {
def changeTitle = {
def b = Book.get(params.id)
b.title = params.value
b.save()
}
}

Example usages for above controller:

<g:remoteField action="changeTitle" update="titleDiv" name="title" value="${book?.title}"/>

<div id="titleDiv">I'm updated with the new title!</div>

Document generated by Confluence on May 01, 2007 11:37 Page 116


Tag - remoteFunction

This page last changed on Dec 05, 2006 by davec.

Tag - remoteFunction

Description

Creates a remote javascript function that can be assigned to a DOM event to call the remote method

Parameters

• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• update (optional) - Either a map containing the elements to update for 'success' or 'failure' states,
or a string with the element to update in which cause failure events would be ignored
• before (optional) - The javascript function to call before the remote function call
• after (optional) - The javascript function to call after the remote function call
• asynchronous (optional) - Whether to do the call asynchronously or not (defaults to true)
• method (optional) - The method to use the execute the call (defaults to "post")
• params (optional) - Parameters to send to the controller

Events

• onSuccess (optional) - The javascript function to call if successful


• onFailure (optional) - The javascript function to call if the call failed
• on_ERROR_CODE (optional) - The javascript function to call to handle specified error codes (eg
on404="alert('not found!')")
• onUninitialized (optional) - The javascript function to call the a ajax engine failed to initialise
• onLoading (optional) - The javascript function to call when the remote function is loading the
response
• onLoaded (optional) - The javascript function to call when the remote function is completed loading
the response
• onComplete (optional) - The javascript function to call when the remote function is complete,
including any updates

Examples

Example controller for an application called "shop":

class Book {
def defaultAction="list"
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }

Document generated by Confluence on May 01, 2007 11:37 Page 117


def bookbyname = { [ book : Book.findByName( params.bookName ) ] } }

Example usages for above controller:

$('mydiv').onclick = <g:remoteFunction action="show" id="1" />

Example as a method call in GSP only:

<select onchange="${remoteFunction(action:'bookbyname',update:[success:'great',
failure:'ohno'], params:'\'bookName=\' + this.value' )}">
<option>first</option>
<option>second</option>
</select>

Notes:

• Use single quotes inside the GSP "${}"

Document generated by Confluence on May 01, 2007 11:37 Page 118


Tag - remoteLink

This page last changed on Aug 18, 2006 by takamori.

Tag - remoteLink

Description

Creates a link that calls a remote function when clicked

Parameters

• action (optional) - the name of the action to use in the link, if not specified the default action will
be linked
• controller (optional) - the name of the controller to use in the link, if not specified the current
controller will be linked
• id (optional) - The id to use in the link
• params(optional) - Request parameter map
• update (optional) - Either a map containing the elements to update for 'success' or 'failure' states,
or a string with the element to update in which cause failure events would be ignored
• before (optional) - The javascript function to call before the remote function call
• after (optional) - The javascript function to call after the remote function call
• asynchronous (optional) - Whether to do the call asynchronously or not (defaults to true)
• method (optional) - The method to use the execute the call (defaults to "post")

Events

• onSuccess (optional) - The javascript function to call if successful


• onFailure (optional) - The javascript function to call if the call failed
• on_ERROR_CODE (optional) - The javascript function to call to handle specified error codes (eg
on404="alert('not found!')")
• onUninitialized (optional) - The javascript function to call the a ajax engine failed to initialise
• onLoading (optional) - The javascript function to call when the remote function is loading the
response
• onLoaded (optional) - The javascript function to call when the remote function is completed loading
the response
• onComplete (optional) - The javascript function to call when the remote function is complete,
including any updates

Examples

Example controller for an application called "shop":

class Book {
def defaultAction="list"
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }

Document generated by Confluence on May 01, 2007 11:37 Page 119


}

Example usages for above controller (note that the params example is for use with the Dojo AJAX
implementation):

<g:remoteLink action="show" id="1">Test 1</g:remoteLink>


<g:remoteLink action="show" id="1" update="[update:'success',failure:'error']"
on404="alert('not found');">Test 2</g:remoteLink>
<g:remoteLink action="show" id="1" update="success" onLoading="showSpinner();">Test
3</g:remoteLink>
<g:remoteLink action="show" id="1" update="success" params="[sortBy:'name',offset:offset]">Test
4</g:remoteLink>

Example of params with the Prototype AJAX implementation:

<g:remoteLink action="show" id="1" update="success"


params="'sortBy=name&offset=${offset}'">Test 4</g:remoteLink>

As a method call in GSP:

my link = <%=remoteLink(action:'show',id:1,update:'success',onFailure:'showError();') {"this is


the body"}%>

Document generated by Confluence on May 01, 2007 11:37 Page 120


Tag - render

This page last changed on Aug 29, 2006 by jason@jasonrudolph.com.

Tag - render

Description

Applys an inbuilt or user defined Groovy template against a model so that templates can be re-used for
lists or instance or a single instance

Parameters

• template (required) - The name of the template to apply


• bean (optional) - The bean to apply the template against
• model (optional) - The model to apply the template against as a java.util.Map
• collection (optional) - A collection of model objects to apply the template to

Examples

Example domain class:

class Book {
String title
String author
}

Example template:

<p><%= it.title %></p>


<p><%= it.author %></p>

This template can now be re-used whether you have a list of books or a single book. For a list the
template will be repeated for each instance:

<g:render template="displaybook" collection="${books}" />

or

<g:render template="displaybook" bean="${book}" />

or you could create a template that handles a certain type of model. For example the template below:

Document generated by Confluence on May 01, 2007 11:37 Page 121


<p><%= book.title %></p>
<p><%= author.fullName %></p>

Could be used with the model as below. The disadvantage of this technique however is that the template
is less re-usable

<g:render template="displaybook" model="['book':book,'author':author]" />

Note that if the value of the template attribute starts with a '/' it will be resolved relative to the views
folder. This is useful for sharing templates between views. Without the leading '/' it will be first be
resolved relative to the current controller's view folder then, failing that, the top level views folder. In
either case the template file must be named with a leading underscore ('_') but referenced in the
template attribute without that underscore or the '.gsp' suffix.

Document generated by Confluence on May 01, 2007 11:37 Page 122


Tag - renderBean

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - renderBean

At the idea stage, not yet implemented!

Description

The displayBean tag displays a bean in the scope with different possible views:

• a default display view of an instance of a domain class (with a simple table with labels right-aligned,
and associated values in the left column)
• a form view with a table like above, pre-filled if the bean is in the current scope, or void for a
creation, with the right widgets for each type of bean property (checkbox, date picker, text area,
etc...)
• a third optional but interesting view could be a mix of the two above with something like
edit-in-place table which would replace the values with input widgets when clicking on the value
label

Parameters

• view - the type of the view, being one of "table", "form", "edit-in-place"
• form - the name of the form containing the values of the properties of the bean (not needed in the
"table" view)
• bean - the name of the bean in the scope to display
• domain-class - the class name of the bean to display

Example

<g:renderBean view="table" form="formName" bean="beanName" domain-class="MyBean" />

Document generated by Confluence on May 01, 2007 11:37 Page 123


Tag - renderErrors

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - renderErrors

Description

Allows rendering of errors in different formats (at the moment only an HTML list is implemented but
others (including JSON) to come soon)

Parameters

• as (optional) - What to render it as current options are "list". Defaults to "list" if not specified.
• bean (optional) - The name of the bean to check for errors
• model (optional) - The name of model, an map instance, to check for errors
• field (optional) - The field within the bean or model to check for errors for

Examples

Render a list for the "book" bean:

<g:renderErrors bean="${book}" as="list" />

Render a list for the title field of the "book" bean:

<g:renderErrors bean="${book}" as="list" field="title"/>

Document generated by Confluence on May 01, 2007 11:37 Page 124


Tag - richTextEditor

This page last changed on Sep 19, 2006 by hansamann.

Tag - richTextEditor

Description

A Rich Text Editor component that by default uses fckeditor with a basepath of /fckeditor.

Be sure to include the fckeditor.js Script in the head of your page:

<!-- FCKEditor JavaScript -->


<script type="text/javascript" src="/<WEBROOT>/js/FCKeditor/fckeditor.js"></script>

Parameters

• name (required) - the name of the form field to bind to


• basepath (optional) - the basepath of the unzipped FCKeditor, /FCKeditor by default. You might
want to unpack the zip to web-app/js/FCKeditor to keep your web app root organized
• toolbar (optional) - the toolbarset to use. Preconfigured in FCKEditor is "Default" (all features) and
"Basic" (basic features such as bold, italic, lists, URLs). You can create your own ToolbarSet by
adding to the file fckconfig.js in the FCKeditor folder
• height (optional) - The heigth in pixels of the WYSIWIG editor to create
• value (optional) - Initial value of the editor.

Examples

Example for an editor with a "Basic" ToolbarSet:

<g:richTextEditor name="content" value="${textElement?.content}" basepath="js/FCKeditor/"


toolbar="Basic" height="150" />

Document generated by Confluence on May 01, 2007 11:37 Page 125


Further Information

• FCKEditor Homepage - http://www.fckeditor.net/


• File grails-app/taglib/UITagLib for the implementation

Document generated by Confluence on May 01, 2007 11:37 Page 126


Tag - select

This page last changed on Mar 15, 2007 by marceloverdijk.

Tag - select

Description

Helper tag for creating HTML selects.

Parameters

• from (required) - The list or range to select from


• value (optional) - The current selected value that evaluates equals() to true for one of the elements
in the from list.
• optionKey (optional) - By default the value attribute of each "option" element will be the result of a
"toString()" call on each element in the "from" attribute list. Setting this allows the value of the
attribute to be a bean property of each element in the list
• optionValue (optional) - By default the value "option" element will be the result of a "toString()"
call on each element in the "from" attribute list. Setting this allows the value to be a bean property
of each element in the list.
• keys (optional) - A list of values to be used for the value attribute of each "option" element.
• noSelection (optional) - A single-entry map detailing the key and value to use for the "no selection
made" choice in the select box. If there is no current selection this will be shown as it is first in the
list, and if submitted with this selected, the key that you provide will be submitted. Typically this will
be blank.
• valueMessagePrefix [Since 0.5] (Optional) - By default the value "option" element will be the
result of a "toString()" call on each element in the "from" attribute list. Setting this allows the value
to be resolved from the I18n messages. The valueMessagePrefix will be suffixed with the value
attribute of the option to resolve the message. If the message could not be resolved, the value is
presented.

Examples

// create a select from a range


<g:select name="user.age" from="${18..65}" value="${age}"
noSelection="['':'-Choose your age-']"/>

// create select from a list of companies


// note the 'optionKey' is set to the id of each company element
<g:select name="user.company.id"
from="${Company.list()}"
value="${user?.company.id}"
optionKey="id" />

// create select with internationalized labels (this is useful for small static lists and the
inList constraint)
// expected properties in messages.properties:
// book.category.M=Mystery
// book.category.T=Thriller
// book.category.F=Fantasy
<g:select name="book.category" from="${['M', 'T', 'F']}" valueMessagePrefix="book.category" />

Document generated by Confluence on May 01, 2007 11:37 Page 127


Example as a method call in GSP only:

${select(from:aList,value:aValue)}

Document generated by Confluence on May 01, 2007 11:37 Page 128


Tag - submitToRemote

This page last changed on Jun 25, 2006 by glaforge.

Tag - submitToRemote

Description

Creates a button that submits the surrounding form as a remote ajax call serializing the fields into
parameters.

Parameters

• url - The url to submit to, either a map contraining keys for the action,controller and id or string
value
• action (optional) - The action to execute as a fallback, defaults to the url if non specified
• update (optional) - Either a map containing the elements to update for 'success' or 'failure' states,
or a string with the element to update in which cause failure events would be ignored
• before (optional) - The javascript function to call before the remote function call
• after (optional) - The javascript function to call after the remote function call
• asynchronous (optional) - Whether to do the call asynchronously or not (defaults to true)
• method (optional) - The method to use the execute the call (defaults to "post")

Events

• onSuccess (optional) - The javascript function to call if successful


• onFailure (optional) - The javascript function to call if the call failed
• on_ERROR_CODE (optional) - The javascript function to call to handle specified error codes (eg
on404="alert('not found!')")
• onUninitialized (optional) - The javascript function to call the a ajax engine failed to initialise
• onLoading (optional) - The javascript function to call when the remote function is loading the
response
• onLoaded (optional) - The javascript function to call when the remote function is completed loading
the response
• onComplete (optional) - The javascript function to call when the remote function is complete,
including any updates

Examples

Example controller for an application called "shop":

class Book {
def list = { [ books: Book.list( params ) ] }
def show = { [ book : Book.get( params['id'] ) ] }
}

Example usages for above controller:

Document generated by Confluence on May 01, 2007 11:37 Page 129


<g:form action="show">
Login: <input name="login" type="text"></input>
<g:submitToRemote update="updateMe" />
</g:form>
<div id="updateMe">this div is updated by the form</div>

Document generated by Confluence on May 01, 2007 11:37 Page 130


Tag - textArea

This page last changed on Nov 29, 2006 by wangjammer5.

Tag - textArea

Description

Creates a HTML text area element. An implicit "id" attribute is given the same value as name unless you
explicitly specify one. All the usual HTML elements apply beyond the below:

Parameters

• name (required) - The name of the text area


• value (optional) - The value of the text area

Examples

<g:textArea name="myField" value="myValue" rows="5" cols="40"/>

Document generated by Confluence on May 01, 2007 11:37 Page 131


Tag - textField

This page last changed on Nov 29, 2006 by wangjammer5.

Tag - textField

Description

Creates a input of type 'text' (a text field). An implicit "id" attribute is given the same value as name
unless you explicitly specify one. All the usual HTML elements apply beyond the below:

Parameters

• name (required) - The name of the text field


• value (optional) - The value of the text field

Examples

<g:textField name="myField" value="myValue" />

Document generated by Confluence on May 01, 2007 11:37 Page 132


Tag - timeZoneSelect

This page last changed on Feb 17, 2006 by graeme.rocher@gmail.com.

Tag - timeZoneSelect

Description

Helper tag for creating HTML selects for selecting from a list of time zones

Parameters

• value (optional) - An instance of java.util.TimeZone. Defaults to the time zone for the current
Locale if not specified

Examples

// create a currency select


<g:timeZoneSelect name="myTimeZone" value="${tz}" />

Document generated by Confluence on May 01, 2007 11:37 Page 133


Tag - validate

This page last changed on Jun 26, 2006 by jania902@gmail.com.

Tag - validate

At the idea stage, not yet implemented!

Description

Allows client-side validation of domain class constraints against a form.

Parameters

• form - The name of the form


• against - The class name of the domain class

Examples

Example domain class:

class User {
String login
String pwd

def constraints = {
login(length:5..15,unique:true)
pwd(length:5..15)
}
}

The below used submits to a "login" action. The field names match those within the class defined about:

<form name="userForm" action="login">


<input type="text" name="login" />
<input type="password" name="pwd" />
</form>

This allows us to apply the validate tag against the constraints set in the domain class and produce the
necessary
javascript to perform client side validation. Tag usage:

<g:validate form="userForm" against="User" />

Document generated by Confluence on May 01, 2007 11:37 Page 134


JSP Tag Reference

This page last changed on Mar 09, 2006 by graeme.rocher@gmail.com.

JSP Tag Reference

Linking Tags

• link
• createLink

Ajax Tags

• remoteFunction
• remoteLink
• formRemote
• submitToRemote

Form Tags

• form
• checkBox
• datePicker
• select
• currencySelect
• localeSelect
• timeZoneSelect

UI Tags

(Coming Soon)

Rendering Tags

• render
• renderErrors

Validation Tags

• eachError
• hasErrors
• message

Document generated by Confluence on May 01, 2007 11:37 Page 135


Validation Reference

This page last changed on Apr 25, 2007 by brownj.

Domain Class Validation

• Example
• Reference
° blank
° creditCard
° email
° inList
° length
° matches
° max
° maxLength
° maxSize
° min
° minLength
° minSize
° notEqual
° nullable
° range
° scale
° size
° unique
° url
° validator

Example

class User {
Long id
Long version

String login
String password
static constraints = {
login(length:5..15,blank:false,unique:true)
password(length:5..15,blank:false)
}
}

In the reference that follows, className.propertyName.validationConstraint refers to the error message


codes defined in grails-app/i18n/message.properties.
For example, referring to the above class, the error message might be defined as:
user.login.blank=Please enter a login

Since 0.5. You could use common pattern "className.propertyName.constraintName.error"


for all constraints, example: "user.login.blank.error=Please enter a login".

Validation Constraint Reference

Document generated by Confluence on May 01, 2007 11:37 Page 136


blank

Usage: set to false if a string value cannot be blank


Example:

login(blank:false)

Error message code: className.propertyName.blank

creditCard

Usage: set to truee if a string should be a credit card number


Example:

cardNumber(creditCard:true)

Error message code: className.propertyName.?????

email

Usage: set to true if a string value is an email address


Example:

contactEmail(email:true)

Error message code: className.propertyName.email.invalid

inList

Usage: constrains a value so that it must be contained within the given list
Example:

name(inList:["Joe", "Fred", "Bob"] )

Error message code: className.propertyName.not.inList

length

Deprecated in 0.4. Removed in 0.5. Use size instead.

Usage: Uses a Groovy range to restrict the length of a string or array


Example:

login(length:5..15)

Document generated by Confluence on May 01, 2007 11:37 Page 137


Error message code: className.propertyName.length.toolong, className.propertyName.length.tooshort
This constraint influences schema generation.

matches

Usage: Applies a regular expression against a string value


Example:

login(matches:"[a-zA-Z]")

Error message code: className.propertyName.matches.invalid

max

Usage: sets the maximum value of a class that implements java.lang.Comparable. The same type needs
to be used as the property itself.
Example:

age(max:new Date())
price(max:999F)

Error message code: className.propertyName.max.exceeded


This constraint influences schema generation.

maxLength

Deprecated in 0.4. Removed in 0.5. Use maxSize instead.

Usage: sets the maximum length of a string or array property


Example:

login(maxLength:5)

Error message code: className.propertyName.maxLength.exceeded


This constraint influences schema generation.

maxSize

Usage: sets the maximum size of a collection or number property

Deprecated in 0.5 for number properties. Use max instead

Example:

children(maxSize:25)

Error message code: className.propertyName.maxSize.exceeded


This constraint influences schema generation.

Document generated by Confluence on May 01, 2007 11:37 Page 138


min

Usage: sets the minimum value of a class that implements java.lang.Comparable. The same type needs
to be used as the property itself.
Example:

age(min:new Date())
price(mix:0F)

Error message code: className.propertyName.min.notmet


This constraint influences schema generation.

minLength

Deprecated in 0.4. Removed in 0.5. Use minSize instead.

Usage: sets the minimum length of a string or array property


Example:

login(minLength:5)

Error message code: className.propertyName.minLength.notmet


This constraint influences schema generation.

minSize

Usage: sets the minimum size of a collection or number property

Deprecated in 0.5 for number properties. Use min instead

Example:

children(minSize:5)

Error message code: className.propertyName.minSize.notmet


This constraint influences schema generation.

notEqual

Usage: validates that a property is not equal to the specified value


Example:

login(notEqual:"Bob")

Error message code: className.propertyName.notEqual

nullable

Document generated by Confluence on May 01, 2007 11:37 Page 139


Usage: set to false if the property value cannot be null
Example:

age(nullable:false)

Error message code: className.propertyName.nullable

range

Usage: Uses a Groovy range to ensure that a property's value occurs within a specified range
Example:

age(range:minAge..maxAge)

Error message code: className.propertyName.range.toosmall or className.propertyName.range.toobig


This constraint influences schema generation.

scale

Since: 0.4
Usage: Set to the desired scale for floating point numbers (i.e., the number of digits to the right of the
decimal point). This constraint is applicable for properties of the following types: java.lang.Float,
java.lang.Double, and java.math.BigDecimal (and its subclasses). When validation is invoked, this
constraint determines if the number includes more nonzero decimal places than the scale permits. If so,
it automatically rounds the number to the maximum number of decimal places allowed by the scale. This
constraint does not generate validation error messages.
Example:

salary(scale:2)

Error message code: N/A


This constraint influences schema generation.

size

Usage: Uses a Groovy range to restrict the size of a collection or number

Deprecated in 0.5 for number properties. Use range instead

Example:

children(size:5..15)

Error message code: className.propertyName.size.toosmall or className.propertyName.size.toobig


This constraint influences schema generation.

unique

Document generated by Confluence on May 01, 2007 11:37 Page 140


Usage: set to true if the property must be unique (this is a persistent call and will query the database)
Example:

login(unique:true)

[Since 0.5] Scope of unique constraint can be specified. "Scope" - is a name of another property of the
same class, or list of such names. Semantic in these cases is: pair of constrained property value and
scope property value must be unique (or combination of constrained property value and all scope
property values must be unique).

Example:

group(unique:'department')

In the above example group name must be unique in one department but there might be groups with
same name in different departments.

Another example:

login(unique:['group','department'])

In this example login must be unique in group and department. There might be same logins in different
groups or different departments.

Error message code: className.propertyName.unique

url

Usage: set to true if a string value is a URL address


Example:

homePage(url:true)

Error message code: className.propertyName.url.invalid

validator

Usage: set to a Closure to use custom validation. A single or no parameter Closure receives the value, a
two-parameter Closure receives the value and object reference

The closure can return:

• null or true to indicate that the value is valid


• false to indicate an invalid value and use the default message code
• a string to indicate the error code to append to the "classname.propertName." string to display an
error
• a list containing a string as above, and then any number of arguments following it, which can be
used as formatted message arguments indexed at 3 onwards. See
grails-app/i18n/message.properties to see how the default error message codes use the arguments.

Document generated by Confluence on May 01, 2007 11:37 Page 141


Examples:

even( validator: {
return (it % 2) == 0
})

password1( validator: {
val, obj ->
obj.properties['password2'] == val
})

magicNumber( validator:
someClosureWithTwoParameters)

// This one assumes you have an error message defined like:


// classname.propertyName.custom.error=My error shows arguments {3} and {4} for value {0}
otherProperty( validator: { return ['custom.error', arg1, arg2] } )

// The following example does not use custom validation.


// A custom message may be defined in messages.properties:
// user.login.blank=Please enter a login
// which will be used instead of default.blank.message
class User {
String login
static constraints = {
login(blank:false)
}
}

// In the following example, custom validation is used:


// user.login.validator.invalid=Please enter a login
class User {
String login
static constraints = {
login(validator: {
return (it.length != 0)
})
}
}

// The following might define the error message as:


// user.login.invalid.bountyhunter=Invalid bounty hunter ({2}) tried to log in. (Class name =
{1}. Property name = {0})
class User {
String login
static constraints = {
login(validator: {
if (!it.startsWith('boba')) return ['invalid.bountyhunter']
})
}
}

Error message code (default): className.propertyName.validator.invalid

Document generated by Confluence on May 01, 2007 11:37 Page 142


Constraints Influencing Schema Generation

This page last changed on Mar 20, 2007 by lataupe.

Where feasible, Grails uses a domain class's constraints to influence the database columns generated for
the corresponding domain class property.

Consider the following example. Suppose we have a domain model with the following property.

String description

By default, in MySQL, Grails would define this columns as...

column name data type

description varchar(255)

But perhaps the business rules for this domain class state that a description can be up to 1000 characters
in length. If that were the case, we'd likely define the column as follows if we were creating the table via
an SQL script.

column name data type

description TEXT

Chances are we'd also want to have some application-based validation to make sure we don't exceed that
1000 character limit before we persist any records. In Grails, we achieve this validation via constraints.
We'd add the following constraint declaration to the domain class.

static constraints = {
description(maxSize:1000)
}

This constraint would provide both the application-based validation we want and it would also cause the
schema to be generated as shown above. Below is a description of the other constraints that influence
schema generation.

Constraints Affecting String Properties

• maxSize
• size

If either constraint is defined, Grails sets the maximum column length based on the constraint value.

In general, it's not advisable to use both constraints on the same domain class property. However, if both
the maxSize constraint and the size constraint are defined, then Grails sets the column length to the
minimum of the maxSize constraint and the upper bound of the size constraint. (Grails uses the minimum
of the two, because any length that exceeds that minimum will result in a validation error.)

Document generated by Confluence on May 01, 2007 11:37 Page 143


Constraints Affecting Numeric Properties

• min
• max
• range

Before 0.5 version minSize, maxSize and size constraint were also considered in schema generation
process for numeric properties

If the max constraint, the min constraint, or the range constraint is defined, Grails attempts to set the
column precision based on the constraint value. (The success of this attempted influence is largely
dependent on how Hibernate interacts with the underlying DBMS.)

In general, it's not advisable to combine the pair min/max and range constraints together on the same
domain class property. However, if both of these constraints is defined, then Grails uses the minimum
precision value from the constraints. (Grails uses the minimum of the two, because any length that
exceeds that minimum precision will result in a validation error.)

• scale

If the scale constraint is defined, then Grails attempts to set the column scale based on the constraint
value. This rule only applies to floating point numbers (i.e., java.lang.Float, java.Lang.Double,
java.lang.BigDecimal, or subclasses of java.lang.BigDecimal). (The success of this attempted influence is
largely dependent on how Hibernate interacts with the underlying DBMS.)

The constraints define the minimum/maximum numeric values, and Grails derives the maximum number
of digits for use in the precision. Keep in mind that specifying only one of min/max constraints will not
affect schema generation (since there could be large negative value of property with max:100, for
example), unless specified constraint value requires more digits than default Hibernate column precision
is (19 at the moment). For example...

someFloatValue(max:1000000, scale:3)

would yield:

someFloatValue DECIMAL(19, 3) // precision is default

but

someFloatValue(max:12345678901234567890, scale:5)

would yield:

someFloatValue DECIMAL(25, 5) // precision = digits in max + scale

and

Document generated by Confluence on May 01, 2007 11:37 Page 144


someFloatValue(max:100, min:-100000)

would yield:

someFloatValue DECIMAL(8, 2) // precision = digits in min + default scale

Document generated by Confluence on May 01, 2007 11:37 Page 145


Success Stories

This page last changed on Apr 17, 2007 by wangjammer5.

Success Stories and Sites Using Grails

Sites using Grails

A list of sites known to be grails-based:

http://aboutgroovy.com/
http://www.copellafruitjuices.co.uk/ UK high-profile fruit juice brand
http://www.tropicana.co.uk/ UK site for leading orange juice brand
http://www.tropicana-go.com/ Children's drink brand
http://tvvoting.com/
http://www.cyathen.com
http://www.groovyblogs.org
http://entry.xmldo.jp/page2007 - Archive site - http://www.jagat.or.jp/page/2007/
http://groovy.canoo.com/errata/erratum
http://groovy.org.es
Chiumento Careers - http://www.chiumentocareers.co.uk/online/user/login

Success stories

Copella, Tropicana and Tropicana Go!

See also Testimonials

Document generated by Confluence on May 01, 2007 11:37 Page 146


User guide

This page last changed on Apr 25, 2007 by graemerocher@yahoo.co.uk.

User Documentation

Starting Up

1. Introduction
2. Installation
3. Quick Start
4. Configuration
5. IDE Integration
6. Auto Reloading
7. Logging
8. Command Line Tools
9. Frequently Asked Questions
10. Sample Applications

Domains

1. Object Relational Mapping (GORM)


2. Validation

Services

1. Services

Controllers

1. Controllers
2. HTTP Method Restrictions
3. Scaffolding
4. URL Mapping
5. Command Objects

Views

1. Views and Layouts


2. GSP Reference (Work in progress)
3. Dynamic Tag Libraries
4. Ajax

Document generated by Confluence on May 01, 2007 11:37 Page 147


5. Encoding Data

Plugins

1. Available Plugins
2. Contribute a Plugin
3. The Plug-in Developers Guide

Testing

1. Unit Testing
2. Functional Testing

Other Interesting Stuff

1. Command Line Scripting


2. Scripting events
3. Job Scheduling (Quartz)
4. Builders
5. Spring Integration
6. Hibernate Integration
7. Advanced Topics
8. Artifact and Scaffolding Templates
9. Checking Projects into SVN
10. Security (Work in progess)

Document generated by Confluence on May 01, 2007 11:37 Page 148


Advanced Topics

This page last changed on Jun 25, 2006 by glaforge.

Advanced Topics

Grails Artifacts

Grails takes the separation of concerns approach splitting a Grails application in three layers or tiers:

• web tier: presentation logic resides here. Artifacts are:


° views
° controllers
° page flows
° models
° command objects
° validators
• business logic tier: business logic controlled by a middle tier that supports transactional
demarcation. Artifacts are:
° domain classes
° services
• persistence tier: operates within the transactional boundries of the business tier and is also
controlled by a middle tier, deals with persistence details. Artifacts are:
° domain class persistence methods
° data sources
° ORM tool sessions and factories.

Grails requires users to provide some of the artifacts in the above list. Configuration of these artifacts is
taken care of by Grails based on a number of conventions per artifact type.

Injection behavior

Whenever injection of beans is supported the default behaviour is injection by type.

CountryService countryService

In this example a bean of type CountryService is required.

To enable injection by name add a "byName" property to the class and set it to true:

boolean byName = true

In the example above this would require a bean named "countryService".

Document generated by Confluence on May 01, 2007 11:37 Page 149


When beans should not be available for injection create an "available" property and set it false. This
property can be used to avoid type conflicts.

boolean available = true

Configurational properties

When property names are reserved for the configuration of specific artifacts in Grails other properties
with the same name but not the same type are ignored.

class SomeService {
boolean transactional = false
String transactional = "false" // this property is ignored for configurational purposes.
}

Document generated by Confluence on May 01, 2007 11:37 Page 150


Ajax

This page last changed on Oct 26, 2006 by yellek.

Ajax Support

Introduction

Ajax stands for Asynchronous Javascript and XML and is the driving force behind the shift to richer web
applications. These types of applications in general are better suited to agile, dynamic frameworks written
in languages like Ruby and Groovy. Grails provides support for building Ajax applications through its Ajax
tab library for a full list of these see the Tag Library Reference.

Rails developers will be familiar with the tag library as there are equivalent helper methods in Rails for
most of Grails' Ajax tags.

Adaptive Ajax Tags

One major difference with Grails' tags is that they are not tied to the Prototype library. For the Grails Ajax
tags to work you need to include a supported Ajax library within the "head" tag of your HTML document.
The tags will then "adapt" to the included library.

Ajax with Prototype:

<g:javascript library="prototype" />

Ajax with Yahoo UI:

<g:javascript library="yahoo" />

Ajax with Dojo:

<g:javascript library="dojo" />

The tags can then be used as described in the following documentation without knowing the details of the
underlying implementation. This allows you to choose which library is best suited for your needs as each
provides its own benefits.

Installing Dojo

If you choose to use dojo because it is quite a large framework it does not come bundled with Grails and
requires installing. Luckily, Grails provides a target to do this for you. Type the following from the root of

Document generated by Confluence on May 01, 2007 11:37 Page 151


a Grails project and dojo will be downloaded and setup automatically:

grails install-dojo

Loading Remote Content

Remote content can be loaded in a number of ways, the most commons way is through the "remoteLink"
tag. This tag allows the creation of HTML anchor tags that perform an asynchronous request and
optionally set the response in an element. The simplest way to create a remote link is as follows:

<g:remoteLink action="delete" id="1">Delete Book</g:remoteLink>

The above link sends an asynchronous request to the "delete" action of the current controller with an id
of "1". This is great, but usually you would want to provide some kind of feedback to the user as to what
has happened:

def delete = {
def b = Book.get( params.id )
b.delete()
render "Book ${b.id} was deleted"
}

<div id="message"></div>
<g:remoteLink action="delete" id="1" update="message">Delete Book</g:remoteLink>

The above example will call the action and set the contents of the "message" div to the response in this
case "Book 1 was deleted". This is done by the "update" attribute on the tag, which can also take a map
to indicate what should be updated on failure:

<div id="message"></div>
<div id="error"></div>
<g:remoteLink action="delete" id="1"
update="[success:'message',failure:'error']">Delete Book</g:remoteLink>

Here the error div will be updated if the request failed.

Handling Events

Specific javascript can be called if certain events occur, all the events start with the "on" prefix and allow
you to give feedback to the user where appropriate, or take other action:

<g:remoteLink action="show" id="1" update="success" onLoading="showProgress();">Show Book


1</g:remoteLink>

The above code will execute the "showProgress()" function which may show a progress bar or whatever is
appropriate. Other events include:

Document generated by Confluence on May 01, 2007 11:37 Page 152


• onSuccess (optional) - The javascript function to call if successful
• onFailure (optional) - The javascript function to call if the call failed
• on_ERROR_CODE (optional) - The javascript function to call to handle specified error codes (eg
on404="alert('not found!')")
• onUninitialized (optional) - The javascript function to call the a ajax engine failed to initialise
• onLoading (optional) - The javascript function to call when the remote function is loading the
response
• onLoaded (optional) - The javascript function to call when the remote function is completed loading
the response
• onComplete (optional) - The javascript function to call when the remote function is complete,
including any updates

Submitting a Form remotely

An HTML form can also be submitted asynchronously in one of two ways. Firstly using the "formRemote"
tag which expects similar attributes to those for the "remoteLink" tag:

<g:formRemote url="[controller:'book',action:'delete']"
update="[success:'message',failure:'error']">
<input type="hidden" name="id" value="1" />
<input type="submit" value="Delete Book!" />
</g:formRemote >

Or alternatively you can use the "submitToRemote" button this allows some buttons to submit remotely
and some not depending on the action:

<form action="delete">
<input type="hidden" name="id" value="1" />
<g:submitToRemote action="delete" update="[success:'message',failure:'error']" />
</form>

Ajax and the Render Method

Grails' render method is the perfect companion for creating Ajax responses in a number of ways. As an
example lets take a look at an example that retrieves the current date and time:

...
// controller action
def time = {
render "${new Date()}"
}
...
<g:remoteLink action="time" update="time">Get Time</g:remoteLink>
<div id="time">Time to be displayed here</div>

Here the render method is used to update the "time" div with the current time. However, the render
method can also be used to render markup:

...
// controller action
def time = {
render(contentType:'text/xml') {

Document generated by Confluence on May 01, 2007 11:37 Page 153


time(new Date())
}
}
...
// resulting response
<time>(the current time)</time>

But it gets even better, you can also render JSON responses using the same builder syntax:

...
// controller action
def time = {
render(builder:'json') {
time(new Date())
}
}
...
// resulting JSON response
{ time: "..." }

And if you want to leverage the OpenRico framework you can create OpenRico responses:

...
// controller action
def time = {
render(builder:'rico') {
element(id:'time') {
new Date()
}
}
}
...
// resulting Rico response
<ajax-response>
<response type="element" id="time">
... // current time here
</response>
</ajax-response>

Document generated by Confluence on May 01, 2007 11:37 Page 154


Artifact and Scaffolding Templates

This page last changed on Jan 23, 2007 by marceloverdijk.

Artifact and Scaffolding Templates (since 0.4)

When creating artifacts or using scaffolding, Grails uses templates to create the domain classes,
controllers, views etc. The default templates are part of the Grails distribution for out of the box
behaviour, but can be customized for project specific needs.

Scenario

Imagine you are using Action Interceptors for checking if an user is authenticated. In this case, (almost)
all controllers in your application need a before interceptor to do the authentication check. Easiest way to
do this is to create a SecuredBaseController containing the authentication interceptor

class SecuredBaseController {

def beforeInterceptor = [action:this.&auth]

def auth() {
if(!session.user) {
redirect(controller:'authentication',action:'login')
return false
}
}
}

You then can extend this SecuredBaseController in the controllers which need to be secured. Nothing new
so far. However, if almost 100% of your controllers need to be secured you will be extending this
SecuredBaseController over and over again. This does not only cost you time, but it also violates DRY.

Solution

As mentioned earlier, Grails uses templates for creating artifacts and scaffolding. The default template for
creating new controllers looks something like:

class @artifact.name@Controller {

def index = { }
}

When creating a new controller the @artifact.name@ will be replaced by the name you specified for the
new controller.

To secure all newly created controllers by default, we need to extend the SecuredBaseController in the
template:

Document generated by Confluence on May 01, 2007 11:37 Page 155


class @artifact.name@Controller extends SecuredBaseController {

def index = { }
}

Customizing templates

To customize the templates for you project you need to the install the templates:

grails install-templates

This will create the src/templates folder in your project which will contain various artifact and scaffolding
templates. These application specific templates can be customized and Grails will use them the next time
you create artificats or generate scaffolding. Grails will first check if the needed template exists within the
project, if it exists it will be used, otherwise the default template from the Grails distribution will be used.
This also means that templates which are not used can be removed from the project.

Note that both the artifact and scaffolding template folder contain a Controller template. So in the
example above both templates need to be changed to extend the SecuredBaseController.

Taking it further

Most projects will use the scaffolding generation only for prototyping or as a starting point, as the
generated views need to be changed to the layout requirements of the project. This can be a really time
consuming as it is not just extending some base class like the SecuredBaseController example above. You
can give your development time a huge boost by changing the list, show, create and edit scaffolding
templates before generating the views.

Document generated by Confluence on May 01, 2007 11:37 Page 156


Auto Reloading

This page last changed on Apr 30, 2007 by wangjammer5.

Auto Reloading

When a Grails application is executed via the 'grails run-app' command it is configured for auto-reloading
(development mode). This mode is disabled when a WAR is created via the 'grails war' command.

All Grails artifacts (controllers, tag libs, services etc.) are reloadable in Grails, however there are some
quirks:

• Services can currently only be reloaded if the 'transactional' property is set to false
• Domain Classes are re-mapped to the database at runtime. If the data source is configured to
auto-generate the database via the 'update' setting of the 'dbCreate' property it will do its best
effort to update the database. This process doesn't always go smoothly however and changing
domain classes occasionally require an application restart

This content is a little stale and needs an update for 0.5

Document generated by Confluence on May 01, 2007 11:37 Page 157


Builders

This page last changed on Sep 02, 2006 by takamori.

Builders

Hibernate Criteria Builder

The Hibernate Criteria Builder allows you to create queries that map to the Hibernate Criteria API. There
are equivalent builder nodes for most criterion within the Hibernate Expression class. For more info see
the Builders Reference

The builder can be used standalone by passing a persistent class and sessionFactory instance:

new grails.orm.HibernateCriteriaBuilder(User.class, sessionFactory).list {


eq("firstName", "Fred")
}

Or an instance can be retrieved via the createCriteria method of Grails domain class instances:

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

The results variable above cannot be typed as a List since it may actually be a proxy.

By default the builder returns a list of results, but can be forced to retrieve a unique result using the "get"
node:

def c = Account.createCriteria()
def a = c.get {
eq("number", 40830994)
}

OpenRico Builder

Grails provides support for the OpenRico project. See this document for more details on how OpenRico
handles response content. Using OpenRicoBuilder in controllers users can generate any response for
OpenRico requests, see the example below which uses the Google API to retrieve search results and then
creates an OpenRico ajax response.

Document generated by Confluence on May 01, 2007 11:37 Page 158


def result = google.doSearch();
new grails.util.OpenRicoBuilder(response).ajax {
object(id:"googleAutoComplete") {
for (re in result.resultElements) {
div(class:"autoCompleteResult", re.URL)
}
}
}

It should be noted that at the moment, OpenRico requests are not handled by the Grails Ajax tags; there
is no OpenRico implementation in JavascriptTagLib.

Document generated by Confluence on May 01, 2007 11:37 Page 159


Command Line Scripting

This page last changed on Jan 30, 2007 by graemerocher@yahoo.co.uk.

Command Line Scripting (Since 0.4)

Basics

Grails supports command line scripting using a Groovy ant wrapper called Gant

A Gant script is essentially a Groovy script that defines special "tasks" that can depend
on each other and invoke other tasks (just like Ant). The bonus is that your build files
are written in Groovy not XML.

A basic Gant script in Grails looks like this:

task('default':"The task description") {


depends(clean, compile)
jar()
}
task(clean:"Delete stuff") { Ant.delete(dir:"build") }
task(compile:"Compile stuff") {
Ant.mkdir(dir:"build/classes")
Ant.javac(srcdir:"src", destdir:"build/classes")
}
task(jar:"Package stuff") {
Ant.jar(basedir:"build/classes", destfile:"build/myproject.jar")
}

The above of course is a very simple build, as your build gets more complex the power of Groovy
comes in handy. Note the use of the implicit "Ant" instance

Using Ant from a Gant script

You can use Ant from a Gant script using the implicit Ant variable. For instance consider this example
from the Compile.groovy Gant script in $GRAILS_HOME/script:

task ('default': "Performs compilation of Java sources") {


compile()
}

task(compile : "Implementation of compilation phase") {


println "Compiling sources.."
Ant.sequential {
mkdir(dir:"${basedir}/web-app/WEB-INF/classes")
path(id:"classpath") {
fileset(dir:"lib")
fileset(dir:"${grailsHome}/lib")
fileset(dir:"${grailsHome}/dist")
fileset(dir:"${basedir}/web-app/WEB-INF/classes")
}
javac(srcdir:"${basedir}/src/java",
destdir:"${basedir}/web-app/WEB-INF/classes",

Document generated by Confluence on May 01, 2007 11:37 Page 160


classpathref:"classpath",debug:"on",
deprecation:"on", optimize:"off")

}
}

Here the script uses the Ant variable in combination with the sequential method which allows you to
omit the Ant prefix before each Ant call such as mkdir, javac and so on

Creating & Executing a Script in Grails

You can create a Gant script in Grails by executing the command:

grails create-script MyScript

The above will create a Gant script in $PROJECT_HOME/scripts, but this is not the only place
they can live as we will see in the next section.

To execute the above script you can type the command:

grails my-script

What happens here is that Grails uses a convention to convert the command number (in lower case,
separated by
underscores) into the script name (in camel case) and then invokes the "default" task defined
within the script.

Where do Gant scripts live?

In Grails Gant scripts can live in a number of places defined below:

• $GRAILS_HOME/scripts
• $PROJECT_HOME/scripts
• $USER_HOME/.grails/scripts
• $PROJECT_HOME/plugins/*/scripts

If there are multiple scripts of the same name in these locations Grails will prompt you for
a choice of which one you want to execute. In other words, one script never overrides another.

Useful Grails provided Scripts

Grails provides a number of scripts that are built in that can be re-used. Within the
$GRAILS_HOME/scripts directory you will find these. For example the Compile.groovy
script allows you to depend on Grails' compilation step or the Package.groovy script
allows you to depend on Grails' packaging step (which involves the generation of web.xml

Document generated by Confluence on May 01, 2007 11:37 Page 161


on the fly)

To rely on these in your code you need to "include" them in your Gant script. The general
way to do this is via establishing the GRAILS_HOME environment variable:

grailsHome = Ant.project.properties."environment.GRAILS_HOME"
includeTargets << new File ( "${grailsHome}/scripts/Package.groovy" )

task('default':"My Funky Script") {


depends( package )
}

in the example above we include the Package.groovy script and depend on its package
task to ensure Grails is packaged correctly before executing our task.

Setting up the Grails classpath

Another useful task to depend on is within Init.groovy called classpath that does the job
of setting up the classpath using Groovy's RootLoader so that referencing within the lib, classes
or grails-app dir doesn't throw a ClassNotFoundException:

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

task('default':"My Funky Script") {


depends( classpath )

// reference a Grails class here


}

If you don't depend on this task then an exception is thrown. Note that this is done because some
tasks need to delete classes (like Clean.groovy) and certain systems (like Windows) disallow this
if they have been loaded by the JVM

Bootstrapping Grails inside a Gant script

Sometimes it is useful to bootstrap the whole Grails environment inside a Grails script. This
is what some of the scaffolding and unit testing task do for example. To do this you can depend
on the Bootstrap.groovy script:

import org.springframework.orm.hibernate3.*

grailsHome = Ant.project.properties."environment.GRAILS_HOME"
includeTargets << new File ( "${grailsHome}/scripts/Bootstrap.groovy" )

task('default':"My Funky Script") {


depends( bootstrap )

def bookClass = application.getDomainClass("Book").getClazz()

def sf = ctx.getBean("sessionFactory")

def template = new HibernateTemplate(sf)

Document generated by Confluence on May 01, 2007 11:37 Page 162


def books = template.loadAll(bookClass)
books.each { println it.title }
}

What the Bootstrap.groovy script does is place a "application" variable which is an instance
of GrailsApplication and a "ctx" which is the Spring ApplicationContext

Document generated by Confluence on May 01, 2007 11:37 Page 163


Command Line Tools

This page last changed on Sep 05, 2006 by graeme.rocher@gmail.com.

The Grails console

Grails ships with an extended version of the regular Groovy console. To run the console simply type the
following command from the root of a Grails project:

grails console

The console is a Swing GUI interface that lets you type arbitrary commands and execute them. It is a
good way to learn Grails and try out the various dynamic finders available on your domain model.

The Grails interactive shell

In addition to the console there is the interactive shell. It works similar to the console but with a text UI
only. To run the shell simply type the following command from the root of a Grails project:

grails shell

There are instructions on how to use it when it loads, but essentially you type in the commands you want
to execute separated by carriage returns and you then type go followed by a carriage return to execute
the commands.

General usage

Both console and shell are useful for working interactively with your Grails application:

• find domain objects with the help of dynamic finder methods


• call mutator methods on domain objects once you have a reference to them
• save() or delete() domain objects like you would otherwise do in a controller
• ... more to come here
Such an interactive work can be helpful for debugging purposes, for verifying your assumptions
about the object state and behavior, to test the effect of dynamic finder methods before putting the
code in a controller.

Below is a transcript of an example session with a grails shell for a fictious book store application.

.... more to come here

Packaging a WAR

Document generated by Confluence on May 01, 2007 11:37 Page 164


To package a WAR file for deployment onto an application server you can do:

grails war

By default this will package for a production environment you can change this by doing:

grails test war // for test enviroment


grails dev war // for development environment
grails prod war // for production

If you want to package for X other environment you can do:

grails -Dgrails.env=blah war

Document generated by Confluence on May 01, 2007 11:37 Page 165


Command objects and Form Validation

This page last changed on Apr 25, 2007 by brownj.

Command Objects

Grails Command Objects provide a simple mechanism to validate form fields that do not map directly to
domain objects. Using the validation constraints concept that applies to domain classes, including the
validate() method and "errors" dynamic property, Grails applies the concept of command objects to
controller actions. Controller actions may optionally specify any number of command object parameters.
The parameter types must be supplied so that Grails knows what objects to create, populate and
validate. Before the controller action is executed Grails will create an instance of the command object
class, populate the properties of the command object with request parameters having corresponding
names and the command object will be validated.

class LoginController {
def login = { LoginCommand cmd ->
if(cmd.hasErrors()) {
redirect(action:'loginForm')
}
else {
// do something else
}
}
}

The command object class may be defined under src/groovy/ or under grails-app/controllers/. The
command object class may also be defined in the same source file as the controller that uses it.

class LoginCommand {
String username
String password
static constraints = {
username(blank:false, minLength:6)
password(blank:false, minLength:6)
}
}

The dynamic errors property on command objects is an instance of the Spring


org.springframework.validation.Errors interface.

Document generated by Confluence on May 01, 2007 11:37 Page 166


Configuration

This page last changed on Apr 06, 2007 by corey_s@qwest.net.

Configuration

Configuring Start-up

Programmatic start-up configuration can be added to a Grails application by creating one or many
"BootStrap" classes in the "%PROJECT_HOME%\grails-app\conf" directory:

class ExampleBootStrap {

def init = { servletContext ->


// init app
}
def destroy = {
// destroy app
}
}

The "init" closure (if it exists) is called on application load and the "destroy" closure (again if it exists) on
application exit

Warning

It is not guaranteed that destroy will be called unless the application exits gracefully (for example
by using the application server's shutdown command) so don't rely on it too much

See the Quick Start page for an example of using the "init" closure to build and save domain objects.

Configuring Data Sources

There are two alternatives when it comes to configuring DataSources for Grails (effective Grails 0.3)

1. Use the JDBC DataSource by defining (test/dev/prod) DataSource under grails-app/conf folder
2. Use JNDI dataSource in the spring/resources.xml folder of the application. Normally you would use
this if you want to re-use the existing dataSource settings of the J2EE Server you are running your
Grails application on.

Specifying DataSource in the grails-app/conf folder

Data source names should end with "DataSource". If no (available) data sources are found Grails will
start with an in-memory HSQLDB database with the database schema created at run-time. There are four
required String properties:

Document generated by Confluence on May 01, 2007 11:37 Page 167


• url - the JDBC url to the database
• driverClassName - the JDBC driver class name
• username - the username
• password - the password

class HsqlDataSource {
String dbCreate = "update"
String url = "jdbc:hsqldb:hsql://localhost"
String driverClassName = "org.hsqldb.jdbcDriver"
String username = "sa"
String password = ""
}

Environments

By default Grails creates 3 data sources called DevelopmentDataSource, ProductionDataSource and


TestDataSource. These can be adapted to each target environment. When you run Grails you can then
tell it what data source to use when specifying the environment:

grails run-app // runs with the default "development" data source


grails dev run-app // runs with the "development" data source
grails prod run-app // runs with the production data source
grails test run-app // runs with the test data source

Warning

When running as prod, you must be sure to copy the grails-app/views directory into
web-app/WEB-INF/grails-app/, otherwise grails won't be able to find any of your views. Note that
you must do this _after_ you have started your app.

These options are also available when packaging the application as a WAR file, although in this case the
default data source used is production:

grails war // Packages the application with the "production" data source
grails dev war // Packages the application with the "development" data source
grails prod war // Packages the application with the "production" data source

If you have other environments you need to target you can create another data source that follows the
convention. For example BookDataSource and then start Grails app as follows:

grails -Dgrails.env=book run-app

Connection Pooling

By default org.apache.commons.dbcp.BasicDataSource is used, all of its properties can be added to data


source classes. If you want to disable connection pooling create a "pooling" property and set it to false.
This will use org.springframework.jdbc.datasource.DriverManagerDataSource instead. Properties
configured on Grails data sources that are not supported by DriverManagerDataSource will silently be

Document generated by Confluence on May 01, 2007 11:37 Page 168


ignored.

boolean pooling = false

Automatic Database Generation

By default Grails is configured to attempt to update or create the database on application load this is
configured with the "dbCreate" property:

String dbCreate= "update"

If this property is removed the database will have to be created manually or by a separate process. Other
possible values for this property are "create" and "create-drop".

SQL Logging

To enable SQL logging in your grails application add the following property to the Grails data source file:

def logSql = true

Configuring a Custom Dialect

To set a custom dialect for Hibernate to use add a 'dialect' property to the data source referencing the
dialect class to use:

def dialect = MySQLDialect.class

Using other databases

Grails GORM is based on the Hibernate object/relational mapping framework. Therefore


Grails supports all Hibernate databases.

Hibernate is regularly tested with the following SQL databases:

• DB2 7.1, 7.2, 8.1


• HSQL DB
• HypersonicSQL 1.61, 1.7.0, 1.7.2, 1.8
• Microsoft SQL Server 2000
• MySQL 3.23, 4.0, 4.1, 5.0
• Oracle 8i, 9i, 10g
• PostgreSQL 7.1.2, 7.2, 7.3, 7.4, 8.0, 8.1
• SAP DB 7.3

Document generated by Confluence on May 01, 2007 11:37 Page 169


• Sybase 12.5 (JConnect 5.5)
• Timesten 5.1

Hibernate has also been tested with and is believed to be compatible with current versions of:

• Apache Derby
• HP NonStop SQL/MX 2.0 (requires Dialect from HP)
• Firebird (1.5 with JayBird 1.01 tested)
• FrontBase
• Informix
• Ingres
• Interbase (6.0.1 tested)
• Mckoi SQL
• Pointbase Embedded (4.3 tested)
• Progress 9

Using MySQL

Download the Java MySQL driver from:

http://www.mysql.com/products/connector/j/

Unpack the archive and copy the mysql*.jar (not the debug jar) to lib
in your grails application directory.

Change the DevelopmentDataSource to use your own values:

class DevelopmentDataSource {
boolean pooling = true
String dbCreate = "create-drop"
String url = "jdbc:mysql://localhost/yourDB"
String driverClassName = "com.mysql.jdbc.Driver"
String username = "yourUser"
String password = "yourPassword"
}

Using JNDI DataSources through spring/resources.xml

Normally you would use this approach if running inside a J2EE server which has its own JNDI entries for
the Database already set up, so you could re-use the connection settings. If there is a bean by name
"dataSource" with class "org.springframework.jndi.JndiObjectFactoryBean", Grails runtime would take
this entry instead of the grails-app/conf/ datasources.

An example entry for dataSource bean in the resources.xml would be as following. Of course you have to
change the property jndiName's value appropriately.

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">


<property name="jndiName" value="jdbc/myDataSource" />

Document generated by Confluence on May 01, 2007 11:37 Page 170


</bean>

Note: This feature is available since Grails 0.3 (see http://jira.codehaus.org/browse/GRAILS-272)

Changing Application Name (Since 0.5)

Occasionally you may want the application name to be different from the project's directory name. This
affects the URI used when testing locally, and the name of JARs produced.

Edit the application.properties file in your project directory and change the value of app.name

Document generated by Confluence on May 01, 2007 11:37 Page 171


Controllers

This page last changed on Apr 24, 2007 by brownj.

Grails Controllers

What is a controller?

A controller handles requests and creates or prepares the response. They can generate the response or
delegate to a view. To create a controller simply create a class whose name ends with "Controller" and
place it within the "grails-app/controllers" directory.

The first part of your controller name is mapped to a URI and each action defined within your controller
maps to URI within the controller name URI.

Controllers are request-scoped. A new instance is created for each request.

Creating Grails Controllers

If you're lazy you can create a controller using the "create-controller" target which will prompt for the
name of your controller:

grails create-controller

For example if we typed "book" the following controller would be created:

class BookController { ... }

BookController maps to the <...>/book URI. Note that grails has done no special configuration in the
background, all this is doing is creating you a controller from a template.

Creating Actions

A controller can have multiple closure properties. Each of these properties maps to a URI:

class BookController {
def list = {

// do controller logic
// create model

return model
};
}

Document generated by Confluence on May 01, 2007 11:37 Page 172


This example maps to the <...>/book/list URI. If only one closure property is present the default URI for
a controller maps to this property. Alternatively you can define an "index" action which is the action that
handles requests when no action is specified in the URI i.e. <...>/book

Controller actions may accept command object parameters. See the Command Object documentation
for details.

Setting the default action

There are 2 ways to set the default action (ie the action that is executed if no only the controller name is
included in the uri), the simplest way is to merely create an action called "index":

def index = {
redirect(action:list)
}

Alternatively you can set it explicitly with the "defaultAction" property:

def defaultAction = "list"

Restricting Access To Actions

By default all controller actions are accessible using any HTTP request method (GET, PUT, POST, etc...).
The documentation for HTTP Method Restrictions explains how to restrict access to certain actions.

Accessing the request parameters, session etc

Every controller has a number of properties inject into them at runtime, these make it possible to access
the request, session etc. For a full reference on these please see the Dynamic Methods Reference

class BookController {
def find = {
def findBy = params["findBy"]
def appContext = servletContext["appContext"]
def loggedUser = session["logged_user"]

// do stuff
// return model
return model
};
}

Using Flash Scope

Flash scope is a concept introduction by Rails and essentially is a temporary store for attributes that
should be available for the next request and the request only, after which they are cleared. This is useful

Document generated by Confluence on May 01, 2007 11:37 Page 173


for setting a message directly before redirection for example:

def delete = {
def b = Book.get( params['id'] )
if(!b) {
flash['message'] = "User not found for id ${params['id']}"
redirect(action:list)
}
... // remaining code
}

Binding Request Data to the Model

Request parameters get passed into web applications as strings, causing a typical scenario of having to
convert each string value into its equivalent object representation. With Grails domain classes this is
made simple by the "properties" property:

def save = {
def b = new Book()
b.properties = params
b.save()
}

In the above example with one line of code the request parameters are auto-magically converted and set
on the instance of Book. If you're using a command object or some other object that you want to bind
data to you can use the "bindData" method present in controllers:

def sc = new SaveCommand()


bindData(sc, params)

Returning the Model

A model is essentially a map that the view uses when rendering. There are a couple of ways to return a
model, the first way is to explicitly return a map instance:

def show = {
def b = Book.get( params['id'] )
return [ book : b ]
}

If no explicit model is returned the controller's properties will be used as the model thus allowing you to
write code like this:

class BookController {
List books
List authors
def list = {
books = Book.list()
authors = Author.list()
}
}

In the above example the "books" and "authors" properties will be available in the view. A more

Document generated by Confluence on May 01, 2007 11:37 Page 174


advanced approach is to return an instance of the Spring ModelAndView class.

Rendering a Response

Sometimes its easier (typically with Ajax applications) to render snippets of text or code to the response
directly from the controller. For this the highly flexible "render" method can be used:

render "Hello World!"

The above code writes the text "Hello World!" to the response, other examples include:

// write some markup


render {
for(b in books) {
div(id:b.id, b.title)
}
}
// render a specific view
render(view:'show')
// render a template for each item in a collection
render(template:'book_template', collection:Book.list())
// render some text with encoding and content type
render(text:"<xml>some xml</xml>",contentType:"text/xml",encoding:"UTF-8")

Action Redirection & Chaining

Actions can be redirected using the "redirect" method present in all controllers:

class OverviewController {
def login = {}

def find = {
if(!session["logged_user"])
redirect(action:login)
.....
};
}

The redirect method expects either another closure within the same controller class, the name of a
controller and action in another class, a URI for a resource in the webapp or a full URL:

// Call the login action within the same class


redirect(action:login)
// Also redirects to the index action in the home controller
redirect(controller:'home',action:'index')
// Redirect to an explicit URI
redirect(uri:"/login.html")
// Redirect to a URL
redirect(url:"http://grails.org")

Parameters can be optionally passed from one action to the next using the params argument of the
method:

redirect(action:myaction, params:["myparam":"myvalue"])

These params are made available through the "params" dynamic property that also accesses request
parameters. If a parameter is specified with the same name as a request parameter the request
parameter is overridden and the controller parameter used.

Document generated by Confluence on May 01, 2007 11:37 Page 175


Actions can also be chained. Chaining allows the model to be retained from one action to the next. For
example calling the "firstInChain" action:

class ChainController {
def firstInChain = {
chain(action:secondInChain,model:["step1":new Object()])
}
def secondInChain = {
chain(action:thirdInChain,model:["step2":new Object()])
};
def thirdInChain= {
return ["step3":new Object()])
};
}

Results in the model:

["step1":object1, "step2":object2, "step3":object3]

The model can be accessed in subsequent controller actions in the chain via the "chainModel" map. This
dynamic property only exists in actions following the call to "chain":

class ChainController {

def nextInChain = {
def model = chainModel["myModel"]
.....
};
}

Like the "redirect" method you can also pass parameters to the chain method:

chain(action:"/another/action", model:["step1":object1], params:["myparam":"param1"])

Action Interceptors

Introduction

Often it is useful to intercept processing based on either request, session or application state. This can be
achieved via action interceptors. There are currently 2 types of interceptors: before and after.

Before Interception

The 'before' interceptor intercepts processing before the action is executed. If it returns 'false' then the
following action will not be executed. The interceptor can be defined for all actions as follows:

def beforeInterceptor = {
println "Tracing action ${actionUri}"
}

The above will be executed before all actions and does not interfere with processing. A common use case
is however for authentication:

def beforeInterceptor = [action:this.&auth,except:'login']


// defined as a regular method so its private

Document generated by Confluence on May 01, 2007 11:37 Page 176


def auth() {
if(!session.user) {
redirect(action:'login')
return false
}
}
def login = {
// display login page
}

The above code defines a method called 'auth'. A method is used so that it is not exposed as an action to
the outside world (i.e. it is private). The 'beforeInterceptor' then defines an interceptor that is used on all
actions 'except' the login action and is told to execute the 'auth' method. The 'auth' method is referenced
using Groovy's method pointer syntax, within the method itself it detects whether there is a user in the
session otherwise it redirects to the login action and returns false, instruction the intercepted action not
to be processed.

After Interception

To define an interceptor that is executed after an action use the 'afterInterceptor' property:

def afterInterceptor = { model ->


println "Tracing action ${actionUri}"
}

The after interceptor takes the resulting model as an argument and can hence perform post manipulation
of the model or response.

Interception Conditions

Rails users will be familiar with the authentication example and how the 'except' condition was used when
executing the interceptor (interceptors are called 'filters' in Rails, this terminology conflicts with the
servlet filter terminology in Java land):

def beforeInterceptor = [action:this.&auth,except:'login']

This executes the interceptor for all actions except the specified action. A list of actions can also be
defined as follows:

def beforeInterceptor = [action:this.&auth,except:['login','register']]

The other supported condition is 'only', this executes the interceptor for only the specified actions:

def beforeInterceptor = [action:this.&auth,only:['secure']]

Handling File Uploads

To upload a file the first step is to create a multipart form like the one below:

Upload Form: <br />


<g:form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="myFile" />

Document generated by Confluence on May 01, 2007 11:37 Page 177


<input type="submit" />
</g:form>

There are then a number of ways to handle the file upload. The first way is to work with the Spring
MultipartFile instance directly:

def upload = {
def f = request.getFile('myFile')
if(!f.empty) {
f.transferTo( new File('someotherloc') )
}
else {
flash.message = 'file cannot be empty'
redirect(action:'uploadForm')
}
}

This is clearly handy for doing transfers to other destinations and manipulating the file directly (you can
also open an InputStream, see javadoc). The next way
to deal with file uploads is to bind the file's contents to a domain class or command bean. Lets look at a
domain class example say you have an 'Image' domain class like the below:

class Image {
byte[] myFile
}

Now when we do the usual set of properties like the below:

def img = new Image()


img.properties = params

The contents of the file will automatically be converted into a byte[] and set on the image domain class.
It is also possible to set the contents of the file as a string by
changing the type of the 'myFile' property on the image to a String type:

class Image {
String myFile
}

The final way to do this is via the 'bindData' method which you can use in combination with a command
object. Say we have a command object like the below:

class UploadCommand {
byte[] myFile
}

We can then use it in the controller like this:

def upload = {
def uc = new UploadCommand()
bindData(uc, params)
assert uc.myFile != null
}

Injecting services into controllers

Controllers may use services to delegate requests to business logic. To have these resources injected add
corresponding properties to the controller.

Document generated by Confluence on May 01, 2007 11:37 Page 178


CountryService countryService

Important here is the name of the property, not it's type. You could also write it without untyped.

def countryService

If you do want to inject services by type, you can add a property called byName to your controller.

class CountryController {
def byName = false
def CountryService whateverNameHere
}

Document generated by Confluence on May 01, 2007 11:37 Page 179


Dynamic Encoding Methods

This page last changed on Apr 30, 2007 by wangjammer5.

Dynamic Encoding Methods

Overview

As of version 0.4 Grails adds support for dynamic encode/decode methods. A set of standard codecs are
bundled with Grails. Grails also supports a simple mechanism for developers to contribute their own
codecs that will be recognized at runtime.

Codec Classes

A Grails codec class is a class that may contain an encode closure, a decode closure or both. When a
Grails application starts up the Grails framework will dynamically load codecs from the grails-app/utils/
directory.

The framework will look under grails-app/utils/ for class names that end with the word 'Codec'. For
example one of the standard codecs that ship with Grails is grails-app/utils/HTMLCodec.groovy

If a codec contains an encode closure Grails will create a dynamic encode method and add that method to
the String class with a name representing the codec that defined the encode closure. For example, the
HTMLCodec class defines an encode closure so Grails will attach that closure to the String class with the
name encodeAsHTML.

The HTMLCodec and URLCodec classes also define a decode closure so Grails will attach those closures to
the String class with the names decodeHTML and decodeURL. Dynamic codec methods may be invoked
from anywhere in a Grails application. For example, consider a case where a report contains a property
called 'description' and that description may contain special characters that need to be escaped to be
presented in an HTML document. One way to deal with that in a GSP is to encode the description
property using the dynamic encode method as shown below:

${report.description.encodeAsHTML()}

Decoding is performed using value.decodeHTML() syntax.

Standard Codecs

HTMLCodec

This codec perfoms HTML escaping and unescaping, so that values you provide can be rendered safely in

Document generated by Confluence on May 01, 2007 11:37 Page 180


an HTML page without creating any HTML tags or damaging the page layout. For example, given a value
"Don't you know that 2 > 1?" you wouldn't be able to show this safely within an HTML page because the
> will look like it closes a tag, which is especially bad if you render this data within an attribute, such as
the value attribute of an input field.

Example of usage:

<input name="comment.message" value="${comment.message.encodeAsHTML()}"/>

Note that the HTML encoding does not re-encode apostrophe/single quote so you must use double quotes
on attribute values to avoid text with apostrophes messing up your page.

URLCodec

URL encoding is required when creating URLs in links or form actions, or any time data may be used to
create a URL. It prevents illegal characters getting into the URL to change its meaning, for example a
"Apple & Blackberry" is not going to work well as a parameter in a GET request as the ampersand will
break the parsing of parameters.

Example of usage:

<a href="/mycontroller/find?searchKey=${lastSearch.encodeAsURL()}">Repeat last search</a>

Base64Codec

Performs Base64 encode/decode functions.


Example of usage:

Your registration code is: user.registrationCode.encodeAsBase64()

JavaScriptCodec

Example of usage:

Element.update('${elementId}', '${render(template: "/common/message").encodeAsJavaScript()}')

Custom Codecs

Applications may define their own codecs and Grails will load them along with the standard codecs. A
custom codec class must be defined in the grails-app/utils/ directory and the class name must end with
'Codec'. The codec may contain a static encode closure, a static decode closure or both. The closure
should expect a single argument which will be the object that the dynamic method was invoked on.

Document generated by Confluence on May 01, 2007 11:37 Page 181


class PigLatinCodec {

static encode = { str ->

// convert the string to piglatin and return the result

With that codec in place an application could do something like this:

${lastName.encodeAsPigLatin()}

Document generated by Confluence on May 01, 2007 11:37 Page 182


Dynamic Tag Libraries

This page last changed on Feb 01, 2007 by raffaele.castagno@gmail.com.

Dynamic Tag Libraries

Grails has a wide range of custom tags built in for both JSP and GSP (see the Tag Library Reference
here), however Grails also allows the creation of simple, logical, and iterative custom tags through its
simple dynamic tag library mechanism.

Contribute!

Got a tag that you would like to share with the rest of the Grails developers? Contribute a tag!

The benefit of Grails' tags is that they require no additional configuration, no updating of TLD descriptors,
and can be auto-reloaded at runtime without a server restart. This makes developing tags feel as if you
were just developing another part of the view and increases their usefulness tenfold.

Warning

Grails Tag libraries require a little extra work to integrate into JSP and are more seamlessly
integrated into GSP because of its dynamic nature. See the last section for how to use grails tags
from JSP

Simple tags

To create new tags open the "grails-app/taglib/ApplicationTagLib.groovy" file or create a new class ending
in "TagLib". To create a simple tag add a new closure property that takes 1 argument which are the
attributes of the tag:

def includeJs = { attrs ->


out << "<script src='scripts/${attrs['script']}.js' />"
}

To call your tag your from a GSP page use the "g" prefix followed by the tag property name:

<g:includeJs script="myscript" />

Logical tags

You can also create logical tags by using a closure syntax that takes 2 arguments, the attributes of the

Document generated by Confluence on May 01, 2007 11:37 Page 183


tag and the body of the tag as a closure:

def isAdmin = { attrs, body ->


def user = attrs['user']
if(user != null && checkUserPrivs(user)) {
body()
}
}

The tag above checks if the user is an administrator and invokes the body of the tag if he/she is:

<g:isAdmin user="${myUser}">
// some restricted content
</g:isAdmin>

Iterative tags

And of course you can create iterative tags:

def repeat = { attrs, body ->


def i = Integer.valueOf( attrs["times"] )
def current = 0
i.times {
body( ++current ) // pass the current iteration as the groovy default arg "it"
}
}

To call your iterative tag do the following:

<g:repeat times="3">
<p>Repeat this 3 times! Current repeat = ${it}</p>
</g:repeat>

Markup building in tags

Grails provides a special method that allows building of markup (a common usecase in tags). To do so
you invoke the 'mkp' method passing a closure with the markup you want rendered:

def dialog = { attrs, body ->


mkp {
div('class':'dialog') {
body()
}
}
}

Tags as method calls in GSP

GSP tags can also be used in Groovy expressions in the GSP page. For example, the hasErrors tag can be

Document generated by Confluence on May 01, 2007 11:37 Page 184


used normally as a tag like this:

<g:hasErrors bean="${book}" field="title">


<span class='label error'>There were errors on the book title</span>
</g:hasErrors>

Or as a method call, like this:

<span id="title" class="label ${hasErrors(bean:book,field:'title','errors')}">Title</span>

The last argument of the method is taken as the body of the tag. Or you can pass a closure that returns a
string:

<%=
hasErrors(bean:book,field:'title') {
'errors'
} %>

Using Grails tag libs from JSP

To use a Grails taglib definition in JSP you can use the JSP "invokeTag" tag which will call a tag defined in
the Grail tag library:

<g:invokeTag name="includeJs" script="myscript" />


<g:invokeTag name="isAdmin" user="${myUser}">
// some restricted content
</g:invokeTag >
<g:invokeTag name="repeat" times="3">
<p>Repeat this 3 times! Current repeat = <c:out value="${it}" /></p>
</g:invokeTag>

If you want your tags to appear like normal JSP tags, here's what you need to do:

1) Create a new java class that sub classes the Grails


org.codehaus.groovy.grails.web.taglib.jsp.JspInvokeGrailsTagLibTag class and calls the "setName()"
method in the constructore of your new class passing the name of your tag:

package com.mycompany.taglib;
public class IncludeJsTag extends JspInvokeGrailsTagLibTag {
public static final String TAG_NAME = "includeJs";
public IncludeJsTag() {
super.setName(TAG_NAME);
}
}

2) JSP requires declarative tag library definition files (TLD) for each tag, to do this modify the
"web-app/WEB-INF/tld/grails.tld" file and add the necessary entries that point to your class:

<tag>
<name>includeJs</name>

Document generated by Confluence on May 01, 2007 11:37 Page 185


<tag-class>com.mycompany.taglib.IncludeJsTag</tag-class>
<body-content>JSP</body-content>
<variable>
<name-given>it</name-given>
<variable-class>java.lang.Object</variable-class>
<declare>true</declare>
<scope>AT_BEGIN</scope>
</variable>
<dynamic-attributes>true</dynamic-attributes>
</tag>

3) You can then call your tag from JSP like a normal JSP tag:

<g:includeJs script="myscript" />

Document generated by Confluence on May 01, 2007 11:37 Page 186


Functional Testing

This page last changed on Nov 10, 2006 by hansamann.

Functional Testing

In addition to unit testing, Grails supports functional testing of your web application.

For this purpose, it uses the free open-source Canoo WebTest .

If you want to try out webtest very quickly, you can create a new project with create-app, create a
domain class and then "generate-all" this domain class. Then generate the test layout with "create
webtest" and generate the webtest itself with "generate-webtest". You can then run the tests with
"run-webtest". Note that the scaffolded webtest will not work out of the box if you use dynamic
scaffolding of your controller. Just use generative scaffolding for the controller instead.

How to test your web application

Install and create

From the root directory of your application call

grails create-webtest

This results in the following actions

• downloads Canoo WebTest if needed and installs under grails.home/downloads/webtest. The


intial dowload can take a few minutes. The progress of download is indicated.
• creates the test directory structure for the current application
• creates standard properties and a standard test suite

To scaffold a webtest for a given domain class use

grails generate-webtest

and enter the name of the domain class when prompted.

• creates an initial webtest for the default views and controllers of the domain class
• tests basic operations: list, create, delete through the web GUI

Running the tests.

Document generated by Confluence on May 01, 2007 11:37 Page 187


From the root directory of your application call

grails run-webtest

Runs the tests and puts reports in the reports dir.

When on Windows, the browser is automatically opened on the HTML report. It will present you a header
with summarized and statistical data like below.

A trailing section shows details about all operations effected during the test (excerpt).

Document generated by Confluence on May 01, 2007 11:37 Page 188


Note that WebTest stores all result pages it received from the server.
From the test report, you can click on the corresponding link to find out what
page the test engine worked upon at this point.

Test First

WebTests can even be started if the server is not running. You can actually run the test before
you have coded anything.

In this case the report will show a lot of failed tests but that's helpful anyways. You'll see what
behavior the tests expect and how the report is generated.

Defining your tests

Document generated by Confluence on May 01, 2007 11:37 Page 189


The webtest folder layout

After creation and generation of a test for the mydomain domain class, you'll find the following files and
folders below your application folder:

myapp
+-- webtest
+-- conf (webtest.properties)
+-- reports (readme.txt)
+-- tests (TestSuite.groovy, MydomainTest.groovy)

Notable places for costomization are

folder file customize for

conf webtest.properties defining host/port/app for testing


other than default

tests TestSuite.groovy manually defining the suite if


auto-detection is not wanted

tests MydomainTest.groovy specifying the test steps (see


below)

Adapting the test logic

MydomainTest.groovy will initially contain lines like

class MydomainTest extends grails.util.WebTest {

// Unlike unit tests, functional tests are often sequence dependent.


// Specify that sequence here.
void suite() {
testMydomainListNewDelete()
// add tests for more operations here
}

def testMydomainListNewDelete() {
webtest('Mydomain basic operations: view list, create new entry, back to view, delete,
view'){
invoke(url:'mydomain')
verifyText(text:'Home')

verifyListPage(0) // <- internal method call for extracting common steps

clickLink(label:'New Mydomain')
verifyText(text:'Create Mydomain')
clickButton(label:'Create')

// more ...
}

There are multiple steps like invoke, clickButton, verifyXXX, etc. that make up the test specification.

Find the full list of available steps, their parameters, a comprehensive description, and examples under
WebTest Docs.

The online documentation lists these steps in their ANT notation (i.e. XML). This exactly maps to the

Document generated by Confluence on May 01, 2007 11:37 Page 190


builder calls inside the webtest() methods in MyappTest.groovy. Behind the scenes, there is an
AntBuilder that cares for the mapping, effectively producing a Groovy-API on top of Canoo WebTest.

Adapt the lines in MydomainTest.groovy to match the expected behavior of your webapp. If you have any
bootstrapped data, your tests can rely on this data being available when starting the tests.

More Tests

You can have many tests like MydomainTest.groovy in the tests directory or its subdirectories.

Every such test must extend grails.util.WebTest and provide a suite method that calls each available
test method. In subdirectories, tests must have the according package statements.

Tests will automatically be picked up by TestSuite.groovy. You can customize this logic to define your
own suite (see its inlined comments on how to do that).

Customization of the suite is sometimes needed to assert a special sequence of test execution or to
restrict the test execution to a subset of availabable tests.

groovy testing
Dierk Koenig

Document generated by Confluence on May 01, 2007 11:37 Page 191


GORM

This page last changed on Mar 29, 2007 by graeme.rocher@gmail.com.

Grails Object Relational Mapping (GORM)

Introduction

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 class in Java see the section on Hibernate Integration for how to write
Grails domain classes in Java but still use dynamic persistent methods.

More Information

• Creating a domain class


• Association & Composition
• Sets, Lists & Maps
• Mapping inheritance
• Performing CRUD operations
• Managing Relationships
• Domain Class Querying
• Hibernate Criteria Builder

Document generated by Confluence on May 01, 2007 11:37 Page 192


GORM - Collection Types

This page last changed on Mar 26, 2007 by graemerocher@yahoo.co.uk.

Sets, Lists & 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 (Since 0.5)

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]

Document generated by Confluence on May 01, 2007 11:37 Page 193


}

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.

Maps of objects (Since 0.5)

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

class Author {
Map books // my 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.

Document generated by Confluence on May 01, 2007 11:37 Page 194


GORM - Creating a domain class

This page last changed on Mar 21, 2007 by ozgwei@gmail.com.

Creating a Domain Class

Basics

A domain class in Grails is essentially a normal Groovy class. It looks like any other class except at
runtime it gets injected with 2 additional properties: an "id" property and a "version" property:

class Book {
String title
}

To help you get started you can run the following convenience target from the root of your Grails project:

grails create-domain-class

Optional and Transient properties

By default all properties are both persistent and required, to change that you can define List properties
called "optionals" and "transients". Transient properties are never written to the database. They don't
have a corresponding column in the database. Optional properties have corresponding columns in the
database that are nullable.

class Book {
static optionals = [ "releaseDate" ]
static transients = [ "digitalCopy" ]

Author author
String title
String author
Date releaseDate
File digitalCopy
}

Default values

You can also create default values for properties that you don't want to make optional. This is done like
so:

class Book {
//omitted code...

String title = ''


String author = '[author unknown]'
//etc..
}

Document generated by Confluence on May 01, 2007 11:37 Page 195


This is also helpful when you want to pre-populate form fields when creating new entries.

Changing the Table

You can change the name of the table used when doing the mapping using the withTable property:

class Book {

static withTable = "book_table"

String title = ''


}

SQL Reserved Words

Be careful with SQL reserved words. The code bellow will have problem because of the "order" attribute.
"order" is a SQL reserved word:

class Book {
Integer order
}

Document generated by Confluence on May 01, 2007 11:37 Page 196


GORM - CRUD

This page last changed on Nov 28, 2006 by toddbittner@gmail.com.

CRUD Operations

Grails domain classes use dynamic persistent methods to facilitate CRUD (Create/Read/Update/Delete)
operations on persistent classes:

Create

To create entries in the database, domain class instances support a "save" method which cascades to the
instance relationships. In the example below we only call "save" on the author and both the Author and
Book instances are persisted:

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


def b = new Book(title:"The Shining",author:a)
a.books.add(b)

// persist
a.save()

In this case we're having to create both sides of the relationship manually. GORM will manage the
persistence of your object model to the database, but won't manage the relationships for you.

However since 0.3 Grails provides more intelligent relationship management that will manage bidrectional
relationship state through dynamic methods:

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


.addBook( new Book(title:"The Shining") )
.addBook( new Book(title:"The Stand") )

This will add several books to the Author plus make sure the author property on each Book is set thus
managing this burden for you.

Read

Grails supports a number of ways of retrieving domain class instances, for more detail on querying see
the section on Domain Class Querying, however to retrieve an instance if the "id" is known you can use
the "get" static method:

Book.get(1)

Or to find all books the "findAll", "list" or "listOrderByX" static methods can be used:

Book.findAll() // retrieve all

Document generated by Confluence on May 01, 2007 11:37 Page 197


Book.list(10) // lists first 10 instances
Book.listOrderByTitle() // lists all the instances ordered by the "title" property

Update

The symantics of updating differ from that of saving a domain class. It is possible to update without
explicitly calling "save" with the changes automatically being persisted if no exceptions occur:

def b = Book.get(1)
b.releaseDate = new Date()

This behaviour is not always desired however paricularily when combined with validation constraints (ie
you don't want your domain object saved if it is not validated). Therefore if you explicity call "save" and
the object is not valid changes will not be persisted:

def b = Book.get(1)
b.title = null // can't have a null title
b.save() // won't save as fails to validate

It is sometimes handy though to make changes to your domain model programmatically if validation fails.
In this way the symantics of the "validate" method differ as it won't discard the changes if validation fails:

def b = Book.get(1)
b.publisher = "Print It"

if(!b.validate()) {
b.publisher = Publisher.DEFAULT
}

In the above case changes will still be persisted even though validation failed during the "validate"
method. If you want the "validate" method to not persist changes if it fails to validate you can pass a
boolean "true" argument:

b.validate(true)

Alternatively, if you want to explicitly control if changes are persisted you can use the "discard" method
that when called will discard any changes:

def b = Book.get(1)
b.title = "A New Title"

// something happenedd to change your mind


b.discard()

Delete

Domain class instances can be removed from the database by using the "delete" instance method:

Document generated by Confluence on May 01, 2007 11:37 Page 198


def b = Book.get(1)
b.delete()

Document generated by Confluence on May 01, 2007 11:37 Page 199


GORM - Defining relationships

This page last changed on Mar 29, 2007 by graeme.rocher@gmail.com.

Creating Relationships

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.

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. No other configuration is
required, and changes to the referenced object
will automatically be saved when the referencing
object is saved.

class Face {
Nose nose
}

This sets up a relationship between a Face and a single Nose. If the Face is deleted, the Nose will be
deleted also. This relationship is unidirectional currently, unless you add a reference in reverse from the
Nose:

class Nose {
Face face
}

In this scenario, deletion of either object will result in the deletion of the other. If this were part of a 3D
modelling system however noses might be part of a library of features, and as such deletion of the Face
referencing the nose should not delete the Nose. You just need to tell Grails that a Face "belongs" to a
Nose instead. While the terminology in this example is slightly unusual it is easy to understand:

class Face {
static belongsTo = Nose

Nose nose

Document generated by Confluence on May 01, 2007 11:37 Page 200


}

This tells Grails that the Nose is the important piece here and that we are simply "using" it and do not
own it.

Maintaining your references

Although we have created a two-way relationship here, setting:

myFace.nose = bigNose

...will not automatically do:

bigNose.face = myFace

You must implement this yourself, typically by implementing Face.setNose(Nose newNose) so that
it assigns "this" to newNose.face.

One-to-many & Many-to-one

Defining a one-to-many relationship is a simple matter of adding the mapping to the "hasMany" map.
Defining a property of type Set is optional (before Grails 0.3 you needed to have "Set books" as well as
the "hasMany ..."). If you want, you can define the property like this: "Set books = new HashSet()"

class Author {
static hasMany = [ books : Book ]

String name
}

The ownership in a relationship is implied by a reference to (i.e. property of the type of) another domain
class or by inclusion of the owned class in the hasMany map, detailed below.
One of the main features of Groovy is its support for static typing which means one-to-one and
many-to-one relationships require no additions to the "relationships" map:

class Book {
Author author
String title
}

For one-to-many's the owning side is assumed to be the "one" side of the relationship (in the above
example this would be "Author.groovy"), but if you create a one-to-one relationship it is important to
define the owning side of the relationship. For example if we had an Author class which had no
relationship to the Book class (ie in a one-to-one scenario) it would be assumed that the book class
"owned" the author which clearly is not the case!
The implications of this is that if you delete an instance of Book the delete operation will also delete the
Author, not exactly the desired effect. To define the belongings side of one-to-one or many-to-one
relationship we use the "belongsTo" property:

Document generated by Confluence on May 01, 2007 11:37 Page 201


class Book {
static belongsTo = Author

Author author
String title
}

A owning class have more than one class in hasMany map.

class Author {
static hasMany = [books:Book, coBooks:Book]
static mappedBy = [books:"mainAuthor", coBooks:"coAuthor"]

String name
}

class Book {
static belongsTo = Author

Author mainAuthor
Author coAuthor
String title
}

As you can see we have to use mappedBy for this case, to let the grails know how to map the fields since
the hasMany map contains duplicate class.
A class can also belong to multiple related classes like this:

static belongsTo = [Author,Publisher]

In other words:

• an owner can have belongings


• belongings use the 'belongsTo' property to refer to their owner(s)
• if an owner dies, all his belongings vanish, if the owner actually has direct references or an explicit
hasMany relationship.

Many-to-many relationships (Since 0.4)

Many-to-many relationships can be defined by having a hasMany on each side of the relationship with at
least one side having a belongsTo property:

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

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

Document generated by Confluence on May 01, 2007 11:37 Page 202


If you do not specify a belongsTo for at least one side of the relationship an error will be thrown.
The behaviour of a many-to-many relationship is that the "owning" side (in the above case Author) is the
only side that can cascade updates. In other words doing the below will save both the Author and the
Book:

new Author(..)
.addBook(new Book(..))
.save()

Since Author is the owner of this relationship this is possible, however you cannot add a new Author to a
Book and save the Book expecting the update to cascade as only the owning side can cascade updates in
this way.
Also, by default only saves and updates are cascaded from the owner and not deletes. The implication
here is that you must explicitly delete a Book to remove it otherwise you will get orphaned instances.
See the Author/Book example and files on the Hibernate Integration page.

Composition (Since 0.5)

It is also possible to define components with GORM. In this case the association will not map to a
separate table, but instead be in the same table as the owner of the composition. For example take the
following classes:

class Person {
String name
Address homeAddress
Address workAddress
static embedded = ['homeAddress', 'workAddress']
}
class Address {
String houseNumber
String postCode
}

In this even though we have two classes the homeAddress and workAddress properties map to the
person table in the following way:

Person Table

id name
home_address_house_number
home_address_post_code
work_address_house_number
work_address_post_code

As you can see the Person class is composed to two Address classes at the domain model and database
level.

Relationship Summary

Here is a tabular summary of possible relationships between two classes A and B.

Document generated by Confluence on May 01, 2007 11:37 Page 203


Relationships may be unidirectional (>) or bidirectional (<>) and have cardinalities one-to-one (1:1),
one-to-many (1:m), many-to-one (m:1), and many-to-many (n:m).
The owner is marked as bold.

A:B unidirectional bidirectional

1:1 A -> B A <-> B ; B.belongsTo = [ A]

1:m A -> Set ; A.hasMany= [B] A -> Set ; A.hasMany = [B]; B


-> A

m:1 A -> B A -> B ; B -> Set ; B.hasMany =


[A]

n:m n/a n/a

no belongsTo needed since in one-to-many always one is the owner.


opposite of

* Note that relatesToMany is deprecated, use hasMany

Document generated by Confluence on May 01, 2007 11:37 Page 204


GORM - Managing Relationships

This page last changed on Apr 12, 2007 by graemerocher@yahoo.co.uk.

Managing Relationships

As of 0.5 this syntax is deprecated! See next section for migration path.

Since 0.3, Grails provides quite a few methods to easy relationship management. Firstly if you have a
one-to-many relationship such as the Author-Book relationship defined below:

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

You can use the dynamic addBook method on author to ease relationship management:

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


.addBook(new Book(title:"IT"))
.addBook(new Book(title:"The Stand"))
.save()

The addBook method is available at runtime and uses the class name of the Book to automatically
establish the relationship. If it is bidirectional it will also make sure that the author property of the Book
instance is set.

If you have more than one one-to-many relationship defined for the same class:

class Author {
String name
static hasMany = [fiction:Book, nonFiction:Book]
}

You can use the add method which takes a to argument which defines which collection to add the book
to:

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


.add(to:"fiction",
new Book(title:"IT"))
.add(to:"nonFiction",
new Book(title:"On Writing: A Memoir of the Craft"))
.save()

Relationship Management for 0.5

Document generated by Confluence on May 01, 2007 11:37 Page 205


Since 0.5, Grails provides quite a few methods to easy relationship management. Firstly if you have a
one-to-many relationship such as the Author-Book relationship defined below:

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

You can use the dynamic addToBooks method on author to ease relationship management:

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


.addToBooks(title:"IT")
.addToBooks(title:"The Stand")
.save()

The addToBooks method is available at runtime and uses the name of the books collection to
automatically establish the relationship. If it is bidirectional it will also make sure that the author
property of the Book instance is set.

Conversely there is also a removeFromBooks method for removing a Book from a relationship:

author.removeFromBooks(myBook)

Document generated by Confluence on May 01, 2007 11:37 Page 206


GORM - Mapping inheritance

This page last changed on Nov 09, 2006 by graeme.rocher@gmail.com.

Mapping Inheritance

GORM uses table-per-heirarchy inheritance which essentially means the parent and all sub-classes share
the same table:

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

The above then allows you to perform polymorphic queries:

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

def podCasts = PodCast.findAll() // find only pod casts

Technical note for those interested: Under the covers, only one table is used in the
table-per-hierarchy model. A class column specifies the subclass and any fields in the subclasses
are included on the same table. Subclass fields cannot be "required" because the underlying
columns need to be nullable for the other subclasses. This doesn't however prevent you from
using Validation constraints to ensure that subclass fields are "required".

Document generated by Confluence on May 01, 2007 11:37 Page 207


GORM - Querying

This page last changed on Apr 30, 2007 by wangjammer5.

Domain Class Querying

Querying with dynamic methods

There are several ways to query for domain class instances, one of them being via Grails dynamic
methods, from more details see DomainClass Dynamic Methods:

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

results =
Book
.findByTitleLike("Harry Pot%")
results =
Book
.findByReleaseDateBetween( firstDate, secondDate )
results =
Book
.findByReleaseDateGreaterThan( someDate )
results =
Book
.findByTitleLikeOrReleaseDateLessThan( "%Something%", someDate )

// find by relationship
results = Book.findAllByAuthor( Author.get(1) )

// and to affect some sorting


results =
Book
.findAllByAuthor( Author.get(1), [sort:'title',order:'asc'] )

Querying by example

Just pass an example of the domain object you would like to find to the find() method.

def b = Book.find( new Book(title:'The Shining') )

Querying with a criteria builder

For more advanced queries or querying across objects graphs you can use Criteria (for a full reference
see the section on Builders):

def c = Book.createCriteria()
def results = c {
like("author.name", "Stephen%")
between("releaseDate", firstDate, secondDate )
}

Querying with HQL queries

Document generated by Confluence on May 01, 2007 11:37 Page 208


Otherwise, as Grails uses Hibernate internally you can use an HQL query:

def results =
Book.findAll("from Book as b where b.title like 'Lord of the%'")

Or with positional parameters:

def results =
Book.findAll("from Book as b where b.title like ?", ["The Shi%"])

This content is stale, needs update for 0.5 named parameters

Be careful with Groovy multi-line strings: if they contain any newlines, then the query will not work. So
for example this:

def results = Book.findAll("""


from Book as b,
Author as a
where b.author = a and a.surname = ?""", ['Smith'])

will not work. You have to use the line-continuation character:

def results = Book.findAll("""\


from Book as b, \
Author as a \
where b.author = a and a.surname = ?""", ['Smith'])

Note The space after "Author as a" is important, otherwise the string would look like "...Author as
awhere b.author...".

Querying with Eager Fetching

Sometimes is desireable to query objects that relate to each other without lazy=true , so SQL is
optimized and there is no n+1 SQL SELECT queries. To do that you can:

1) Add LEFT JOIN FETCH to your HQL query

2) You can also try with Criteria Builder, with something like this:

import org.hibernate.FetchMode as FM
// ......

def c2 = Task.createCriteria()
def tasks = c2.list{
eq("assignee.id", task.assignee.id)
maxResults(new Integer(params.max))
firstResult(new Integer(params.offset))
fetchMode('assignee', FM.EAGER)
fetchMode('project', FM.EAGER)

Document generated by Confluence on May 01, 2007 11:37 Page 209


order('priority', 'asc')
}

The code above has not been really tested, so if someone verifies it works for EAGER fetching, please
delete this text line here. (justo wrote this Querying with Eager Fetching section as someone in the
list suggested).

3) You can use hibernate .hbm files to mapp relations using lazy=false.

Document generated by Confluence on May 01, 2007 11:37 Page 210


GSP Reference

This page last changed on Mar 28, 2007 by wangjammer5.

GSP Reference

Example
Reference

• Variables available
• Page properties
• Invoking tags and passing attributes
• Inline Groovy script

Example

Reference

Variables available

There are a number of variables available to all pages. These are similar to those used in Java Server
Pages (JSP).

• application
• flash
• out
• params
• request
• response
• session

application

Since: the beginning

This refers to the servletContext, which can be useful for accessing attributes shared across the whole
application (not per-request).

Example:

Imagine you have set a versionNumber attribute on the servletContext in your ApplicationBootStap's
init() closure. You can then display this in any page:

Document generated by Confluence on May 01, 2007 11:37 Page 211


<div>
Application version ${application.getAttribute('versionNumber')}
</div>

flash

out

params

request

response

Document generated by Confluence on May 01, 2007 11:37 Page 212


Hibernate Integration

This page last changed on Mar 03, 2007 by yesudeep.

Hibernate integration

Mapping Domain Classes with Hibernate

If GORM (Grails Object Relational Mapping) is not flexible enough for your liking you can alternatively
map your domain class using Hibernate. To do this create a "hibernate.cfg.xml" file in the
"%PROJECT_HOME%\hibernate" directory of your project and the corresponding Hbm mapping xml file
for your domain class. For more info on how to do this read the documentation on mapping on the
Hibernate Website

This will allow you to map Grails domain classes onto a wider range of legacy systems and be more
flexible in the creation of your database schema.

Using Existing Hibernate Data Models

Grails also allows you to write your domain model in Java or re-use an existing domain model that has
been mapped using Hibernate. all you have to do is place the necessary "hibernate.cfg.xml" file and
corresponding mappings files in the "%PROJECT_HOME%\hibernate" directory.

You will still be able to call all of the dynamic persistent and query methods allowed in GORM!

Mapping with Hibernate Annotations

Grails also supports creating domain classes mapped with Hibernate's Java 5.0 Annotations support. To
do so you need to tell Grails that you are using an annotation configuration by setting the "configClass" in
your data source project as follows:

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration
class DevelopmentDataSource {
def configClass = GrailsAnnotationConfiguration.class
... // remaining properties
}

That's it for the configuration! Oh and make sure you have Java 5.0 installed as this is required to use
annotations. Now to create an annotated class we simply create a new Java class and use the annotations
defined as part of the EJB 3.0 spec (for more info on this see the Hibernate Annotations Docs:

package com.books;
@Entity
public class Book {
private Long id;

Document generated by Confluence on May 01, 2007 11:37 Page 213


private String title;
private String description;
private Date date;

@Id
@GeneratedValue
public Long getId() {
return id;
}

public void setId(Long id) {


this.id = id;
}

public String getTitle() {


return title;
}

public void setTitle(String title) {


this.title = title;
}

public String getDescription() {


return description;
}

public void setDescription(String description) {


this.description = description;
}
}

Once thats done we need to register the class with the Hibernate sessionFactory, to do so we add entries
to the "%PROJECT_HOME%/hibernate/hibernate.cfg.xml" file as follows:

<hibernate-configuration>
<session-factory>
<mapping package="com.books" />
<mapping class="com.books.Book" />
</session-factory>
</hibernate-configuration>

And that's it! When Grails loads it will register the necessary dynamic methods with the class! To see
what else you can do with a Hibernate domain class see the section on Scaffolding

Note when you generate views, or controllers you need to specify the entire package name ie
com.books.Book, currently (v 0.3) there are mistakes in the generated code. Specifically the static
methods need to be fully qualified (add the package name)

Using Grails Dynamic Methods in a Java-Hibernate Application

You can use Grails dynamic methods (for example, findBy*()) and properties for domain classes in an
application written in Java that uses Hibernate for object-relational mapping (ORM). Simply embed into
your application the Groovy scripts that harness Grails dynamic functionality, which results in short
readable scripts that query for data (DML operations currently do not work).

Add the following JAR files to your build path:

1. grails
2. groovy-all
3. spring
4. commons-lang

Document generated by Confluence on May 01, 2007 11:37 Page 214


5. commons-collections
6. servletapi
7. ognl

You can find these JAR files within your Grails installation directory--more specifically, the
<GRAILS_HOME>/lib and <GRAILS_HOME>/dist directories.

In your Java code:

import groovy.lang.Binding;
import groovy.util.GroovyScriptEngine;

import org.hibernate.SessionFactory;

import org.codehaus.groovy.grails.commons.DefaultGrailsApplication;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil;

To generate the dynamic methods do:

DefaultGrailsApplication defaultApplication;
SessionFactory sessionFactory;

defaultApplication = new DefaultGrailsApplication (new Class[] {}, null);


sessionFactory = HibernateUtil.getSessionFactory ();

GrailsHibernateUtil.configureDynamicMethods (sessionFactory, defaultApplication);

The HibernateUtil class manages a SessionFactory so that I have to create it only once. The source code
for this class is taken from the Hibernate documentation.

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil {


private static final SessionFactory sessionFactory;

static {
try {
// Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration ().configure ().buildSessionFactory ();
}
catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed.
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError (ex);
}
}

public static SessionFactory getSessionFactory () {


return sessionFactory;
}
}

Now you are ready to execute Groovy scripts that use the dynamic methods:

String[] scriptLocations;
GroovyScriptEngine engine;
Binding binding;

Document generated by Confluence on May 01, 2007 11:37 Page 215


scriptLocations = new String[] { "groovy" };
engine = new GroovyScriptEngine (scriptLocations);
binding = new Binding ();

// Create a variable named "input" with a value "hello" in the script


// binding.setVariable ("input", "hello");

try {
Object obj = engine.run ("Foobar.groovy", binding);
// ...

Foobar.groovy may look like this:

import foil.MillRoll
return MillRoll.list()

which would give you a List with all persisted "foil.MillRoll" Objects.

Using custom UserType

You can define custom user hibernate types to map database fields in non-standard ways.
For example, here's a custom UserType that maps a varchar2(1) field wich allows values of '0' and '1' tu
a boolean instead than String.

For example, you can create this class as ./src/groovy/persistence/OneZeroUserType.groovy:

package persistence;

import org.hibernate.*;
import org.hibernate.usertype.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.*;
import java.io.Serializable;

public class OneZeroUserType implements UserType


{
def SQL_TYPES = [Hibernate.STRING.sqlType()];

public int[] sqlTypes() {


return SQL_TYPES;
}

private Class targetClass;

public void setParameterValues(Properties parameters) {


String targetClassName = parameters.getProperty("targetClass");
try {
targetClass = Class.forName(targetClassName);
} catch (ClassNotFoundException e) {
throw new HibernateException("Class " + targetClassName + " not found ", e);
}
}

public Class returnedClass() {


return targetClass;
}

public boolean isMutable() { return false; }

public Object deepCopy(Object value) { return value; }

public Serializable disassemble(Object value)


{ return (Serializable) value; }

Document generated by Confluence on May 01, 2007 11:37 Page 216


public Object assemble(Serializable cached, Object owner)
{ return cached; }

public Object replace(Object original, Object target, Object owner)


{ return original; }

public boolean equals(Object x, Object y)


{
if (x == y) return true;
if (x == null || y == null) return false;
return x.equals(y);
}

public int hashCode(Object x)


{
return x.hashCode();
}

public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws


SQLException
{
String value = resultSet.getString(names[0]);
if ("1".equals(value))
return true;
else
return false;
}

public void nullSafeSet(PreparedStatement statement, Object value, int index) throws


HibernateException, SQLException
{
if (value == null)
{
statement.setNull(index, Hibernate.STRING.sqlType());
}
else
{
if((Boolean)value)
{
statement.setString(index, "1");
}
else
{
statement.setString(index, "0");
}
}
}
}

You can then use the new type in your .hbm.xml hibernate mapping file:

<property name="FOrdLun" type="persistence.OneZeroUserType">


<column name="F_ORD_LUN" length="1" />
</property>

Other Resources

• Tutorial - Many-to-Many Mapping with Hibernate XML


• Tutorial - Hosting Grails to Your Legacy DB - Step-by-step guide written by Jason Rudolph on how to
get Grails working with a legacy MySQL db using Hibernate XML
• Tutorial - Grails+EJB3 - Another excellent article by Jason Rudolph on how to use Grails with EJB
entity beans

Document generated by Confluence on May 01, 2007 11:37 Page 217


Many-to-Many Mapping with Hibernate XML

This page last changed on Nov 07, 2006 by graeme.rocher@gmail.com.

Tutorial: Many-to-Many mapping with Hibernate XML


(Author/Book)

Here is an example with a many-to-many relationship: an author can write several books and a book can
be written by several authors. The relationship will be managed from the author's side: a book can be
added or removed from the author's list of books.

From the book GSP pages it looks like an author can be added/removed from the book side, but in
reality, the author of the current book gets his/her book list updated. See the book controller for more
details. Following are the Hibernate files and domain class files for Author and Book, the data source
config file and some excerpts of the controllers.

The zip file contains all the files to build the example. The database used is mySQL and the
"\conf\DevelopmentDataSource.groovy" file set accordingly. Change it for your database, don't forget to
include the JBDC driver in your placing the driver jar file in the %PROJECT_HOME%\lib directory. In this
example: "%PROJECT_HOME%\lib\mysql-connector\mysql-connector-java-3.1.12-bin.jar". IMPORTANT:
The version of Grails used is 0.3-SNAPSHOT of 17-Oct-06.

%PROJECT_HOME%\hibernate\hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>


<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
<mapping resource="Book.hbm.xml"/>
<mapping resource="Author.hbm.xml"/>
</session-factory>
</hibernate-configuration>

%PROJECT_HOME%\hibernate\Author.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="Author" table="author">
<id name="id" column="id" unsaved-value="null">
<generator class="native"></generator>
</id>

<version name="version" column="version" type="java.lang.Long"/>


<property name="name" column="name" />

<set name="books" table="author_book" lazy="true" inverse="false">


<key>
<column name="author_id" not-null="true"/>
</key>
<many-to-many class="Book">

Document generated by Confluence on May 01, 2007 11:37 Page 218


<column name="book_id" not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>

%PROJECT_HOME%\hibernate\Book.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="Book" table="book">
<id name="id" column="id" unsaved-value="null">
<generator class="native"></generator>
</id>

<version name="version" column="version" type="java.lang.Long"/>


<property name="title" column="title"/>

<set name="authors" table="author_book" lazy="true" inverse="true">


<key>
<column name="book_id" not-null="true"/>
</key>
<many-to-many class="Author">
<column name="author_id" not-null="true"/>
</many-to-many>
</set>
</class>
</hibernate-mapping>

%PROJECT_HOME%\grails-app\conf\DevelopmentDataSource.groovy

class DevelopmentDataSource {
boolean pooling = true
String dbCreate = "create-drop"
String url = "jdbc:mysql://localhost/library"
String driverClassName = "com.mysql.jdbc.Driver"
String username = "root"
String password = ""
}

%PROJECT_HOME%\conf\ApplicationBootStrap.groovy

class ApplicationBootStrap {

Closure init =
{
def book
book = new Book(title: 'Moto')
book.save()
book = new Book(title: 'Auto')
book.save()
book = new Book(title: 'Cooking')
book.save()
book = new Book(title: 'Windsurfing')
book.save()

def java = new Book(title: 'Java')


java.save()

def author = new Author(name: 'Fred')


author.addBook(java)
author.save()
}

Document generated by Confluence on May 01, 2007 11:37 Page 219


}

%PROJECT_HOME%\grails-app\controllers\AuthorController.groovy

class AuthorController {
...
def edit = {
def author = Author.get( params.id )

if (!author) {
flash.message = "Author not found with id ${params.id}"
redirect(action:list)
}
else {
def availableBooks = Book.list(max:20,order:'asc')
def authorBooks = author.books
availableBooks = availableBooks - authorBooks;
return [author : author , availableBooks : availableBooks]
}
}

def addBook = {
def author = Author.get( params.id )
def book = Book.get(params.bookId)
author.addBook(book)
author.save()
redirect(action:'edit', params:[id:author.id])
}

def removeBook = {
def author = Author.get( params.id )
def book = Book.get(params.bookId)
author.books.remove(book)
author.save()
redirect(action:'edit', params:[id:author.id])
}
...
}

%PROJECT_HOME%\grails-app\controllers\BookController.groovy

class BookController {
...
def delete = {
def book = Book.get( params.id )
if (book) {
def authors = book.authors
// Removing the book from its authors' list
authors.each { author ->
println (">>>>>>>>>>>> removing book:" + book.title + " from author: " +
author.name)
author.books.remove(book)
author.save()
}
book.delete()
flash.message = "Book ${params.id} deleted."
redirect(action:list)
}
else {
flash.message = "Book not found with id ${params.id}"
redirect(action:list)
}
}

def edit = {
println (">>>>>>>>>>>>> editBook: " + params.id)
def book = Book.get( params.id )

if(!book) {
flash.message = "Book not found with id ${params.id}"

Document generated by Confluence on May 01, 2007 11:37 Page 220


redirect(action:list)
}
else {
def availableAuthors = Author.list(max:20,order:'asc')
def bookAuthors = book.authors
availableAuthors = availableAuthors - bookAuthors;
return [book : book , availableAuthors : availableAuthors]
}
}

def addAuthor = {
def bookId = params.id
def book = Book.get(bookId)
def author = Author.get(params.authorId)
println (">>>>>>>>>>>>> addAuthor: " + params['authorId'] + ' for book: ' + book.title)

// if the book is updated from here, all the other books for this author are removed
// book.addAuthor(author) // deletes the existing books for this author and adds this
book
// book.authors.add(author) // Doesn't work at all, no change to authors
/* if (!book.save())
{
book.errors.each {
println '>>>>>>>>>>>>>>>>>>>> Error saving book' + it
}
}
*/
// MUST DO this because inverse='true' in hbm.xml
author.addBook(book)
author.save()
redirect(action:'edit',id:bookId)
}

def removeAuthor = {
def bookId = params.id
def book = Book.get(bookId)
def author = Author.get(params.authorId)
println (">>>>>>>>>>>>> START removeAuthor: " + bookId + ' for author: ' + author.name)
author.books.remove(book)
println (">>>>>>>>>>>>> DONE removeAuthor: " + params.bookId + ' for author: ' +
author.name)
author.save()
redirect(action:'edit',id:bookId)
}
...
}

%PROJECT_HOME%\grails-app\views\author\edit.gsp

<!-- Author's books -->


<tr class='prop'>
<td valign='top' class='name'>
<label for='books'><nobr>Author's Books:</nobr></label>
</td>
<td valign='top' class='value ${hasErrors(bean:author,field:'books','errors')}'>
<ul>
<g:each var='b' in='${author?.books?}'>
<li>
${b.title}
<g:link controller='book' action='show' id='${b.id}'> (Show)</g:link>
<g:link controller='author'
params='["id":author?.id, "bookId":b.id]' action='removeBook'>
(Remove)
</g:link>
</li>
</g:each>
</ul>
</td>
</tr>
<!-- Available books -->
<tr class='prop'>
<td valign='top' class='name'>
<label for='books'><nobr>Available Books:</nobr></label>
</td>

Document generated by Confluence on May 01, 2007 11:37 Page 221


<td valign='top' class='value ${hasErrors(bean:author,field:'books','errors')}'>
<ul>
<g:each var='b' in='${availableBooks?}'>
<li>
${b.title}
<g:link controller='book' action='show' id='${b.id}'> (Show)</g:link>
<g:link controller='author'
params='["id":author?.id, "bookId":b.id]' action='addBook'>
(Add)
</g:link>
</li>
</g:each>
</ul>
</td>
</tr>

%PROJECT_HOME%\grails-app\views\book\edit.gsp

<!-- Book Author(s) -->


<tr class='prop'>
<td valign='top' class='name'>
Authors:
</td>
<td valign='top' class='value ${hasErrors(bean:book,field:'authors','errors')}'>
<ul>
<g:each var='a' in='${book?.authors?}'>
<li>
${a.name}
<g:link controller='author' action='show' id='${a.id}'> (Show)</g:link>
<g:link controller='book'
params='["id":book?.id, "authorId":a.id]'
action='removeAuthor'>
(Remove)
</g:link>
</li>
</g:each>
</ul>
</td>
</tr>

<!-- Available Authors -->


<tr class='prop'>
<td valign='top' class='name'>
<nobr>Other Authors:</nobr>
</td>
<td valign='top' class='value
${hasErrors(bean:book,field:'availableAuthors','errors')}'>
<ul>
<g:each var='a' in='${availableAuthors?}'>
<li>
${a.name}
<g:link controller='author' action='show' id='${a.id}'> (Show)</g:link>
<g:link controller='book'
params='["id":book?.id, "authorId":a.id]' action='addAuthor'>
(Add)
</g:link>
</li>
</g:each>
</ul>
</td>
</tr>

Download the example files:

AuthorBook.zip

Document generated by Confluence on May 01, 2007 11:37 Page 222


HTTP Method Restrictions

This page last changed on Nov 04, 2006 by brownj.

HTTP Method Restrictions

Introduction

Often a web application needs to impose restrictions on which HTTP request methods are allowed for
specific actions in the application. For example, initiating any action that destroys or modifies data using
an HTTP-GET is generally considered to be a bad idea.

Inspecting The Request Method

The request method may be inspected inside of a controller action and the application may respond
however is appropriate. The code below is a way to prevent the delete action from being invoked using
an HTTP-GET.

class PersonController {

def delete = {
if(request.method == 'GET') {
// redirect to the list action
redirect(action:list)
} else {
// the rest of the delete action goes here
}
}
}

Instead of redirecting to some other action the application may want to return a 403 (Forbidden Access)
error code like this:

class PersonController {

def delete = {
if(request.method == 'GET') {
response.sendError(403)
} else {
// the rest of the delete action goes here
}
}
}

A problem with inspecting the request method inside of the controller action is that this code ends up
being repeated in a lot of actions within a controller, in many controllers in an application and in many
applications. For specialized application specific handling of invalid requests this may make sense but for
the general case the Grails framework provides a simple declarative syntax to help with this problem.

Document generated by Confluence on May 01, 2007 11:37 Page 223


Declarative Syntax For Method Restrictions

As of version 0.3 Grails provides a simple declarative syntax to help limit access to controller actions
based on the HTTP request method. The optional allowedMethods property may be added to a controller
to let the framework know which HTTP methods are allowed for controller actions. By default, all request
methods are allowed for all controller actions. The allowedMethods property only needs to be defined if
the controller contains actions that need to be restricted to certain request methods.

The allowedMethods property should be assigned a value that is a Map. The keys in the map should be
the names of actions that need to be restricted. The value associated with each of those keys may be
either a String or a List of Strings. If the value is a String, that String represents the only request
method that may be used to invoke that action. If the value is a List of Strings the List represents all of
the request methods that may be used to invoke that action. If the specified restrictions are violated
then a 403 will be returned in the response.

Example:

class PersonController {

// action1 may be invoked via a POST


// action2 has no restrictions
// action3 may be invoked via a POST or DELETE
def allowedMethods = [action1:'POST',
action3:['POST', 'DELETE']]

def action1 = { ... }

def action2 = { ... }

def action3 = { ... }

Document generated by Confluence on May 01, 2007 11:37 Page 224


IDE Integration

This page last changed on Mar 03, 2007 by takamori.

IDE Integration

Eclipse Integration

Importing a Grails Project

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.

Don't use the root directory, or paths with spaces

There is a known issue that Grails will not run properly if you try to use the root directory of your
drive as your project, or paths with spaces.

Setting up Eclipse Environment Variables

You will need to create an Eclipse classpath variable called GRAILS_HOME that points to the location
where you installed Grails for the project to build successfullly by going to Windows -> Preferences... ->
Java -> Build path -> Classpath Variables -> New.

If you don't already have GRAILS_HOME as part of your standard environment, in order to run your
Grails project, you will need to establish that value in the Run dialog (Run...) under the Environment tab,
to the same value as above.

Also, if you are using JSP you will need to add your JDK's tools.jar library to your project classpath
otherwise jetty will display compilation errors. See this page for info:
http://nuin.blogspot.com/2005/05/launch-jetty-from-eclipse-solving.html

Groovy Eclipse plugin issues

If you are using the Eclipse Groovy plugin then make sure you disable the preference 'Groovy
Compiler Generating Class Files' (Eclipse -> Window -> Preferences -> Groovy Preferences)
before importing the Grails project. By default this option is enabled and generates class files for
your groovy files, and stores them in the basedir of your Grails project. When these class files are
generated, unexpected behaviour is encountered like not able to generate controllers and views
for you domain classes.

Document generated by Confluence on May 01, 2007 11:37 Page 225


Running a Grails application

Grails also automatically creates an Eclipse run configuration for you. To run the project you are in use
the "Run" dropdown to open the "Run" dialog then under "Java Applications" find the name of your
project select it and click "Run". The Grails application will load embedded inside Eclipse, any changes
made inside the Eclipse project can be auto-reloaded.

If you are getting exceptions like

org.mortbay.util.MultiException[java.io.FileNotFoundException: {yourpath}/web-app]
at org.mortbay.http.HttpServer.doStart(HttpServer.java:731)
at org.mortbay.util.Container.start(Container.java:72)
at grails.util.GrailsMain.main(GrailsMain.java:67)

then you need to do is run the ant target:

grails dev package

which will package up grails into the web-app directory in the same way as the "grails run-app" command
will. This is then used as the base for eclipse to execute.

Step Debugging with Eclipse

You can step debug a Grails application if you install the latest build of the Groovy Eclipse plug-in. What
you need to do is the following:

• Open up the Groovy file you want to debug (lets say a controller called BookController.groovy)
then set a break point on the line you want to stop at.
• Now debug the application in the same way as you did in the above section on "Running a Grails
application" except with the "Debug" menu.
• Load your browser and navigate to the action that calls the code.

Eclipse should then stop at the appropriate place and you can then inspect variables and step through the
code. If you have the Grails source code set-up on your Source path you can step into that code too.

Adding domain classes etc.

You can configure grails as an "External Tool", allowing you to create domain classes etc. from within
Eclipse:

1. Select "Run > External Tools > External Tools...".


2. Enter a name of "Grails".
3. Browse the file system for the location of grails or grails.bat.
4. Set the working directory to "${project_loc}".
5. Set the arguments as "${string_prompt}".
6. Under the "Refresh" tab, set to refresh the "project containing the selected resource" upon
completion.
7. Under the "Common" tab, tick "Display in favorites menu".

Document generated by Confluence on May 01, 2007 11:37 Page 226


You can then run Grails by clicking the down arrow next to the external tool icon (run with a suitcase)
and selecting "Grails", for example:

1. Choose "Grails" from the external tools drop-down.


2. Enter "create-domain-class" in the dialogue box.
3. In the console window, follow the prompts as normal.
4. Open your new class from grails-app/domain.

Editing GSP files

The gsp files are just jsp files with a special taglib. The extension gsp has to be added as follows:

• General -> Editors -> File Associations: add *.gsp and link the JSP Editor to it.
• General -> Content Types Fold out Text -> JSP and add *.gsp

This enables jsp editing for the gsp files. To use the taglib add the following at the start of the gsp:

<%@ taglib prefix="g" uri="http://grails.codehaus.org/tags" %>

Troubleshooting

1. If you getting the following error every time you save *.groovy file in your project:

An internal error occurred during: "Building workspace".


BUG! exception in phase 'conversion' in source unit '...' Error:
duplicate class declaration for name: ... and class:
org.codehaus.groovy.ast.ClassNode@...[name:...]

try the following:

•Right click on package explorer's project name and open "Properties..." dialog.
•Select "Builders" and make sure that "Groovy Builder" is checked.
•Select "Java Compiler/Building" and check "Enable project specific settings".
•Append "*.groovy" to "Filtered Resources" text field, to prevent ".groovy" files being
copied to the output directory. Note that the path separator is "," not ";"
• Apply changes and close dialog.
• Clean your project. Make sure that the output directory doesn't contain "*.groovy" files
2. If Eclipse complains that it can not find the sources where breakpoints are set ensure the following:
• Step filtering is enabled for groovy.*, org.codehaus.* (more about this
http://groovy.codehaus.org/Debugging+with+Eclipse )
• Build out put for the project is in a separate folder (say /bin ). Make sure this is present for
Project->Properties->Groovy Project Properties
3. Few other recommendations:
• Make sure to add all the libraries from grails-app/lib folder to the project
• Using verbose logging/tracing through log4j.properties until everything works from the Eclipse
IDE. Sometimes if some library is not found, unless it is printed in the console, it is difficult to
find out what went wrong.
• Make sure to use the same JDK for tools.jar as well as the runtime jar rt.jar. Do note
sometimes using the JRE instead of rt.jar causes problems.
• Sometimes "launch configuration" generated by grails is not in sync with the way ant's

Document generated by Confluence on May 01, 2007 11:37 Page 227


build.xml works. In Grails 0.3 ensure that following VM parameters (do note not program
arguments, but VM arguments ) are set "-Dorg.mortbay.xml.XmlParser.NotValidating=true".
Without this there will be XML Parser exception thrown when launched from the IDE.

Brute Force method:

If running from IDE has issues, most likely it is because some library is missing. Ensure that all libraries
under GRAILS_HOME/dist, GRAILS_HOME/ant/lib, GRAILS_HOME/lib and your project folder/lib are
added to the build path of the project.

Document generated by Confluence on May 01, 2007 11:37 Page 228


Installation

This page last changed on Jan 04, 2007 by pbarry.

Installation from Download

Prerequisites

In order to start using Grails you need to have the following:

• An installation of Java SDK 1.4 or higher and have set your JAVA_HOME variable to the SDK install
location

Steps

• Download the latest Grails release


• Extract the archive into an appropriate location
• Create a GRAILS_HOME environment variable that points to the path where you extracted the
archive (eg C:\grails on Windows or ~/grails on Unix)
• Append a reference to the "bin" directory within the Grails directory to your PATH variable (eg
%GRAILS_HOME%\bin on Windows or $GRAILS_HOME/bin on Unix)
• Type "grails" at the command line, if a help message is displayed you are ready to start using
Grails!

Installation from Subversion

Prerequisites

In order to start using Grails from SVN you need to have the following:

• An installation of Java 1.4 or higher and have set your JAVA_HOME variable to the install location
• A working installation of Apache Ant 1.6.5 or higher
• JUnit (to run the build tests - put junit.jar in your ANT_HOME\lib directory)
• An installation of Subversion

Steps

• Checkout Grails from the SVN repository


° Run this command: svn co http://svn.codehaus.org/grails/trunk/grails/
• Set the GRAILS_HOME environment variable to the checkout location
• Add the "%GRAILS_HOME%\bin" directory to your PATH environment variable
• Go to the %GRAILS_HOME% directory and type "ant" to build Grails
• That's it! Start developing in Grails!

Document generated by Confluence on May 01, 2007 11:37 Page 229


Document generated by Confluence on May 01, 2007 11:37 Page 230
Introduction

This page last changed on Apr 18, 2006 by jdmwood.

Introduction

Welcome to the Grails documentation, this documentation is as up-to-date as possible, but if you find any
inconsistency or gaps in the documentation please don't hesitate to report it to the Mailing Lists or update
it yourself via the Wiki.

The Background

The rise of Ruby on Rails has signified a huge shift in how we build web applications today, it is a
fantastic framework with a growing community. There is, however, space for another such framework
that integrates seamlessly with Java. Thousands of companies have invested in Java and these same
companies are losing out on the benefits of a Rails-like framework. Enter Grails.

The Elevator Pitch

Grails is not just a Rails clone, it aims to provide a Rails-like environment that is more familiar to Java
developers and that uses idioms that Java developers are more familiar with making the adjustment in
mentality to a dynamic framework less of a jump. The concepts within Grails like interceptors, tag libs,
Groovy Server Pages (GSP) make those in the Java community feel right at home.

The Additional Power

Grails' foundation on solid Open Source technologies such as Spring, Hibernate and SiteMesh give it even
more potential in the Java space with Spring providing powerful inversion of control and MVC, Hibernate -
stable and mature object relational mapping technology with the ability to integrate with legacy systems
and SiteMesh - flexible layout control and page decoration.

Grails complements these with additional features taking advantage of the coding by convention
paradigm such as:

• Dynamic Tag Libraries


• Grails Object Relational Mapping
• Groovy Server Pages
• Scaffolding

To get started now Download Grails, Install it and Try it!

Document generated by Confluence on May 01, 2007 11:37 Page 231


Job Scheduling (Quartz)

This page last changed on Mar 22, 2007 by lataupe.

Scheduling Jobs

Overview

Grails allows you to schedule jobs to be executed using a specified interval or cron expression. The
underlying system uses the Quartz Enterprise Job Scheduler configured via Spring, but is made simpler
by the coding by convention paradigm.

Scheduling Jobs

To create a new job run the "grails create-job" command and enter the name of the job. Grails will create
a new job and place it in the "grails-app/jobs" directory:

class MyJob {
def startDelay = 60000
def timeout = 1000

def group = "MyGroup"

def execute(){
print "Job run!"
}
}

The above example will wait for 1 minute and after that will call the 'execute' method every second. The
'timeout' and 'startDelay' properties are specified in milliseconds and must have Integer or Long type. If
these properties are not specified default values are applied (1 minute for 'timeout' property and 30
seconds for 'startDelay' property). It isn't recommended to set 'startDelay' property value lesser than 30
seconds since your application needs to fully startup before executing jobs. Jobs can optionally be placed
in different groups.

Important: in earlier versions of Grails (before 0.5) 'startDelay' and 'timeout' properties must be defined
as Strings and default values are 1 minute for 'timeout' and 0 seconds for 'startDelay'

Scheduling a Cron Job

Jobs can be scheduled using a cron expression. For those unfamiliar with "cron", this means being able to
create a firing schedule such as: "At 8:00am every Monday through Friday" or "At 1:30am every last
Friday of the month". (See the API docs for the CronTrigger class in Quartz for more info on cron
expressions):

class MyJob {
def cronExpression = "0 0 6 * * ?"

Document generated by Confluence on May 01, 2007 11:37 Page 232


def group = "MyGroup"

def execute(){
print "Job run!"
}
}

Dependency Injection and Jobs

Jobs are configured for auto-wiring by name thus properties can be injected into them. To get hold of the
data source you can do:

def javax.sql.DataSource dataSource

Or a service class:

def MyService myService

The Grails application context is configured using convention so most types can be injected simply by
using their property name representation (ie the first letter being lower case in the majority of cases).

Hibernate Sessions and Jobs

(Since 0.5) Jobs are configured by default to have Hibernate Session bounded to thread each time job is
executed. This is required if you are using Hibernate code which requires open session (such as lazy
loading of collections) or working with domain objects with unique persistent constraint (it uses Hibernate
Session behind the scene). If you want to override this behavior (rarely useful) you can use
'sessionRequired' property:

def sessionRequired = false

Document generated by Confluence on May 01, 2007 11:37 Page 233


Logging

This page last changed on Feb 28, 2007 by wangjammer5.

Configuring Logging

Grails uses Apache Commons Logging, defaulting to Log4J for the log output and configuration.

To configure Log4j open the "web-app/WEB-INF/log4j.environment.properties" file and configure it to log


the required output. Where environment is the mode your are using. For example if you are in
development mode the file will be called log4j.development.properties. It will be copied to
"tmp/war/WEB-INF/log4j.properties". The default is to copy the log4j.properties file out of the grails
home/src/war/WEB-INF/log4j.properties. If you don't provide a log4j.environment.properties mode for
the environment you are running in, this file will be used.

It is worthwhile reading the Log4j docs to understand how to setup logging.

Artefact logs (Since 0.5)

All application artefacts have a dynamically added "log" property. This includes Domain classes,
Controllers, Taglibs, Jobs, Services, Bootstraps, Datasources etc.

Logs are named using the convention "grails.app.<artefactType>.ClassName" i.e:

# 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 artefact type IDs come from the registered artefact handlers. At the time of writing, out of the box
these are:

• bootstrap
• dataSource
• tagLib
• service
• controller
• task
• domain

Document generated by Confluence on May 01, 2007 11:37 Page 234


Per-controller logs (Since 0.4)

Within controllers you can use the "log" property supplied by Grails to log using standard commons
logging methods. You can configure the logging of each controller individually by editing log4j.properties
as follows:

log4j.logger.YourController=debug, stdout
log4j.additivity.YourController=false&nbsp;

Where YourController is the name of your controller class.

The log naming has changed in 0.5 see previous section

Log4j Hibernate Output

To log all SQL queries and all the stuff hibernate does, add the line

log4j.logger.org.hibernate=debug, stdout

To the log4j.environment.properties file in:

web-app/WEB-INF

Document generated by Confluence on May 01, 2007 11:37 Page 235


Scaffolding

This page last changed on Dec 01, 2006 by toddbittner@gmail.com.

Scaffolding

What is Scaffolding?

Scaffolding allows you to auto-generate a whole application for a given domain class including:

• The necessary views


• Controller actions for create/read/update/delete (CRUD) operations

Enabling Scaffolding

The simplest way to get started with scaffolding is to enable scaffolding via the "scaffold" property. For
the "Book" domain class, you need to set the "scaffold" property on a controller to true:

class BookController {
def scaffold = true
}

The above works because the "BookController" follows the same naming convention as the "Book"
domain class, if we wanted to scaffold a specific domain class you can reference the class directly in the
scaffold property:

def scaffold = Author.class

And thats it! If you run this grails application the necessary actions and views will be auto-generated at
runtime. The following actions are dynamically implemented by default by the runtime scaffolding
mechanism:

• list
• show
• edit
• delete
• create
• save
• update

An interface like the one demonstrated in the screenshots below will be generated automatically:

Document generated by Confluence on May 01, 2007 11:37 Page 236


If you prefer to keep your domain model in Java and mapped with Hibernate you can still use scaffolding,
simply import the necessary class and set the scaffold property to it.

Dynamic Scaffolding

Because Grails does not use code templates to achieve this you can add your own actions to the
scaffolded controller that interact with the scaffolded actions. For example, in the below example,
changeAuthor redirects to the show action:

class BookController {
def scaffold = Book.class

def changeAuthor = {
def b = Book.get( params["id"] )
b.author = Author.get( params["author.id"] )
b.save()

// redirect to a scaffolded action


redirect(action:show)
}
}

You can also override the scaffolded actions with your own actions if necessary:

class BookController {
def scaffold = Book.class

// overrides scaffolded action to return both authors and books


def list = {
[ "books" : Book.list(), "authors": Author.list() ]
}
}

Generating Controllers & Views

The above scaffolding features are useful but in real world situations its likely that you will want to
customize the logic and views. Grails allows you to generate a controller and the views used to create the
above interface via the command line. To generate a controller type:

Document generated by Confluence on May 01, 2007 11:37 Page 237


grails generate-controller

Or to generate the views type:

grails generate-views

Or to generate everything type:

grails generate-all

All these commands will prompt you for the name of the domain class to generate to various artifacts for
the specified domain class. You can even generate a controller and views for a domain class that is
written in Java and mapped with Hibernate!

Customising the Generated views

The views that Grails generates have some form of intelligence in that they adapt to the Validation
constraints. For example you can change the order that fields appear in the views simply by re-ordering
the constraints in the builder:

def constraints = {
title()
releaseDate()
}

You can also get the generator to generate lists instead of text inputs if you use the "inList" constraint:

def constraints = {
title()
category(inList:["Fiction", "Non-fiction", "Biography"])
releaseDate()
}

Or if you use the range constraint on a number:

def constraints = {
age(range:18..65)
}

Restricting the length via a constraint also effects how many characters can be entered in the generated
view:

def constraints = {
name(length:0..30)
}

And you can change an input field to be a text area by using the "widget" constraint:

Document generated by Confluence on May 01, 2007 11:37 Page 238


def constraints = {
description(widget:'textarea')
}

Java Integration

If your domain model is written in Java and mapped with Hibernate you can still take advantage of Grails'
scaffolding mechanism. For the purpose of this documentation it is assumed you have read how Grails'
Hibernate integration works in the section on GORM, needless to say to scaffold a hibernate domain class
simply reference the domain class in the controller:

import com.books.HibernateBook
class BookController {
def scaffold = HibernateBook.class
}

If you want to generate the controller and views for a Hibernate domain class you can still do so, but
make sure you type the full package and class name.

To integrate with the Grails constraints mechanism and hence hook into useful things like the way the
views are generated and Grails' Validation mechanism you can do so by creating a Groovy script following
the naming convention of your domain class and ending in the "Constraints" suffix. For example for the
"HibernateBook" class defined above you would need to create a
"com/books/HibernateBookConstraints.groovy" script in the same package is the class itself. Within the
script just define constraints in the same way as you would do in a GORM class but without the def or
static keywords before the name:

constraints = {
title(length:5..15)
desc(blank:false)
}

Document generated by Confluence on May 01, 2007 11:37 Page 239


Scripting events

This page last changed on Apr 30, 2007 by brownj.

Scripting events

As of v0.5 there is now the ability to hook into scripting events. These are events triggered during
execution of Grails target and plugin scripts.

For example, you can hook into status update output (i.e. "Tests passed", "Server running") and the
creation of files or artefacts.

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 a script called Events.groovy either in the scripts/ folder of a plugin, or in
your .grails/scripts/ folder in your user home directory. All events scripts are called whenever an event
occurs, so you can have 10 plugins handling events and also a custom per-user script.

Event handlers are closures defined in Events.groovy, with a name beginning with "event". The following
example can be put in your <home>/.grails/home and will use the Mac OS X "Growl" application to pop
up notifications of script status (you need to install the growlnotify extras from the Growl's .dmg):

Ant = new AntBuilder()

eventCreatedArtefact = { type, name ->


growlNotify("Created $type $name")
}

eventStatusUpdate = { msg ->


growlNotify(msg)
}

eventStatusFinal = { msg ->


growlNotify(msg)
}

void growlNotify(String message) {


Ant.exec(executable:'growlnotify') {
arg(value:'-n')
arg(value:'Grails')
arg(value:'-m')
arg(value:message)
}
}

You can see here the three handlers eventCreatedArtefact, eventStatusUpdate, eventStatusFinal.
Currently Grails scripting will generate the following events:

Not all the scripts have been updated in SVN head so not all of these occur, and some only occur

Document generated by Confluence on May 01, 2007 11:37 Page 240


for certain targets.

Event Parameters Description

StatusUpdate message Passed a string indicating current


script status/progress

StatusError message Passed a string indicating an


error message from the current
script

StatusFinal message Passed a string indicating the


final script status message, i.e.
when completing a target, even
if the target does not exit the
scripting environment

CreatedArtefact artefactType,artefactName Called when a create-xxxx script


has completed and created an
artefact

CreatedFile fileName Called whenever a project source


filed is created, not including
files constantly managed by
Grails

PluginInstalled pluginName Called after a plugin has been


installed (NOT IMPLEMENTED
YET)

Exiting returnCode Called when the scripting


environment is about to exit
cleanly

Triggering events

If you are writing a custom script for a plugin you should ensure that you follow existing conventions for
event generation, and add any new useful events relating to your plugin.

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!"])

Document generated by Confluence on May 01, 2007 11:37 Page 241


Security

This page last changed on Apr 04, 2007 by jnicho02.

The following is raw text and requires further editing and adding to....

Securing your application

Making it simple to build a secure webapp out-of-the-box is one of the key criteria for adoption of the
Grails platform......although i'd have trouble telling you the exact definition of 'secure' other than it's
enough so that a Developer/Architect could allay any questions/fears from Management.

Grails is no more or less secure than Java Servlets. We can add more to reduce the risk of mistakes, but
ultimately the core problem is developer awareness.

What are the most common web security problems?

SQL injection

Hibernate automatically escapes data when committing to database, but avoid writing bad dynamic HQL
code that uses unchecked request params

Phishing

Phishing is mainly a company policy issue.

HTML/JS cross-site scripting injection

HTML/URL injection

HTML/URL injection is easily handled with the codecs introduced in Grails 0.4, and the taglib fixes to use
encodeAsURL where appropriate.

Document generated by Confluence on May 01, 2007 11:37 Page 242


Services

This page last changed on Apr 03, 2007 by jnicho02.

Services

Grails Services

A service is a class that holds one or more methods that implement business logic. Logical parts of the
business logic are contained in separate service classes. Services are demarcated by transactions to
make units of work atomic on the persistence level. When certain types of exceptions are thrown
transactions are rolled back.

Services need to be registered with the middle tier and also need transactional configuration next to the
configuration of optional AOP services.

Services are application-scoped, which means it is not a good idea to use instance variables because they
can and will be modified concurrently (at the same time).

Coding conventions for services

Service class names should start with the name of the service and end with "Service". A country service
would thus be called "CountryService".

By default transaction demarcation is enabled for all services, meaning that by default all methods of a
service are wrapped in a transaction. Transaction demarcation can be disabled for specific services by
creating a "transactional" property and setting is to false:

class CountryService {
boolean transactional = false
}

Access to service methods is not synchronised, so nothing prevents concurrent execution of those
functions.
In fact, because the service is a singleton and may be used concurrently, you should be very careful
about storing state in a service. Or take the easy (and better) road and never store state in a service.

Dependency Injection

Other services can be injected into a service by creating corresponding properties. To inject the
CountryService create a "countryService" property.

CountryService countryService

Document generated by Confluence on May 01, 2007 11:37 Page 243


A javax.sql.DataSource instance can be retrieved for the configured database by adding the property:

javax.sql.DataSource dataSource

This could be used in conjunction with Spring's JdbcTemplate to perform direct transactional SQL
operations or with Groovy Sql

Accessing Services

From a controller

In a typical multitier scenario you can easily access services using dependency injection, for example
from a controller:

class CountryService {
def String sayHello(String name) {
return "hello ${name}"
}
}

class GreetingController {
CountryService countryService
def helloAction = {
render(countryService.sayHello(params.name))
}
}

That's all, you can test it by typing this URL


http://myserver:8080/myapp/greeting/helloAction?name=Falken in your browser location bar. A page
containing "hello Falken" will be returned. See Grails controllers for more details about controllers, e.g.
changing to access services by type rather than by name.

From a servlet

Alternatively, you can access services from other places of your web application (like servlets) if you need
it. Service objects are beans which can be retrieved from the Spring Bean Factory. You can proceed this
way:

Implement a java interface containing the service method definitions which you want to be available, for
example:

package serviceinterfaces;

public interface CountryServiceInt {


public String sayHello(String name);
}

Save it in your "<..>/myapp/src/java/serviceinterfaces" directory

Modify the CountryService groovy class for implementing the CountryServiceInt interface:

class CountryService implements serviceinterfaces.CountryServiceInt {

def String sayHello(String name) {

Document generated by Confluence on May 01, 2007 11:37 Page 244


return "hello ${name}"
}
}

For accessing the service from a servlet you can do this:

ApplicationContext ctx = (ApplicationContext)


request.getSession().getServletContext().getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT);
CountryServiceInt service = (CountryServiceInt) ctx.getBean("countryService");
String str = service.sayHello(request.getParameter.("name"));
//do something with str

Document generated by Confluence on May 01, 2007 11:37 Page 245


Spring Integration

This page last changed on Oct 26, 2006 by kgkiran.

Spring Integration

Beans can be configured to auto-wiring into Grails components by adding entries into the
"%PROJECT_HOME%\spring\resources.xml" file of your Grails application. Controllers by default use
auto-wiring by name so a bean defined as follows

<bean id="myBean" class="MyBeanImpl"></bean>

can be injected into a Grails controller by specifing a corresponding property name:

class SomeController {

def myBean
//.....
}

Grails service classes support injection by type or name, defaulting to type:

class SomeService {
MyBean myBean

def serviceMethod() {
myBean.invoke()
}
}

Also JNDI DataSources can be set up with a bean id "dataSource". More details under Configuration page.

Document generated by Confluence on May 01, 2007 11:37 Page 246


The Plug-in Developers Guide

This page last changed on Apr 16, 2007 by wangjammer5.

The Plug-in Developers Guide

This page forms a guide to developers wishing to develop plugins for Grails. Since 0.4, Grails provides a
number of extension points that allow you to extend anything from the command line interface to the
runtime configuration engine. The following sections detail how to go about it:

• Creating, Distributing and Installing Plugins


• Understanding a Plugin's structure
• Adding Basic artifacts (Controllers, Scripts etc.)
• Hooking into build script events
• Hooking into Runtime Configuration
• Adding Dynamic Methods at runtime
• Participating in Auto Reload Events
• Understanding Plugin Dependencies and Load order
• Adding new Artefact types
• User contributed Plugins

See also the list of available Plugins for non-trivial examples.

Document generated by Confluence on May 01, 2007 11:37 Page 247


Auto Reloading Plugins

This page last changed on Feb 28, 2007 by graemerocher@yahoo.co.uk.

Handling Auto Reload Events with Plugins

Monitoring Resources for Changes

Often it is valuable to monitor resources for changes and then reload those changes when they occur.
This is how Grails implements advanced reloading of application state at runtime. For example, consider
the below simplified snippet from the ServicesPlugin that Grails comes with:

class ServicesGrailsPlugin {
...
def watchedResources = "file:./grails-app/services/*Service.groovy"

...
def onChange = { event ->
if(event.source) {
def serviceClass = application.addServiceClass(event.source)
def serviceName = "${serviceClass.propertyName}"
def beans = beans {
"$serviceName"(serviceClass.getClazz()) { bean ->
bean.autowire = true
}
if(event.ctx) {
event.ctx.registerBeanDefinition(serviceName,
beans.getBeanDefinition(serviceName))
}
}
}
}

Firstly it defines a set of watchedResources as either a String or a List of strings that contain either the
references or patterns of the resources to watch. If the watched resources is a Groovy file, when it is
changed it will automatically be reloaded and passed into the onChange closure inside the event object.

The event object defines a number of useful properties:

• event.source - The source of the event which is either the reloaded class or a Spring Resource
• event.ctx - The Spring ApplicationContext instance
• event.plugin - The plugin object that manages the resource (Usually this)
• event.application - The GrailsApplication instance

From these objects you can evaluate the conventions and then apply the appropriate changes to the
ApplicationContext and so forth based on the conventions, etc. In the "Services" example above, a new
services bean is re-registered with the ApplicationContext when one of the service classes changes.

Influencing Other Plugins

As well as being able to react to changes that occur when a plugin changes, sometimes one plugin needs
to "influence" another plugin.

Document generated by Confluence on May 01, 2007 11:37 Page 248


Take for example the Services & Controllers plugins. When a service is reloaded, unless you reload the
controllers too, problems will occur when you try to auto-wire the reloaded service into an older controller
Class.

To get round this, you can specify which plugins another plugin "influences". What this means is that
when one plugin detects a change, it will reload itself and then reload all influenced plugins. See this
snippet from the ServicesGrailsPlugin:

def influences = ['controllers']

Observing other plugins

If there is a particular plugin that you would like to observe for changes but not necessary watch the
resources that it monitors you can use the "observe" property:

def observe = ["hibernate"]

In this case when a Hibernate domain class is changed you will also receive the event chained from the
hibernate plugin

Document generated by Confluence on May 01, 2007 11:37 Page 249


Contribute a Plugin

This page last changed on Feb 06, 2007 by wangjammer5.

Contribute a Plugin

As of Grails 0.4, Grails provides an extensible plugin architecture for developing plugins that extend
Grails' capabilities in whatever way you choose. Checkout The Plug-in Developers Guide for more info on
how to develop plugins.

If you decide to make the jump and develop a plugin Codehaus provides a number of services to Grails
plugin developers including:

1. The Grails plugins JIRA issue tracker


2. A shared SVN repository for Grails plugins

Also Grails plugins hosted at Codehaus can be installed with the command:

grails xfire 0.4

This feature (the plugin repository) is not yet functioning, coming soon for 0.5

And retrieved with the grails list-plugins target. Every time a release of a Grails is made the plugins
hosted at Codehaus will be built and placed within http://dist.codehaus.org/grails-plugins

Please post your ideas on the Mailing lists if you are interested in developing a plugin

Document generated by Confluence on May 01, 2007 11:37 Page 250


Creating Plugins

This page last changed on Feb 28, 2007 by graemerocher@yahoo.co.uk.

Creating, Distributing & Installing

Creating a Plugin

You can create a Grails plugin by running the command:

grails create-plugin [PLUGIN NAME]

This will create a plugin project for the name you specify. Say for example grails create-plugin
example would create a new plugin project called example. The structure of a Grails plugin is exactly the
same as a regular Grails project's directory structure, except that in the root of the plugin directory you
will find a plugin Groovy file. Following our example plugin it will look something like:

class ExampleGrailsPlugin {
def version = 0.1

...
}

All plugins must have this class in the root of their directory structure to be valid. The plugin class defines
the version of the plugin and optionally various hooks into plugin extension points (covered shortly).

In fact, not only is the structure the same, but a plugin is a Grails application so you can just type
grails run-app from the root of the plugin directory to execute a Grails plugin as a Grails app.

Installing & Distributing Plugins

To distribute the example plugin you need to navigate to its root directory using cd example and then
type:

grails package-plugin

This will create a zip file of the plugin starting with "grails" then the plugin name and version. For
example in the above case this would be grails-example-0.1.zip.

Once you have a plugin distribution file you can navigate to a Grails project and type:

grails install-plugin /path/to/plugin/grails-example-0.1.zip

If the plugin was hosted on a remote HTTP server you can also do:

Document generated by Confluence on May 01, 2007 11:37 Page 251


grails install-plugin http://myserver.com/plugins/grails-example-0.1.zip

Also for Grails plugins that are distributed at http://dist.codehaus.org/grails/plugins you can do:

grails install-plugin example 0.1

Document generated by Confluence on May 01, 2007 11:37 Page 252


Plugin Basics

This page last changed on Dec 05, 2006 by graeme.rocher@gmail.com.

Plugin Basics

Adding a new Script

A plugin can add a new script simply by providing the relevant Gant script within the scripts directory of
the plugin:

+ MyPlugin.groovy
+ scripts <-- additional scripts here
+ grails-app
+ controllers
+ services
+ etc.
+ lib

Adding a new Controller, Tag Library or Service

A plugin can add a new controller, taglib, service etc. by simply creating the relevant file within the
grails-app tree. Note that when the plugin is installed it will be loaded from where it is installed and not
copied into the main dir tree.

+ ExamplePlugin.groovy
+ scripts
+ grails-app
+ controllers <-- additional controllers here
+ services <-- additional services here
+ etc. <-- additional XXX here
+ lib

Document generated by Confluence on May 01, 2007 11:37 Page 253


Plugin Dependencies

This page last changed on Dec 05, 2006 by jason@jasonrudolph.com.

Plugin Dependencies

Understanding Plugin Dependencies and Load order

Plugins often depend on the presence of other plugins and can also adapt depending on the presence of
others. To cover this, a plugin can define two properties. The first is called dependsOn. For example, take
a look at this snippet from the Grails Hibernate plugin:

class HibernateGrailsPlugin {

def version = 1.0


def dependsOn = [dataSource:1.0,
domainClass:1.0,
i18n:1.0,
core: 1.0]

As the above example demonstrates the Hibernate plugin is dependent on the presence of 4 plugins: The
dataSource plugin (DataSourceGrailsPlugin), The domainClass plugin (DomainClassGrailsPlugin), the i18n
plugin and the core plugin.

Essentially the dependencies will be loaded first and then the Hibernate plugin. If all dependencies do not
load, then the plugin will not load.

However, this is a "hard" dependency in that if the dependency is not resolved, the plugin will give up
and won't load. It is possible though to have a "weaker" dependency using the loadAfter property:

def loadAfter = ['controllers']

Here the plugin will be loaded after the "controllers" plugin if it exists, otherwise it will just be loaded. The
plugin can then adapt to the presence of the other plugin, for example the Hibernate plugin has this code
in the doWithSpring closure:

if(manager?.hasGrailsPlugin("controllers")) {
openSessionInViewInterceptor(OpenSessionInViewInterceptor) {
flushMode = HibernateAccessor.FLUSH_AUTO
sessionFactory = sessionFactory
}
grailsUrlHandlerMapping.interceptors << openSessionInViewInterceptor
}

Here the Hibernate plugin will only register an OpenSessionInViewInterceptor if the "controllers" plugin
has been loaded.

Document generated by Confluence on May 01, 2007 11:37 Page 254


Interacting with the GrailsPluginManager

The previous snippet presented an example of how to interact with the PluginManager. The manager
variable is an instance of the GrailsPluginManager interface and it provides methods to interact with other
plugins and the PluginManager itself from any plugin.

Document generated by Confluence on May 01, 2007 11:37 Page 255


Plugin Dynamic Methods

This page last changed on Feb 28, 2007 by graemerocher@yahoo.co.uk.

Adding dynamic methods at runtime

The Basics

Grails plugins allow you to register dynamic methods with any Grails managed or other class at runtime.
New methods can only be added within a doWithDynamicMethods closure of a plugin. After which no new
methods can be added. This is to ensure thread safety when using dynamic methods.

For Grails managed classes like controllers, tag libraries and so forth you can add methods, constructors
etc. using the ExpandoMetaClass mechanism by accessing each controller's MetaClass:

class MyPlugin {

def doWithDynamicMethods = { applicationContext ->

application.controllers.metaClass.each { metaClass ->


metaClass.myNewMethod = {-> println "hello world" }
}
}
}

For other classes you can use the special "metaClass" property of each java.lang.Class. :

To do this your plugin MUST depend on the core Grails plugin: static dependsOn = [core:0.4]
as this plugin sets up the "metaClass" property on java.lang.Class

class MyPlugin {

def doWithDynamicMethods = { applicationContext ->


String.metaClass.swapCase = {->
def sb = new StringBuffer()
delegate.each {
sb << (Character.isUpperCase(it as char) ?
Character.toLowerCase(it as char) :
Character.toUpperCase(it as char))
}
sb.toString()
}

assert "UpAndDown" == "uPaNDdOWN".swapCase()


}
}

Interacting with the ApplicationContext

The doWithDynamicMethods closure gets passed the Spring ApplicationContext instance. This is useful as
it allows you to interact with objects within it. For example if you where implementing a method to
interact with Hibernate you could use the SessionFactory instance in combination with a

Document generated by Confluence on May 01, 2007 11:37 Page 256


HibernateTemplate:

To use the Hibernate plugin your plugin MUST depend on the hibernate Grails plugin: static
dependsOn = [hibernate:0.4] as this plugin sets up the SessionFactory and Hibernate
dependencies

import org.springframework.orm.hibernate3.HibernateTemplate

class MyHibernatePlugin {

def doWithDynamicMethods = { applicationContext ->

application.domainClasses.metaClass.each { metaClass ->

metaClass.myNewPersistentMethod = { ->

def sf = applicationContext.sessionFactory
def ht = new HibernateTemplate(sf)

// do something with HibernateTemplate


}
}
}
}

Also because of the autowiring and dependency injection capability of the Spring container you can
implement more powerful dynamic constructors that use the application context to wire dependencies
into your object at runtime:

class MyConstructorPlugin {

def doWithDynamicMethods = { applicationContext ->

application.domainClasses.each { domainClass ->

domainClass.metaClass.ctor = {->
return applicationContext.getBean(domainClass.name)
}
}

}
}

Document generated by Confluence on May 01, 2007 11:37 Page 257


ExpandoMetaClass

This page last changed on Feb 06, 2007 by graemerocher@yahoo.co.uk.

The Grails ExpandoMetaClass

Grails contains a special MetaClass called an ExpandoMetaClass that allows you to dynamically add
methods, constructors, properties and static methods using a neat closure syntax. ExpandoMetaClass
also has an even more dynamic cousin: DynamicMethodsExpandoMetaClass

At a basic level the ExpandoMetaClass can be created simply by passing in the desired class:

def metaClass = new ExpandoMetaClass(myClass)

However, this will not place the ExpandoMetaClass in the registry and hence is only useful for
per-instance MetaClasses. If you want the ExpandoMetaClass to be shared and available VM wide you
need to do:

def metaClass = new ExpandoMetaClass(myClass, true)

The second boolean argument indicates to the ExpandoMetaClass that it should be placed in the registry.
The final thing you need to know about creating ExpandoMetaClass is that it cannot be used until you call
initialize() and once you call initialize() you cannot add new methods. This is to ensure thread safety. So
the basic usage pattern is as follows:

def metaClass = new ExpandoMetaClass(myClass, true)


// add methods here

metaClass.initialize()

Adding instance methods

Once you have an ExpandoMetaClass to add new methods to it is trivial:

class Book {
String title
}

def metaClass = new ExpandoMetaClass(Book, true)

metaClass.titleInUpperCase << {-> title.toUpperCase() }


metaClass.initialize()

def b = new Book(title:"The Stand")

assert "THE STAND" == b.titleInUpperCase()

Note that in this case the left shift << operator is used to "append" the new method. If the method

Document generated by Confluence on May 01, 2007 11:37 Page 258


already exists an exception will be thrown. If you want to replace an instance method you can use the =
operator:

metaClass.toString = {-> title.toUpperCase() }

Adding static methods

Static methods can also be added using the same technique as above with the addition of the "static"
qualifier:

metaClass.'static'.create << { String title -> new Book(title:title) }


metaClass.initialize()

def b = Book.create("The Stand")

Adding constructors

Adding constructors is again similar except that you use a special "ctor" property of the MetaClass:

metaClass.ctor << { String title -> new Book(title:title) }


metaClass.initialize()

def b = new Book("The Stand")

Adding properties

Properties can be added in a couple of ways. Firstly you can use the instance method syntax seen
previously:

metaClass.getAuthor << { "Stephen King" }


metaClass.initialize()

def b = new Book("The Stand")

assert "Stephen King" == b.author

In this case the property is dictated by the closure and is a read-only property. You can add the
equivalent setter but then remember you will have to store the property somewhere for retrieval later so
make sure you use thread safe code.

Alternatively you can simply assign a value as follows:

metaClass.author = "Stephen King"


metaClass.initialize()

def b = new Book("The Stand")

Document generated by Confluence on May 01, 2007 11:37 Page 259


assert "Stephen King" == b.author

In this case the property is mutable and has both a setter and getter.

However, using this technique the property is stored in a ThreadLocal, SoftReference Map so don't
expect the value to stick around forever!

Borrowing Methods from other classes

With ExpandoMetaClass you can also use Groovy's method pointer syntax to borrow methods from other
classes. For example:

class AnotherClass {
def borrowMe() {
"hello!"
}
}

def another = new AnotherClass()

metaClass.borrowed = another.&borrowMe

def b = new Book()

assert "hello!" == b.borrowed()

Document generated by Confluence on May 01, 2007 11:37 Page 260


DynamicMethodsExpandoMetaClass

This page last changed on Feb 06, 2007 by graemerocher@yahoo.co.uk.

Grails' DynamicMethodsExpandoMetaClass

As well as the regular ExpandoMetaClass Grails has another powerful MetaClass called
DynamicMethodsExpandoMetaClass. This MetaClass allows you to match a number of methods using a
regex pattern.

Note: Unlike ExpandoMetaClass to achieve this effect DynamicMethodsExpandoMetaClass uses


proxying and hence is not suitable for use on frequently used classes like java.lang.Object or
java.lang.String

Creating an instance

To do this magic you first need to create an instance:

import org.codehaus.groovy.grails.commons.metaclass.*

def metaClass = new DynamicMethodsExpandoMetaClass(Book.class)

The above code will create the MetaClass, but not place it in the MetaClassRegistry, which is useful if you
want to do per-instance MetaClass'. To place a DynamicMethodsExpandoMetaClass in the registry you
need to do:

import org.codehaus.groovy.grails.commons.metaclass.*

def metaClass = new DynamicMethodsExpandoMetaClass(Book.class, true) // pass true to place in


registry

Matching instance methods

To match instance methods you basically have to assign a closure to a property that is a regex starting
with ^ and ending with $:

metaClass./^findBy(\w+)$/ = { matcher, args ->


return "${matcher[0][1]}"
}

The above example will match all methods that start with "findBy" (such as findByTitle, findbyFoo etc.).
The first argument passed to the closure is a java.util.regex.Matcher the second argument is the
arguments to the method. From there you can do what you like within the body of the closure. To get a
reference to "this" you should use the "delegate" property

Document generated by Confluence on May 01, 2007 11:37 Page 261


metaClass./^findBy(\w+)$/ = { matcher, args ->
println delegate // prints 'this' ie. the object the method was invoked on
}

Matching static methods

Like ExpandoMetaClass this MetaClass can also do static methods by using a "static" qualifier:

metaClass.'static'./^findBy(\w+)$/ = { matcher, args ->


println delegate // prints 'this' ie. the object the method was invoked on
return "${matcher[0][1]}"
}

Once you've constructed your MetaClass (in this example we're doing it for the Book class) you can then
happily invoke the added methods on it:

println new Book().findByFoo() // prints 'Foo'


println Book.findByBar() // prints 'Bar'

Also, DynamicMethodsExpandoMetaClass extends ExpandoMetaClass so all the features of that MetaClass


are available too! So you can mix regex matched methods and regular Expando methods.

Disclaimer: "With great power comes great responsibility"

Document generated by Confluence on May 01, 2007 11:37 Page 262


Runtime Configuration Plugins

This page last changed on Dec 05, 2006 by jason@jasonrudolph.com.

Runtime Configuration & Plugins

Understanding the Plugin class

There are a number of other properties you can specific on a plugin class and in the next few sections we
look at how you can use those.

class ExampleGrailsPlugin {
def version = 0.1

...
}

Hooking into the Grails Spring configuration

First, you can hook in Grails runtime configuration by providing a closure property called doWithSpring.
For example the following snippet is from one of the core Grails plugins that provides i18n support:

import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;

class I18nGrailsPlugin {

def version = 0.1

def doWithSpring = {
messageSource(ReloadableResourceBundleMessageSource) {
basename = "WEB-INF/grails-app/i18n/messages"
}
localeChangeInterceptor(LocaleChangeInterceptor) {
paramName = "lang"
}
localeResolver(CookieLocaleResolver)
}
}

This plugin sets up the Grails messageSource bean and a couple of other beans to manage Locale
resolution and switching. It using the Spring Bean Builder syntax to do so.

Participating in web.xml Generation

Grails generates the WEB-INF/web.xml file at load time, and although plugins cannot change this file
directly, they can participate in the generation of the file. Essentially a plugin can provide a
doWithWebDescriptor closure that gets passed the web.xml as a XmlSlurper GPathResult.

Consider the below example from the ControllersPlugin:

Document generated by Confluence on May 01, 2007 11:37 Page 263


def doWithWebDescriptor = { webXml ->
def controllers = [] as HashSet

plugin.watchedResources.each {
def match = it.filename =~ /(\w+)(Controller.groovy$)/
if(match) {
def controllerName = match[0][1]
controllerName = GCU.getPropertyName(controllerName)
controllers << controllerName
}
}
def mappingElement = webXml.'servlet-mapping'
controllers.each { c ->
mappingElement + {
'servlet-mapping' {
'servlet-name'("grails")
'url-pattern'("/${c}/*")
}
}
}
...
}

Here the plugin goes through all its watched resources, finding all the controller names and then creates
<servlet-mapping> elements appended after the last <servlet-mapping> element found in the web.xml

Note that at the point of web.xml generation there is no GrailsApplication instance, so you need to
use the conventions in the file names instead.

Doing Post Initialisation Configuration

Sometimes it is useful to be able do some runtime configuration after the Spring ApplicationContext has
been built. For this you can define a doWithApplicationContext closure property.

class SimplePlugin {
def name="simple"
def version = 1.1

def doWithApplicationContext = { appCtx ->


SessionFactory sf = appCtx.getBean("sessionFactory")
// do something here with session factory
}
}

Document generated by Confluence on May 01, 2007 11:37 Page 264


Understanding Plugins

This page last changed on Feb 28, 2007 by graemerocher@yahoo.co.uk.

Working with Plugins

Understanding a Plugin's structure

So as mentioned previously, a plugin is merely a regular Grails application with this special file; however
when installed, the structure of a plugin differs slightly. For example, take a look at this plugin directory
structure:

+ grails-app
+ controllers
+ domain
+ taglib
etc.
+ lib
+ src
+ java
+ groovy
+ web-app
+ js
+ css

Basically when a plugin is installed into a project, the stuff within the grails-app directory will go into a
directory like $PROJECT_HOME/plugins/example-1.0/grails-app. They will NOT be copied into the main
source tree. A plugin NEVER messes with a project's primary source tree.

However, static resources such as those inside the web-app directory will be copied into the project's
web-app directory under a special "plugins" directory for example web-app/plugins/example-1.0/js. It
is therefore the responsibility of the plugin to make sure that it references static resources from the
correct place. For example if you were referencing a JavaScript source from a GSP this would be:

<g:createLinkTo dir="/plugins/example/js" file="mycode.js" />

To make this easier there is a special pluginContextPath variable available that changes whether you're
executing the plugin standalone or whether you've installed it into an application:

<g:createLinkTo dir="${pluginContextPath}" file="js/mycode.js" />

At runtime this will either evaluate to /js or /plugins/example/js depending on whether the plugin is
running standalone or has been installed in an application

Java & Groovy code that the plugin provides within the lib and src/java and src/groovy directories will
be compiled into the main project's web-app/WEB-INF/classes directory so that they are made available
at runtime.

What a Plugin can and can't do

Document generated by Confluence on May 01, 2007 11:37 Page 265


A plugin can do just about anything, but a good plugin should be as unintrusive as possible. It should use
convention over configuration where possible, otherwise provide an artifact in a project's grails-app/conf
directory where configuration can be done.

One thing a plugin cannot do though is modify the web-app/WEB-INF/web.xml or


web-app/WEB-INF/applicationContext.xml files. A plugin can participate in web.xml generation, but not
modify the file or provide a replacement. A plugin can NEVER change the applicationContext.xml file,
but can provide runtime bean definitions as seen shortly.

Document generated by Confluence on May 01, 2007 11:37 Page 266


Unit Testing

This page last changed on Feb 02, 2007 by jnicho02.

Unit testing

Grails also supports functional testing.

Creating & Running a test suite

To create a test suite run the "grails create-test-suite" target or just create a new class in
"%PROJECT_HOME%\grails-test" that extends GroovyTestCase and ends with "Tests".

Below is an example of a test suite that tests the validate method on a domain class:

class BookTests extends GroovyTestCase {

def testValid() {
def b = new Book(title:"Groovy in Action", author:"Dierk Koenig")

assert b.validate()
}
}

To run the test suite run the command "grails test-app"

For more info on how to write unit tests using Groovy see the section on Unit Testing on the main
Groovy website. This page contains a useful list of all the different assert methods that come with
the JUnit and GroovyTestCase superclasses.

Keeping the Hibernate session open

You may find that if you are testing your persisted domain model objects and accessing collection
properties that you get hibernate errors. For example, say I'm writing a social bookmarking application
and I have a User model object which relates to many UserBookmark objects. (So my User class defines
a "Set userBookmarks" property.)

I want to unit test business logic in my User class, so I start out with the following test:

/**
* Tests saveBookmark
*/
void testSaveBookmark() {
// verify boris has no bookmarks yet
def user = User.get(3)

Document generated by Confluence on May 01, 2007 11:37 Page 267


assertNotNull user
assertEquals "boris", user.username
assertEquals 0, user.userBookmarks.size()
}

But when I run it I get:

[java] 1) testSaveBookmark(UserTests)org.hibernate.LazyInitializationException: failed to


lazily initialize a collection of role: User.userBookmarks, no session or session was closed
[java] at
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCol
[java] at
org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(Abstrac
[java] at
org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)
[java] at org.hibernate.collection.PersistentSet.size(PersistentSet.java:114)
[java] at gjdk.org.hibernate.collection.PersistentSet_GroovyReflector.invoke(Unknown
Source)
[java] at groovy.lang.MetaMethod.invoke(MetaMethod.java:111)
[java] at
org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke(MetaClassHelper.java:657)
[java] at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:350)
[java] at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:146)
[java] at
org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:104)
[java] at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod(ScriptBytecodeAdapter.java:85)
[java] at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeNoArgumentsMethod(ScriptBytecodeAdapter.java:175)
[java] at UserTests.testSaveBookmark(UserTests.groovy:47)
[java] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[java] at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[java] at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[java] at
org.codehaus.groovy.grails.support.GrailsTestSuite.runTest(GrailsTestSuite.java:47)
[java] at grails.util.RunTests.main(RunTests.java:57)

The error is caused by this line:

assertEquals 0, user.userBookmarks.size()

because I'm accessing a collection property on my user object. (Behind the scenes, Hibernate has created
a placeholder object for the "userBookmarks" property. The idea is that the data is only fetched when
required.)

This works fine in a normal running Grails application because Grails uses the standard "Open Session in
View" pattern and support classes provided by Spring, but fails in the test because the same principle is
not applied.

The solution is to create a Hibernate session before the test starts and close it after the test finishes.

You can use the setUp() and tearDown() methods (which run before and after each test method,
respectively), like so:

import org.hibernate.Session
import org.hibernate.SessionFactory
import org.springframework.orm.hibernate3.SessionFactoryUtils
import org.springframework.orm.hibernate3.SessionHolder

Document generated by Confluence on May 01, 2007 11:37 Page 268


import org.springframework.transaction.support.TransactionSynchronizationManager

/**
* Tests my User code
*/
class UserTests extends GroovyTestCase {

SessionFactory sessionFactory

void setUp() {
Session session = SessionFactoryUtils.getSession(sessionFactory, true)
TransactionSynchronizationManager.bindResource(sessionFactory, new
SessionHolder(session))
}

void tearDown() throws Exception {


SessionHolder sessionHolder = (SessionHolder)
TransactionSynchronizationManager.unbindResource(sessionFactory)
SessionFactoryUtils.closeSessionIfNecessary(sessionHolder.getSession(), sessionFactory)
}

/**
* Tests saveBookmark
*/
void testSaveBookmark() {
// verify boris has no bookmarks yet
def user = User.get(3)
assertNotNull user
assertEquals "boris", user.username
assertEquals 0, user.userBookmarks.size()
}
}

It now passes!

Note the line

SessionFactory sessionFactory

This is set automatically by Grails, so you don't have to look it up yourself!

Credit goes to the following link for code http://forum.hibernate.org/viewtopic.php?t=929167

Document generated by Confluence on May 01, 2007 11:37 Page 269


Validation

This page last changed on Nov 30, 2006 by wangjammer5.

Validation

Validating Domain Classes

Grails allows you to apply constraints to a domain class that can then be used to validate a domain class
instance. Constraints are applied using a "constraints" closure which uses the Groovy builder syntax to
configure constraints against each property name, for example:

class User {
Long id
Long version

String login
String password
String email
Date age

static constraints = {
login(length:5..15,blank:false,unique:true)
password(length:5..15,blank:false)
email(email:true,blank:false)
age(min:new Date(),nullable:false)
}
}

Note that as of Grails 0.4 your constraints must be static or an exception will be thrown.

To validate a domain class you can call the "validate()" method on any instance:

def user = new User()


// populate properties

if(user.validate()) {
// do something with user
}
else {
user.errors.allErrors.each {
println it
}
}

The errors property on domain classes is an instance of the Spring


org.springframework.validation.Errors interface.

By default the persistent "save()" method calls validate before executing hence allowing you to write code
like:

if(user.save()) {
return user
}

Document generated by Confluence on May 01, 2007 11:37 Page 270


else {
user.errors.allErrors.each {
println it
}
}

For a full reference see the Validation Reference

Display Errors in the View

So your instance doesn't validate, how do you now display an appropriate error message in the view? For
starters you need to redirect to the right action or view with your erroneous bean:

class UserController {
def save = {
def u = new User()
u.properties = params
if(u.save()) {
// do something
}
else {
render(view:'create',model:[user:u])
}
}
}

In this case we use the render method to render the right view, alternatively you could chain the model
back to a "create" action:

chain(action:create,model:[user:u])

The chain method stored the model in flash scope so that it is available in the request even after the
redirect.

So now to the view, you clearly have an instance with errors, to display them we use a special tag called
"hasErrors":

<g:hasErrors bean="${user}>
<g:renderErrors bean="${user}" as="list" />
</g:hasErrors>

This is used in conjunction with the tag "renderErrors" which renders the errors as a list. In GSP because
you can call tags as regular methods calls it also means you can do some neat tricks to highlight the
errors really easily such as:

<div class="prop ${hasErrors(bean:user,field:'login', 'errors')}">


<label for="login"><input type="text" name="login" />
</div>

The above code will add the "errors" CSS class to the property if there are any errors for the field 'login'
now simply add a CSS style:

Document generated by Confluence on May 01, 2007 11:37 Page 271


.errors { border: 1px solid red }

And you have the erroneous field highlighting when there is a problem.

Changing the Error Message

Of course the default error message that Grails displays is probably not what you were after, so you will
want to change this. The way you do this is by modifying the "grails-app/i18n/messages.properties" file
and adding a message for the particular error code.

For example if we follow the above example the error code may be "user.login.length.tooshort" so we add
an entry:

user.login.length.tooshort=I'm sorry the login you entered wasn't quite long enough, please
make it longer

For a complete list of error codes and how they correspond to validation constraints see the Validation
Reference

Defining constraints for Hibernate mapped classes

To integrate with the Grails constraints mechanism and hence hook into useful things like the way the
views are generated and Grails' Validation mechanism you can do so by creating a Groovy script following
the naming convention of your domain class and ending in the "Constraints" suffix. For example for a
"com.books.HibernateBook" class (either an EJB3 entity of mapped with Hibernate XML) defined above
you would need to create a "com/books/HibernateBookConstraints.groovy" script in the same package as
the class itself, in the src/java directory tree. Within the script just define constraints in the same way as
you would do in a GORM class but without the @Property notation:

constraints = {
title(length:5..15)
desc(blank:false)
}

Document generated by Confluence on May 01, 2007 11:37 Page 272


Views and Layouts

This page last changed on Oct 05, 2006 by graeme.rocher@gmail.com.

Views and layouts

Controllers & Views

Grails supports the creation of views using either JavaServer Pages (JSP) or Groovy Server Pages (GSP).
This section describes how to provide a model to views. For a more complete reference on see the GSP
and JSP references.

Syntactically GSP and JSP are very similar the main difference being that code within scriptlets is in
Groovy not Java! Grails controllers uses a convention mechanism to delegate to an appropriate view. For
example an action called list will delegate to a "list" view:

class BookController {
def list = {
["books" : Book.list() ]
}
}

The corresponding view for the above action would need to be placed in the "grails-app/views/book"
directory with the name "list.jsp" or "list.gsp". The example below is in GSP:

<html>
<head>
<title>Book list</title>
</head>
<body>
<h1>Book list</h1>
<table>
<tr>
<th>Title</th>
<th>Author</th>
</tr>

<g:each in="${books}">
<tr>
<td>${it.title}</td>
<td>${it.author}</td>
</tr>
</g:each>
</table>
</body>
</html>

Defining Layouts

Layouts can be created through Grails's support for SiteMesh. There are 2 ways to create layouts the first
is to associate a view with a layout at the "layout" meta tag to your page:

Document generated by Confluence on May 01, 2007 11:37 Page 273


<html>
<head>
<meta name="layout" content="main"></meta>
</head>
<body>This is my content!</body>
</html>

Now create a layout in called "main.gsp" in the "grails-app/views/layouts" directory and you're done!:

<html>
<head>
<title><g:layoutTitle default="An example decorator" /></title>
<g:layoutHead />
</head>
<body onload="${pageProperty(name:'body.onload')}">
<div class="menu"><!--my common menu goes here--></menu>
<div class="body">
<g:layoutBody />
</div>
</div>
</body>
</html>

The layout uses GSP tags to apply the layout onto the target page.

Layout by Convention

The second way to associated layouts is to use "layout by convention". For example if you have a
controller such as the below:

class BookController {
def list = { ... }
}

You can create a layout called grails-app/views/layouts/book.gsp which will be applied to all views
that the BookController delegates to.

Alternatively you can create a layout called grails-app/views/layouts/book/list.gsp which will only
be applied to the list action within the BookController.

If you have both the above mentioned layouts in place the layout specific to the action will take
precedence when the list action is executed.

Document generated by Confluence on May 01, 2007 11:37 Page 274


0.5 Release Notes

This page last changed on Apr 30, 2007 by wangjammer5.

This is a work in progress

0.5 Release Notes

30 April 2007

The Grails development team has reached another milestone and is pleased to announce the release of
version 0.5 of the Grails web-application development framework.

Grails is a dynamic web-application framework built in Java and Groovy, leveraging best of breed APIs
from the J2EE sphere including Spring, Hibernate and SiteMesh. Grails brings to Java and Groovy
developers the joys of convention-based rapid development while allowing them to leverage their existing
knowledge and capitalize on the proven and performant APIs Java developers have been using for years.

Development has been intense since the release of 0.4.2 at the end of February, tackling over 190 issues
in this period. This release has seen exciting contributions from new team members and users and
significant functionality enhancements.

Thank you to all the team members, patch contributors and users. A lot of hard work has gone into this
release - we hope you enjoy using this latest installment of the Grails adventure.

New Features

• Custom URL Mappings


• Command objects / form validation
• List & Map support in GORM
• Support for composition in domain class (Hibernate "components")
• Base64 codec
• Dependency resolution with Ivy
• Project metadata and versioning support, smarter scripts and upgrade processes
• Script event hooks
• Automatic addition of log objects to all artefacts
• New Artefact API available to Plugins

Improvements

• Major improvements to artefact reloading


• Improved relationship management methods in GORM
• Cascading validation

Document generated by Confluence on May 01, 2007 11:37 Page 275


• Retrieving multiple objects with Book.getAll(1,2,3)
• Using named HQL parameters in find() methods
• Clean up of some legacy constraints issues
• Performance improvements (40-50% faster)
• Taglib optimisations
• Improvements to scaffolding (sortable columns, pagination of large resultsets, etc.)
• I18N improvements
• Overhauled GSP view loading
• Even greater test coverage of the core Grails code
• Many many bug fixes

Detailed examples

Custom URL Mappings

You can now create a URL mapping class that uses, for those interested, a dynamic builder/metaclass
mechanism to map the URI space of your application to your controllers and actions in almost any way
you like. You can pull out parts of the URL as variables and even apply constraints to these.

On top of this, grails taglibs that produce links are smart and will reverse map controller/action
combinations to URLs from the mappings, so links generated within your pages are consistent with your
public URL interface defined in your mappings.

Example:

class MyUrlMappings {
static mappings = {
"/product/$id" {
controller = "product"
action = "show
}
"/$id/$year/$month/$day" {
controller = "blog"
action = "show"
constraints {
year(matches:/\d{4}/)
month(matches:/\d{2}/)
day(matches:/\d{2}/)
}
}
}
}

This removes the necessity to use something like Apache's mod_rewrite to produce user-friendly URLs or
to abstract your URL space away from your implementation.

Documentation

Command Objects / Form validation

Grails has always had domain class constraints, but often a form or request parameters do not relate

Document generated by Confluence on May 01, 2007 11:37 Page 276


directly to a domain class. New in 0.5, command objects are automatically created and populate by Grails
when the request is received, and validated against database-like constraints, before your action is even
called.

Example:

class LoginController {
def login = { LoginCommand cmd ->
if(cmd.hasErrors()) {
redirect(action:'loginForm')
}
else {
// do something else
}
}
}

class LoginCommand {
String username
String password
static constraints = {
username(blank:false, minSize:6)
password(blank:false, minSize:6)
}
}

Any Groovy class can be used as a command object, with the standard Grails property binding and
validation options. You just specify the typed parameters to the action closure and Grails works out the
rest!

Documentation

List & Map support in GORM

GORM has been enhanced to support lists of domain objects in a relationship, as opposed to the default
Set behaviour, providing ordered lists.

// Support for Lists of objects


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

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

There is also support for Maps of standard non-domain types:

// Support for Maps of objects


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

def a = new Author()


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

...as well as maps of standard type keys to domain objects:

Document generated by Confluence on May 01, 2007 11:37 Page 277


// If you want a map of domain classes you can do
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()

Documentation

Support for composition in domain class (Hibernate


"components")

By default GORM currently uses table-per-hierarchy mapping of classes to the database, which means
that classes in relationships typically are stored in a separate table.

You now can use the Hibernate composition mechanism to embed the data from objects that would
otherwise be considered relationships, within the main table used for the outer class, using the
"embedded" declaration.

class Address {
String street
// ...
String country
}

class Person {
String firstName
String lastName

Address homeAddress
Address workAddress

static embedded = ['homeAddress', 'workAddress']


}

The "embedded" property is set to the list of property names that represent complex properties that
should be written into the table directly instead of forming a relationship.

Documentation

Base64 codec

Augmenting the existing super-useful codecs supplied in 0.4, we have now added a Base64 codec so that
you can now write code such as this anywhere in your Groovy code or GSPs:

Your registration code is: user.registrationCode.encodeAsBase64()

Documentation

Document generated by Confluence on May 01, 2007 11:37 Page 278


Dependency resolution with Ivy

We've added support for Ivy dependency resolution for your projects. There are two new targets for this:

grails install-ivy

With the above run once per-project, you can then execute:

grails get-dependencies

To update your project's dependencies.

Project metadata and versioning support, smarter scripts and


upgrade processes

The days of accidentally running with the wrong Grails version for your project are gone with 0.5 and
future versions. Applications have metadata stored in a file (not generally for user editing) that includes
the required version of grails, and a version number of your application.

Most of the grails targets therefore refuse to run if the grails version you are using in GRAILS_HOME does
not match that of the project, so that you never omit to run grails upgrade.

Your application's version number is now included in the filename of generated war files. You can set the
version number with "grails set-version"

Furthermore, you can now override the name used for your application so that it does not use the parent
directory name.

Script event hooks

A new event mechanism allows target scripts, even those in plugins and your custom application scripts,
to fire and respond to events. By default we have events for artifact and file creation, plugin installation,

Document generated by Confluence on May 01, 2007 11:37 Page 279


script shutdown, and progress notifications. This allows, for example, integration with Growl on Mac OS X
to provide on-screen notifications when grails tasks complete.

Documentation

Automatic addition of log objects to all artefacts

Version 0.4 added an implicit "log" object for controllers. We have now expanded this feature to all
artefact classes in the application. This means that all domain classes, services, jobs, controllers and so
on (all declared artefacts using the artefact API) receive an implicit log object of their own.

The logs are named in such a way that you can controll the logging of individual artefacts or the category
of artefacts they belong to, or all of your artefacts in the application.

Documentation

New Artefact API available to Plugins

The internal artefact mechanisms have been overhauled to allow plugins to register first-class artefacts of
their own that will be managed just like all other grails artefacts, and receive implicit log objects and
other features.

Documentation

Improvements

Major improvements to artefact reloading

Document generated by Confluence on May 01, 2007 11:37 Page 280


Automatic reloading of modified code at runtime is a major productivity boost, and one of the most
enjoyable parts of using Grails versus traditional Java web-application development. In this release we
added support for reloading of domain classes, transactional services and Quartz jobs.

Improved relationship management methods in GORM

Along with some of our users, we thought that the implicit addXXXX methods in 0.4 were nice but bit
clunky when you had multiple relationships of the same type. We've sorted this out for 0.5 and are proud
to introduce the minor but important change from addXXXX to addToXXXX methods, where the latter new
form takes the name of the property (collection) not the type of the relationship:

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


.addToBooks(title:"IT")
.addToBooks(title:"The Stand")
.save()

author.removeFromBooks(myBook)

You will also notice we now have the orthogonal removeFromXXXX which manages the bi-directional
references if they exist.

Documentation

Cascading validation

Validation constraints are now applied to all related objects in the object graph when persisting or
validating a domain object.

Retrieving multiple objects with Book.getAll(1,2,3)

A new method was added for retrieving multiple objects in one call.

Using named HQL parameters in find() methods

There is now support for positional and named parameters in HQL queries.

Clean up of some legacy constraints issues

We've finally removed the "optionals" property and nullability is purely controlled by the nullable
constraints, and the often duplicated functionality between length and size constraints is being phased
out, with the size variants being the future path.

Performance improvements (40-50% faster)


Document generated by Confluence on May 01, 2007 11:37 Page 281
It's early days for Grails performance tuning - we make it work first and optimize as necessary later.
However we've added some important optimisations in this release to improve first load time and also
runtime performance.

Taglib optimisations

Specific optimisations related to taglibs should see significant request throughput increases where pages
use many GSP tags.

Improvements to scaffolding

As part of our ongoing effort to increase the real-world usefulness of scaffolding, we have added sortable
columns, improved pagination of large result sets, and other improvements to the default scaffolding
templates.

I18N improvements

Message bundles are reloadable and we have support for more languages out of the box including
Russian, German and Spanish. There have also been changes to some default message codes used, to
make them more logical.

Overhauled GSP view loading

View resolution has been re-written to use a resource loader mechanism.

Document generated by Confluence on May 01, 2007 11:37 Page 282


FAQ

This page last changed on Apr 05, 2007 by masukomi.

Frequently Asked Questions (FAQ)

General

Q: I get an exception when loading my Grails application in my browser

One thing to always check in case of unexpected exceptions is the value of the CLASSPATH variable in
your console. Run set CLASSPATH on Windows and echo $CLASSPATH on Mac OS X, Linux and Unix to
print the value. Grails does not depend on the CLASSPATH variable so in case it's set run set
CLASSPATH= on Windows and export CLASSPATH= on Mac OS X, Linux and Unix to remove it.

Q: How do I check my project into SVN / I am getting strange SVN errors with files generated
by Grails

Because Grails (certainly up to an including 0.4) generates and copies some files under the project tree,
SVN and other version control systems can complain about files changing, or files not being in version
control.

For Subversion (SVN) the solution is to mark the correct directories or files to be "ignored". However how
you do this is slightly obscure. See the article Checking Projects into SVN.

Application Servers

Q: I'm getting errors when deploying on JBoss 4.0.x What do I do?

JBoss' unified class loader can cause problems with conflicting Jar files. One issue commonly encountered
is with log4j, which is part of both JBoss and Grails. This can be resolved by removing log4j.jar from your
deployed .war file or using scoped classloading (with some caveats).

Ideally you wouldn't want to remove the log4j file from your deployment as this requires some additional
work and will break many automated deployment/testing processes. JBoss' class loaders are based on a
hierarcy of classloaders but this causes issues where there are files shared between the JBoss parent
classloaders and the child classloader for our web application. What we really want to do is tell JBoss to
leave us alone when it comes across files that we have in our .war file. To do this we must 'scope' our
classloader so that the classes we are using are in their own class loader repository away from the JBoss
classes. To do this for a war is relatively straightforward. We must create a file called jboss-service.xml
and place it in our .war file

Document generated by Confluence on May 01, 2007 11:37 Page 283


<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
myappname:loader=myappname.war
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>

This will tell the JBoss class loaders to isolate (to a large extent) our classes from those that JBoss is
using, to load our classes first and not to delegate class loading to the parent classloading in case of a
conflict. You need to replace "myappname" with the name of your app or any other string. The only thing
you want is for the loader-repository name to be unique. Generally a good string to use will include your
package name so you can avoid namespace collisions within the webserver

"com.foocompany.webProjectBar:loader=webProjectFooBar.war"

would be a good name this is almost guaranteed to be unique within the container. This is especially
important in a shared hosting environment based on JBoss.
Once you have finished with that file and you drop it into the WEB-INF directory of your web application
and you deploy your web application ideally you should be done. But you're not because of one slight
miscalculation. Log4J will by default look for a log4j.xml file to load its properties from and failing that, it
will fall-back to a log4j.properties. Since we have a classloader hierarchy, you know that if the child
classloader fails - the request to load a class (or resource) gets escalated up the classloader chain until a
classloader accepts it or until they all fail to load the resource at which time an Exception is thrown. The
problem is that the parent classloader already knows about a log4j.xml file - the one loaded by JBoss, so
you will find that you still throw a ClassCastException because log4j.xml for JBoss is trying to load log4j
for your web application. There are two possible fixes for this:
1) In grails we migrate to the log4j.xml file syntax for specifying log4j settings and the problem goes
away because the child classloader will find what its looking for (and this has been suggested and being
evaluated)
2) Change the configuration of the JBoss application server so that it doesn't have a log4j.xml file either.
If you have the ability to make this change, it make save you some headache down the road with
other web applications that bundle log4j in their distributions as well. The fix is very straightforward:

1. Go in the servers conf directory. I have JBoss installed in /jboss-4.0.5.GA, so the conf directory is
/jboss-4.0.5.GA/server/default/conf. If you are deploying into a profile other than default, simply
substitute default for the name of the profile that you are deploying into such as
/jboss-4.0.5.GA/server/foobarprofile/conf.
2. Move the log4j.xml to jboss-log4j.xml
3. Edit the jboss-service.xml file and find the mbean called "org.jboss.logging.Log4JService". Change
the attribute "ConfigurationURL" so that it points to this new jboss-log4j.xml file:

<attribute name="ConfigurationURL">resource:jboss-log4j.xml</attribute>

1. Restart the JBoss application server and now any application that has log4j bundled in it will deploy
properly and with their own log4j configuration.

<!-- ==================================================================== -->


<!-- Log4j Initialization -->
<!-- ==================================================================== -->

<mbean code="org.jboss.logging.Log4jService"
name="jboss.system:type=Log4jService,service=Logging"
xmbean-dd="resource:xmdesc/Log4jService-xmbean.xml">
<attribute name="ConfigurationURL">resource:jboss-log4j.xml</attribute>
<!-- Set the org.apache.log4j.helpers.LogLog.setQuiteMode. As of log4j1.2.8

Document generated by Confluence on May 01, 2007 11:37 Page 284


this needs to be set to avoid a possible deadlock on exception at the
appender level. See bug#696819.
-->
<attribute name="Log4jQuietMode">true</attribute>
<!-- How frequently in seconds the ConfigurationURL is checked for changes -->
<attribute name="RefreshPeriod">60</attribute>
</mbean>

Q: How do I setup Grails on Oracle AS?

There is a great tutorial on the Oracle website detailing exactly how to setup Grails on Oracle

Q: Deploying on JETTY 6

I had to remove the lib/jsp 2.1 directory from my jetty install to disable JSP 2.1

Q: Deploying under IBM's J9 JVM (applies to WebSphere installs too)

WebSphere uses the J9 Java Virtual Machine. J9 is also one of the alternatives you'll have to consider on
a PPC Linux box because the Sun JVM doesn't run there. Unfortunately J9 does a lot of work under the
covers to make things run faster that don't work well with Groovy.

Add '-Xverify:none' to JVM arguments

Without this you'll get a NoClassDefFoundError.

Under WebSphere you can set this via the WebSphere Administative Console: Application servers >
server1 > Process Definition > Java Virtual Machine > Generic JVM arguments) save the change and
restart the application server. (See also GRAILS-476.)

Under Tomcat 5 you can add it to the tomcat5.conf

We found that sending email caused j9 to throw a GPF Fault - and Tomcat then does it's version of a
Core Dump. Perusing the dump file doesn't seem to help - as there is no indication of the class or
method which caused GPF. GPF is short for General Protection Fault - which means that something is
attempting to access a resource to which they do not have permission (per the underlying operating
system). And finally once past the GPF mail wouldn't send due to some incompatiblity with the Gnu
JavaMail API and the Sun specification JavaMail API. Once the Gnu mail.jar was replaced with the Sun
version - email functioned normally.

Q: Deploying on Websphere

Commons-logging is shipped with WebSphere and included in Grails. WebSphere may


complain on problems with the Grails LogFactory.

When trying to load a WAR file on WAS 6 and selecting "Parent last" as the classloader option, some
users report the following error:

Document generated by Confluence on May 01, 2007 11:37 Page 285


Caused by: org.apache.commons.logging.LogConfigurationException: The chosen LogFactory
implementation does not extend LogFactory. Please check your configuration...

The following steps are reported to work in solving this problem:


1. Delete commons-logging-1.1.jar from the lib directory
2. Add commons-logging-adapters-1.1.jar to the lib directory
3. After adding the application, modify the classloader to "Parent last."
For more information, IBM offers a 20-page PDF document on how to get commons-logging to work with
WebSphere. (See also GRAILS-515.)
WebSphere ships with an old version of ant.jar in $WASHOME/lib

You will see errors like 'java.lang.NoSuchMethodError: org.apache.tools.ant.UnknownElement: method


setNamespace(Ljava/lang/String;)V not found'.

Workaround: replace the ant.jar with a more recent version of ant (e.g. from GRAILS_HOME/lib).

Acegi filter does not find FilterChainProxy

Class of type org.acegisecurity.util.FilterChainProxy not found in classloader

Solution: replace the Acegi FilterToBeanProxy with the Spring implementation (which uses the Thread
ClassLoader) :

<filter>
<filter-name>filterChainProxy</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Scaffolding does not work for GSP views

Make sure that you pre-generate the GSP views: 'grails generate-all <Domain>'. This is an issie with
version 0.4.2, which will be fixed for 0.5.

Make sure you are not using JDK1.5 specific features. Use a 1.4 JVM when creating the WAR
file. Make sure you're not using the GrailsAnnotationConfiguration.

Q: I'd like to implement a big project as multi modules with Grails, What to do?

Since version 0.4, Grails has came with a plugin architecture. You can separate your project as a set of
plugins. See how to develop a plug-in here.

View Technologies

Q: Can I view my GSP's (Groovy Server Pages) directly?

Document generated by Confluence on May 01, 2007 11:37 Page 286


A: Yes, but they need to into the web-app directory of your Grails application

Q: Why won't XXX Javascript Library Display Properly?

A: Sometimes third party javascript libraries depend upon other resources loaded directly from the
javascript files themselves like stylesheets. Examples of libraries that do this would be the Yahoo UI
libraries and niftycube. When the javascript attempts to load the URL Grails changes the URL so that the
resource is not found. Try adding a link using the createLinkTo tag for the particular resource.

Controllers

Q: Can I use the render method to return a binary file to the client?

A: Not at the moment. However the servlet response instance can be used. For example, a zip file is
created on the server and returned to the client:

def createZip = {
byte[] zip = createZipForClient()
response.contentType = "application/octet-stream"
response.outputStream << zip
}

Alternatively, you can use:

response.setHeader("Content-disposition", "attachment; filename=" +


session.userid + ".csv");
render(contentType: "text/csv", text: "my,comma,seperated,variable,file");

Q: Can I use JFreeChart to display charts to the client?

Of course you can! Just use JFreeChart to create an image of the chart you want to show and then
stream that back through the response.

An example of a controller that creates a Pie Chart:

import org.jfree.chart.ChartFactory
import org.jfree.data.general.DefaultPieDataset
import org.jfree.chart.encoders.EncoderUtil

class PiechartController {

def index = {

// create the data for the pie chart


def slices = [
[label:"One", percent:43.2],
[label:"Two", percent:10.0],

Document generated by Confluence on May 01, 2007 11:37 Page 287


[label:"Three", percent:27.5],
[label:"Four", percent:17.5],
[label:"Five", percent:11.0],
[label:"Six", percent:19.4]
]

// load the data into a dataset


def dataset = new DefaultPieDataset();
slices.each { slice ->
dataset.setValue(slice.label, slice.percent)
}

// create the pie chart and stream it back to the client


def chart = ChartFactory.createPieChart("Pie Chart Demo 1", dataset, true, true,
false)
EncoderUtil.writeBufferedImage(chart.createBufferedImage(800, 600), "png",
response.getOutputStream())
}

You will also need to copy jfreechart-1.0.1.jar and jcommon-1.0.0.jar into the libs folder of your grails
app.

Grails Object Relational Mapping (GORM)

Q: In a one-to-many relationship, how to do I have a sorted set of the many objects?

In the Author/Book example, Book must implement the Comparable interface, and the set of books must
be of type SortedSet:

class Author {
Long id
Long version

def relatesToMany = [ books : Book ]

String name
SortedSet books
}

Q: I have a simple domain class that gets erros when trying to view its list?

Be careful with SQL reserved words. The code bellow will result in mapping errors because "order" is an
SQL reserved word. Change that to "sortOrder" or something else.

class Category{
String name
Integer order

Q: How can I flush a Hibernate session multiple times within my controller?

Spring will inject the a SessionFactory object into your controller, provided you import the proper libraries
and provide a reference for the injection:

Document generated by Confluence on May 01, 2007 11:37 Page 288


import org.hibernate.*

class SomeController {
SessionFactory sessionFactory
def flush_multiple_times = {
assert sessionFactory != null
def hibSession = sessionFactory.getCurrentSession()
assert hibSession != null
hibSession.flush()
// do something
hibSession.flush()
}
}

Security

Q: How can I secure my application?

The most commons way to secure a Grails app is through Controller interceptors and the login tutorial
(PDF). If you want a declarative approach to security another way of securing your applications might be
to use Acegi. This article might give you a solution.

Grails in Eclipse

Q: Launching Grails in Eclipse fails with an exception about JAVA_HOME

Your Eclipse is configured to use a Java Runtime Environment or JRE. However, to launch a Grails
application you need a Java Developer Kit or JDK. If you don't have a JDK installed on your system your
can download the latest version from http://java.sun.com

Go to Preference in Eclipse (in the Window menu) and go to "Java/Installed JREs". You will find a JRE
installed, for example "jre1.5.0_09". Now add the JDK by clicking the "Add..." button. Click the
"Browse..." button and select the location of your JDK (for example "C:\Program
Files\Java\jdk1.5.0_09"). Click "Ok" and enter a name for this JDK (for example "JDK 1.5.0_09").

Now make sure to select the JDK you just installed in your launch configuration.

Document generated by Confluence on May 01, 2007 11:37 Page 289


Checking Projects into SVN

This page last changed on Feb 16, 2007 by wangjammer5.

Checking Projects into SVN

Author: Marc Palmer

The information in here should be easily adapted to CVS. Replace the svn propset svn:ignore
commands to set the same text in .cvsignore files in the directories specified in the commands.

Up to and including Grails 0.4.x there are files that are generated or copied by Grails within your project
tree. This can be problematic as it is unclear what is to go into SVN and what isn't. In addition, you will
not usually want your compiled .class files going into version control, nor duplicates of your libs etc.

This is correct at the time of writing (Grails 0.4.x) but makes the following assumptions:

• You do not want ./plugins/core (Core Grails plugins) under SVN


• You do not want anything under ./web-app/WEB-INF/ under SVN. You should not usually need to
put files in here. Files from ./conf are copied to WEB-INF/classes so they are on the classpath, if you
need to supply anything.

Why is this such a hassle? Well SVN prevents files or directories being considered for version control by
checking an "ignores" list that is set via an SVN property. This property is set on specific directories
within your SVN working copy. Therein lies the problem - until you have a working copy you cannot tell it
to ignore files.

Creating a new project and putting it into SVN

This approach is for use when starting a new Grails project - i.e. it does not yet exist on your disk at all,
nor in SVN. It will talk you through your first check in, including the relevant svn:ignore properties, and
avoids any checkin of these ignored files that may or may not exist locally.

With SVN installed, create your project. We will use "MyProject" as the name for the purposes of
demonstration:

grails create-app MyProject


cd <projname>

Now you must create an empty SVN dirictory under your SVN repository using whatever appropriate tools
you have. This directory should be called the same as MyProject but it doesn't have to be. We will call
this SVN repository directory path "emptysvndir" for this example. Next you do:

Document generated by Confluence on May 01, 2007 11:37 Page 290


svn checkout <svn-server-url>/emptysvndir/ .
svn add *
svn propset svn:ignore "WEB-INF" web-app/
svn propset svn:ignore "core" plugins/
svn rm --force web-app/WEB-INF
svn rm --force plugins/core
svn commit -m "First commit"

That should have your project committed, and changes to ./plugins/core and ./web-app/WEB-INF/ should
be ignored by SVN.

You will not need to check out this project as we have used the "in place import" technique.

At the time of writing (Grails 0.4.x), to checkout this project fresh locally or on another machine
you will need to checkout as usual but then run:

grails upgrade

To re-instate some files that we are not checking in.

Fixing an existing project that is already in SVN

This approach is for use when you have optimistically imported your entire project into SVN already and
have started getting errors or are being annoyed by the warning messages relating to locally changed
files.

We will use "MyProject" as the name for the purposes of demonstration:

cd MyProject
svn propset svn:ignore "WEB-INF" web-app/
svn propset svn:ignore "core" plugins/
svn rm web-app/WEB-INF
svn rm plugins/core
svn commit -m "Fixing SVN"

That should have your project committed, and changes to ./plugins/core and ./web-app/WEB-INF/ should
be ignored by SVN.

At the time of writing (Grails 0.4.x), to checkout this project fresh locally or on another machine
you will need to checkout as usual but then run:

grails upgrade

To re-instate some files that we are not checking in.

Document generated by Confluence on May 01, 2007 11:37 Page 291


Frequently Asked Questions

This page last changed on Jun 05, 2006 by graeme.rocher@gmail.com.

Frequently Asked Questions

Moved here

Document generated by Confluence on May 01, 2007 11:37 Page 292

You might also like