1 Introduction - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: 2.1.0
Table of Contents
1 Introduction
Java web development as it stands today is dramatically more complicated than it needs to be. Most modern web frameworks in the Java space are over complicated and don't embrace the Don't Repeat Yourself (DRY) principles.Dynamic frameworks like Rails, Django and TurboGears helped pave the way to a more modern way of thinking about web applications. Grails builds on these concepts and dramatically reduces the complexity of building web applications on the Java platform. What makes it different, however, is that it does so by building on already established Java technologies like Spring and Hibernate.Grails is a full stack framework and attempts to solve as many pieces of the web development puzzle through the core technology and its associated plugins. Included out the box are things like:- An easy to use Object Relational Mapping (ORM) layer built on Hibernate
- An expressive view technology called Groovy Server Pages (GSP)
- A controller layer built on Spring MVC
- A command line scripting environment built on the Groovy-powered Gant
- An embedded Tomcat container which is configured for on the fly reloading
- Dependency injection with the inbuilt Spring container
- Support for internationalization (i18n) built on Spring's core MessageSource concept
- A transactional service layer built on Spring's transaction abstraction
1.1 What's new in Grails 2.1?
Maven Improvements / Multi Module Build Support
Grails' Maven support has been improved in a number of significant ways. Firstly it is now possible to specify plugins within yourpom.xml
file:<dependency> <groupId>org.grails.plugins</groupId> <artifactId>hibernate</artifactId> <version>2.1.0.RC1</version> <type>zip</type> <scope>compile</scope> </dependency>
create-multi-project-build
script which features initial support for Maven (Gradle coming in a future release). This script can be run from a parent directory containing Grails applications and plugins and it will generate a Maven multi-module build.Enabling Maven in a project has been made easier with the inclusion of the create-pom
command:grails create-app myapp
cd myapp
grails create-pom com.mycompany
mvn package
grails create-app myapp grails create-plugin plugin-a grails create-plugin plugin-b grails create-multi-project-build com.mycompany:parent:1.0-SNAPSHOT mvn install
Grails Wrapper
The Grails Wrapper allows a Grails application to build without having to install Grails and configure a GRAILS_HOME environment variable. The wrapper includes a small shell script and a couple of small bootstrap jar files that typically would be checked in to source code control along with the rest of the project. The first time the wrapper is executed it will download and configure a Grails installation. This wrapper makes it more simple to setup a development environment, configure CI and manage upgrades to future versions of Grails. When the application is upgraded to the next version of Grails, the wrapper is updated and checked in to the source code control system and the next time developers update their workspace and run the wrapper, they will automatically be using the correct version of Grails.See the Wrapper Documentation for more details.Debug Option
Thegrails
command now supports a -debug
option which will startup the remote debug agent. This behavior used to be provided by the grails-debug
command. grails-debug
is still available but is deprecated and may be removed from a future release.grails -debug run-app
Grails Command Aliases
Thealias
command may be used to define aliases for grails commands.The following command creates an alias named rit
(short for "run integration tests"):grails alias rit test-app integration:
Cache Plugin
Grails 2.1 installs the cache plugin by default. This plugin provides powerful and easy to use cache functionality to applications and plugins. The main plugin provides basic map backed caching support. For more robust caching options one of the implementation plugins should be installed and configured. See the cache-redis docs and the cache-ehcache docs for details.See the main plugin documentation for details on how to configure and use the plugin.1.2 What's new in Grails 2.0?
This section covers the new features that are present in 2.0 and is broken down into sections covering the build system, core APIs, the web tier, persistence enhancements and improvements in testing. Note there are many more small enhancements and improvements, these sections just cover some of the highlights.1.2.1 Development Environment Features
Interactive Mode and Console Enhancements
Grails 2.0 features brand new console output that is more concise and user friendly to consume. An example of the new output when running tests can be seen below:In general Grails makes its best effort to display update information on a single line and only present the information that is crucial. This means that while in previous versions of Grails the war command produced many lines of output, in Grails 2.0 only 1 line of output is produced:In addition simply typing 'grails' at the command line activates the new interactive mode which features TAB completion, command history and keeps the JVM running to ensure commands execute much quicker than otherwiseFor more information on the new features of the console refer to the section of the user guide that covers the console and interactive mode.Reloading Agent
Grails 2.0 reloading mechanism no longer uses class loaders, but instead uses a JVM agent to reload changes to class files. This results in greatly improved reliability when reloading changes and also ensures that the class files stored in disk remain consistent with the class files loaded in memory, which reduces the need to run the clean command.New Test Report and Documentation Templates
There are new templates for displaying test results that are clearer and more user friendly than the previous reports:In addition, the Grails documentation engine has received a facelift with a new template for presenting Grails application and plugin documentation:See the section on the documentation engine for more usage info.Use a TOC for Project Docs
The old documentation engine relied on you putting section numbers into the gdoc filenames. Although convenient, this effectively made it difficult to restructure your user guide by inserting new chapters and sections. In addition, any such restructuring or renaming of section titles resulted in breaking changes to the URLs.You can now use logical names for your gdoc files and define the structure and section titles in a YAML table-of-contents file, as described in the section on the documentation engine. The logical names appear in the URLs, so as long as you don't change those, your URLs will always remain the same no matter how much restructuring or changing of titles you do.Grails 2.0 even provides a migrate-docs command to aid you in migrating existing gdoc user guides.Enhanced Error Reporting and Diagnosis
Error reporting and problem diagnosis has been greatly improved with a new errors view that analyses stack traces and recursively displays problem areas in your code:In addition stack trace filtering has been further enhanced to display only relevant trace information:Line | Method
->> 9 | getValue in Book.groovy
- - - - - - - - - - - - - - - - - - - - - - - - -
| 7 | getBookValue in BookService.groovy
| 886 | runTask . . in ThreadPoolExecutor.java
| 908 | run in ''
^ 662 | run . . . . in Thread.java
H2 Database and Console
Grails 2.0 now uses the H2 database instead of HSQLDB, and enables the H2 database console in development mode (at the URI /dbconsole) so that the in-memory database can be easily queried from the browser:Plugin Usage Tracking
To enhance community awareness of the most popular plugins an opt-in plugin usage tracking system has been included where users can participate in providing feedback to the plugin community on which plugins are most popular.This will help drive the roadmap and increase support of key plugins while reducing the need to support older or less popular plugins thus helping plugin development teams focus their efforts.Dependency Resolution Improvements
There are numerous improvements to dependency resolution handling via Ivy including:- Grails now makes a best effort to cache the previous resolve and avoid resolving again unless you change
BuildConfig.groovy
. - Plugins dependencies now appear in the dependency report generated by
grails dependency-report
- Plugins published with the release plugin now publish their transitive plugin dependencies in the generated POM which are later resolved.
- It is now possible to customize the ivy cache directory via
BuildConfig.groovy
grails.project.dependency.resolution = {
cacheDir "target/ivy-cache"
}
- You can change the ivy cache directory for all projects via
settings.groovy
grails.dependency.cache.dir = "${userHome}/.ivy2/cache"
- It is now possible to completely disable resolution from inherited repositories (repositories defined by other plugins):
grails.project.dependency.resolution = { repositories {
inherits false // Whether to inherit repository definitions from plugins
…
}
…
}
- It is now possible to easily disable checksum validation errors:
grails.project.dependency.resolution = {
checksums false // whether to verify checksums or not
}
1.2.2 Core Features
Binary Plugins
Grails plugins can now be packaged as JAR files and published to standard maven repositories. This even works for GSP and static resources (with resources plugin 1.0.1). See the section on Binary plugins for more information.Groovy 1.8
Grails 2.0 comes with Groovy 1.8 which includes many new features and enhancementsSpring 3.1 Profile Support
Grails' existing environment support has been bridged into the Spring 3.1 profile support. For example when running with a custom Grails environment called "production", a Spring profile of "production" is activated so that you can use Spring's bean configuration APIs to configure beans for a specific profile.1.2.3 Web Features
Controller Actions as Methods
It is now possible to define controller actions as methods instead of using closures as in previous versions of Grails. In fact this is now the preferred way of expressing an action. For example:// action as a method def index() {} // action as a closure def index = {}
Binding Primitive Method Action Arguments
It is now possible to bind form parameters to action arguments where the name of the form element matches the argument name. For example given the following form:<g:form name="myForm" action="save"> <input name="name" /> <input name="age" /> </g:form>
def save(String name, int age) { // remaining }
Static Resource Abstraction
A new static resource abstraction is included that allows declarative handling of JavaScript, CSS and image resources including automatic ordering, compression, caching and gzip handling.Servlet 3.0 Async Features
Grails now supports Servlet 3.0 including the Asynchronous programming model defined by the specification:def index() { def ctx = startAsync() ctx.start { new Book(title:"The Stand").save() render template:"books", model:[books:Book.list()] ctx.complete() } }
Link Generation API
A general purposeLinkGenerator
class is now available that is usable anywhere within a Grails application and not just within the context of a controller. For example if you need to generate links in a service or an asynchronous background job outside the scope of a request:LinkGenerator grailsLinkGeneratordef generateLink() { grailsLinkGenerator.link(controller:"book", action:"list") }
Page Rendering API
Like theLinkGenerator
the new PageRenderer
can be used to render GSP pages outside the scope of a web request, such as in a scheduled job or web service. The PageRenderer
class features a very similar API to the render
method found within controllers:grails.gsp.PageRenderer groovyPageRenderervoid welcomeUser(User user) {
def contents = groovyPageRenderer.render(view:"/emails/welcomeLetter", model:[user: user])
sendEmail {
to user.email
body contents
}
}
PageRenderer
service also allows you to pre-process GSPs into HTML templates:new File("/path/to/welcome.html").withWriter { w -> groovyPageRenderer.renderTo(view:"/page/content", w) }
Filter Exclusions
Filters may now express controller, action and uri exclusions to offer more options for expressing to which requests a particular filter should be applied.filter1(actionExclude: 'log*') { before = { // … } } filter2(controllerExclude: 'auth') { before = { // … } }filter3(uriExclude: '/secure*') { before = { // … } }
Performance Improvements
Performance of GSP page rendering has once again been improved by optimizing the GSP compiler to inline method calls where possible.HTML5 Scaffolding
There is a new HTML5-based scaffolding UI:jQuery by Default
The jQuery plugin is now the default JavaScript library installed into a Grails application. For backwards compatibility a Prototype plugin is available. Refer to the documentation on the Prototype plugin for installation instructions.Easy Date Parsing
A newdate
method has been added to the params
object to allow easy, null-safe parsing of dates:def val = params.date('myDate', 'dd-MM-yyyy')// or a list for formats
def val = params.date('myDate', ['yyyy-MM-dd', 'yyyyMMdd', 'yyMMdd'])// or the format read from messages.properties via the key 'date.myDate.format'
def val = params.date('myDate')
Customizable URL Formats
The default URL Mapping mechanism supports camel case names in the URLs. The default URL for accessing an action namedaddNumbers
in a controller named MathHelperController
would be something like /mathHelper/addNumbers
. Grails allows for the customization of this pattern and provides an implementation which replaces the camel case convention with a hyphenated convention that would support URLs like /math-helper/add-numbers
. To enable hyphenated URLs assign a value of "hyphenated" to the grails.web.url.converter
property in grails-app/conf/Config.groovy
.// grails-app/conf/Config.groovygrails.web.url.converter = 'hyphenated'
grails.web.UrlConverter.BEAN_NAME
. If Grails finds a bean in the context with that name, it will be used as the default converter and there is no need to assign a value to the grails.web.url.converter
config property.// src/groovy/com/myapplication/MyUrlConverterImpl.groovypackage com.myapplicationclass MyUrlConverterImpl implements grails.web.UrlConverter { String toUrlElement(String propertyOrClassName) { // return some representation of a property or class name that should be used in URLs… } }
// grails-app/conf/spring/resources.groovybeans = {
"${grails.web.UrlConverter.BEAN_NAME}"(com.myapplication.MyUrlConverterImpl)
}
Web Flow input and output
It is now possible to provide input arguments when calling a subflow. Flows can also return output values that can be used in a calling flow.1.2.4 Persistence Features
The GORM API
The GORM API has been formalized into a set of classes (GormStaticApi
, GormInstanceApi
and GormValidationApi
) that get statically wired into every domain class at the byte code level. The result is better code completion for IDEs, better integration with Java and the potential for more GORM implementations for other types of data stores.Detached Criteria and Where Queries
Grails 2.0 features support for DetachedCriteria which are criteria queries that are not associated with any session or connection and thus can be more easily reused and composed:def criteria = new DetachedCriteria(Person).build { eq 'lastName', 'Simpson' } def results = criteria.list(max:4, sort:"firstName")
where
method and DSL has been introduced to greatly reduce the complexity of criteria queries:def query = Person.where { (lastName != "Simpson" && firstName != "Fred") || (firstName == "Bart" && age > 9) } def results = query.list(sort:"firstName")
New findOrCreate and findOrSave Methods
Domain classes have support for the findOrCreateWhere, findOrSaveWhere, findOrCreateBy and findOrSaveBy query methods which behave just like findWhere and findBy methods except that they should never return null. If a matching instance cannot be found in the database then a new instance is created, populated with values represented in the query parameters and returned. In the case of findOrSaveWhere and findOrSaveBy, the instance is saved before being returned.def book = Book.findOrCreateWhere(author: 'Douglas Adams', title: "The Hitchiker's Guide To The Galaxy")
def book = Book.findOrSaveWhere(author: 'Daniel Suarez', title: 'Daemon')
def book = Book.findOrCreateByAuthorAndTitle('Daniel Suarez', 'Daemon')
def book = Book.findOrSaveByAuthorAndTitle('Daniel Suarez', 'Daemon')
Abstract Inheritance
GORM now supports abstract inheritance trees which means you can define queries and associations linking to abstract classes:abstract class Media { String title … } class Book extends Media { } class Album extends Media {} class Account { static hasMany = [purchasedMedia:Media] }..def allMedia = Media.list()
Multiple Data Sources Support
It is now possible to define multiple datasources inDataSource.groovy
and declare one or more datasources a particular domain uses by default:class ZipCode { String code static mapping = { datasource 'ZIP_CODES' } }
def zipCode = ZipCode.auditing.get(42)
Database Migrations
A new database migration plugin has been designed and built for Grails 2.0 allowing you to apply migrations to your database, rollback changes and diff your domain model with the current state of the database.Database Reverse Engineering
A new database reverse engineering plugin has been designed and built for Grails 2.0 that allows you to generate a domain model from an existing database schema.Hibernate 3.6
Grails 2.0 is now built on Hibernate 3.6Bag Collections
You can now use Hibernate Bags for mapped collections to avoid the memory and performance issues of loading large collections to enforceSet
uniqueness or List
order.For more information see the section on Sets, Lists and Maps in the user guide.
1.2.5 Testing Features
New Unit Testing Console Output
Test output from the test-app command has been improved:New Unit Testing API
There is a new unit testing API based on mixins that supports JUnit 3, 4 and Spock style tests (with Spock 0.6 and above). Example:import grails.test.mixin.TestFor@TestFor(SimpleController) class SimpleControllerTests { void testIndex() { controller.home() assert view == "/simple/homePage" assert model.title == "Hello World" } }