Last updated by 2 years ago

Page: 1.4.0.M1 Release Notes, Version:6

Grails 1.4.0.M1 Release Notes

24th of May 2011 - Grails is a dynamic web application framework built on Java and Groovy, leveraging best of breed APIs from the Java EE 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.

New Features & Improvements

Upgraded Libraries

Grails 1.4 comes with Spring 3.1 M1, Groovy 1.8, Hibernate 3.6, Servlet 3.0 and Tomcat 7.0

Binary Plugins

Plugins can now be packaged as JAR files using the -binary flag of the package-plugin command:

$ grails package-plugin --binary

This will create a jar file from a Grails plugin with the sources pre-compiled into byte code. A dependency on the plugin can be declared in BuildConfig like any other JAR dependency.

See the documentation on binary plugins for further info.

Reloading Agent

There is a new JVM-agent that handles reloading of classes making it possible to reload changes to domain classes, statically typed services and more cases that weren't supported before.

Plugin Usage Tracking

A new optional system for users to report plugin usage is integrated into Grails. The statistics of the most used plugins will soon be published on the Grails website based on this information.

Improved Scaffolding UI

There is a new HTML5 enhanced scaffolding UI

New Test Report and Documentation Templates

Test reports and documentation look better in Grails 1.4, thanks to new templates

Integration of the resources plugin into Grails core

The resources plugin is now fully integrated making it even easier to serve websites with optimized static resource handling (caching, gzipping, bundling etc.)

See the documentation on using the advanced static resource handling for more information.

Better Unit Testing

The section on unit testing in the user guide has been completely re-written based on new support for unit test mixins that work in JUnit 3, JUnit 4 and Spock (0.6 of spock required).

Unit testing has been greatly simplified for all artifact types. Example:

// Test class
class SimpleController {
    def home() {
        render view:"homePage", model:[title:"Hello World"]
    }
    …
}
void testIndex() {
    controller.home()

assert view == "/simple/homePage" assert model.title == "Hello World" }

Included in this release is support for unit testing of filters, URL mappings, file uploads, content negotiation, template/view rendering and criteria queries (all of which required integration tests previously)

See the hugely improved documentation on unit testing for further info.

Abstract Inheritance Support in GORM

GORM now supports abstract inheritance trees which means you can define queries and associations linking to abstract classes:

abstract Media {
     String title
     …
}
class Book extends Media {

} class Album extends Media {

} class Account { static hasMany = [purchasedMedia:Media] }

..

def allMedia = Media.list()

GORM API now available to Java (and other static languages)

The GORM API is now injected in the bytecode of GORM entities via Groovy transformations. This means many GORM methods are visible and calling from Java code (excuse the semi-colons):

Book book = new Book();
book.setTitle("The Stand")
book.save();

System.out.println(Book.count()); System.out.println(Book.list());

Attributes On link Namespace Tags

Tags in the link namespace now support an attrs attribute.

<link:accountDetails attrs="[class: 'fancy']" acctNumber="8675309">Show Account</link:accountDetails>

With a URL mapping like this:

"/details/$acctNumber"(controller: 'account', action: 'showAccount')
  ...

That would result in:

<a href="/details/8675309" class="fancy">Show Account</a>

H2 Database Engine

Grails now includes H2 as the default database for new applications in place of HSQL.

Support For Calling Association Named Queries

When a named query involves a domain class relationship and the relationship class defines a named query, that named query may be accessed directly as a method call. An example:

class Author {

static hasMany = [publications:Publication]

static namedQueries = { authorsWithRecentPublications { publications { // invoking a named query defined in the Publication class… recentPublications() } } } }

class Publication {

Author author

static namedQueries = { recentPublications { def now = new Date() gt 'datePublished', now - 10 } } }

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 = { // … } }

Shared Constraints And Command Objects

Command objects now support the application of shared constraints using the same technique previously supported with domain classes.

New OrCreate and OrSave Queries

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')

Automatic Updating of SNAPSHOT dependencies and plugins

Grails now checks for new releases of all dependencies and plugins that have a version number that ends with “SNAPSHOT” and will automatically download the newer version if one is available and install it.

Support for permanent (301) redirects

The redirect() method now accepts a permanent parameter that if true will result in the redirect being issued with a 301 HTTP status code, as opposed to the usual 302 HTTP status code.

Breaking Changes and Deprecations in 1.4

  • The OpenRicoBuilder has been removed
  • The JsonBuilder class deprecated in favour of grails.web.JSONBuilder has been removed
  • All static holders are deprecated (ConfigurationHolder, ApplicationHolder, PluginManagerHolder, BuildSettingsHolder etc.)
  • Abstract base classes extended by GORM entities must go into src/groovy if they are not to be regarded as persistent
  • Criteria query joins are now INNER joins instead of LEFT joins by default
  • Public methods in controllers are now treated as actions, so you may want to make those methods private or protected.
  • 'count' is no longer a valid domain class property.
  • The 'release-plugin' command has been removed - use 'publish-plugin' from the new Release plugin instead.
  • The g:resource tag may now throw a FileNotFoundException if the resources plugin is also installed. This can happen if the resource you link to does not exist. Without resources framework installed, the URI to the non-existent resource will be rendered.
  • The redirect() method no longer commits the response, allowing extra headers to be added after the redirect() call. Code that relies on response.isCommitted() may break and will need to change to use request.isRedirected()
  • The redirect() method also uses the grails.serverURL setting if provided. The default value in Config.groovy hard codes the port number to 8080, so running the server on a different port will break redirects. In this case, remove the grails.serverURL setting from the development and test environments.
  • The withFormat(Closure) method no longer inspects the CONTENT_TYPE header but now deals exclusively with the response format via the file extension, format parameter or ACCEPT header. There is a new request.withFormat(Closure) method to deal with the request format as defined by the CONTENT_TYPE header
  • The default applicationContext.xml has changed, so be sure to run grails upgrade on existing projects.