Last updated by 1 year ago

Page: 1.0 Release Notes, Version:4

Grails 1.0 Release Notes

4th of February 2008

G2One Inc - The Groovy/Grails company - and the Grails development team are pleased to announce the 1.0 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 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.

Thank you to all the team members, patch contributors and users. Grails 1.0 has been 2 years and 8 months in the making, and many have contributed to what is a fantastic milestone.

New Features

  • GORM features ORM DSL for advanced Mappings
  • Support for easy to use Filters
  • Content Negotiation support
  • REST support
  • JNDI Support

New Features

ORM DSL

Grails 1.0 RC1 introduces an Object Relational Mapping (ORM) Domain Specific Language (DSL) that reduces the need to fallback to traditional Hibernate mapping. The DSL allows customization of the following aspects:

  • Table and column names
  • Inheritance strategy
  • Second-level cache configuration
  • Id generation strategy
  • Composide Id support
  • Eager/Lazy loading
  • Database indices
  • Custom Hibernate user types
Example:
class Person {
  String firstName
  static hasMany = [addresses:Address]
  static mapping = {
      table 'people'
      version false
      id column:'person_id'
      columns {
          firstName column:'First_Name'
          addresses lazy:false
      }
  }
}
class Address {
  String street
  String postCode
}

Refer to the full documentation here.

Filters

Grails has up until now supported interceptors that can be used within controllers. Filters however offer a more powerful way of defining cross cutting concerns.

Filters can be applied to an entire controller, only specific actions or entire URI spaces. Example:

class SecurityFilters {
   def filters = {
       loginCheck(controller:'*', action:'*') {
           before = {
              if(!session.user && !actionName.equals('login')) {
                  redirect(action:'login')
                  return false
               }
           }

} } }

Refer to the full documentation here.

Content Negotation

Grails now supports content negotiation via the Accept/Content-Type HTTP headers, a parameter or URI extensions. Mime types can be configured in Config.groovy:

grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
                      xml: ['text/xml', 'application/xml']
                      // etc.
                    ]

And requests dealt with via the withFormat method:

def list = {
    def results = Book.list()
    withFormat {
         html bookList:result
         xml { render results as XML }
    }
}

Automatic XML/JSON Unmarshalling

JSON and XML requests can now be automatically unmarshalled via the params object. Given an incoming XML request of:

<book>
    <title>The Stand</title>
    <author>Stephen King</author></book>

This can be consumed with:

def save = {
   def b = new Book(params['book'])
   if(b.save()) {
      // deal with book
   }
}

Support for Mapping Foreign Key Columns and Join Tables

Grails' ORM DSL now support mappings foreign key columns and join tables for associations. To change the foreign key of a one-to-one you can do:

class Book {
    Author author
    static mapping = {
        columns {
            author column:'auth_id'
        }
    }
}

You can also change the join table and column used for unidirectional one-to-many and many-to-many associations:

class Author {
    static hasMany = [books:Book]
    static mapping = {
        columns {
            books joinTable:[name:'authors_books', key:'book_id', column:'author_id']
        }
    }
}

JNDI Data Sources

Grails now has improved support for JNDI data sources via a {{jndiName}} property in the DataSource definition:

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