Skip to content

Releases: grails/grails-core

Grails 1.2.0

16 Jan 08:18
Compare
Choose a tag to compare

23rd of December 2009

SpringSource are pleased to announce the 1.2 release of the Grails web application development framework.

New features in 1.2 are described below.

New Features

Dependency Resolution DSL

Grails 1.2 features a new DSL for configuring JAR dependencies that can be resolved against Maven repositories:

grails.project.dependency.resolution = {
    inherits "global" // inherit Grails' default dependencies
       repositories {
           grailsHome()
           mavenCentral()
    }
    dependencies {
          runtime 'com.mysql:mysql-connector-java:5.1.5'
    }
}

Built on Apache Ivy, users can now explicitly control how Grails resolves all of its dependencies without needing to use Maven or Apache Ivy directly.

There is also a new command to easily install dependencies into your local cache for use with the DSL:

grails install-dependency mysql:mysql-connector-java:5.1.5

Significant Performance Optimizations

GSP and the Sitemesh rendering layer have been significantly improved to offer 2 to 3 times better throughput. This was achieved by:

  • Output buffering has been refactored to a streaming approach: the minimum amount of new objects are created.
  • Tag library calls return an instance of org.codehaus.groovy.grails.web.util.StreamCharBuffer class by default.
  • Tag libraries can now return object values too. This was changed to reduce object generation.
  • Sitemesh doesn't have to parse the output coming from GSP since the head, meta, title and body tags are captured from the beginning. This is done in GSP compilation when the config param "grails.views.gsp.sitemesh.preprocess" is unset or is true.
  • Some performance improvements are the result of monitoring for unnecessary Exceptions created in Grails and preventing them from happening.

Thanks to @lhotari for his significant contributions to Grails in this area.

BootStrap environments

The BootStrap.groovy class now has environment support:

def init = { ServletContext ctx ->
   environments {
       production {
          ctx.setAttribute("env", "prod")
       }
       development {
          ctx.setAttribute("env", "dev")
       }
   }
   ctx.setAttribute("foo", "bar")
}

Spring 3 Upgrade

Grails now also supports Spring annotation prototypes through component scanning such as @Service, @Component etc.

In order to do so you need to tell Grails which packages your Spring beans are contained within in Config.groovy. For example:

  grails.spring.bean.packages = \['com.foo.stuff','com.foo.otherstuff'\]

Any class can be annotated with @Component and will automatically become a Spring bean injectable in other classes.

In addition you can annotate classes with @Controller and these will be able to handle requests just like regular Spring MVC controllers, thus providing support for those wanting to use a combination of Spring MVC and Grails:

 @Controller
 class SpringController {

       @Autowired
       SessionFactory sessionFactory

      @RequestMapping("/hello.dispatch")
      ModelMap handleRequest() {
           def session = sessionFactory.getCurrentSession()
          return new ModelMap(session.get(Person, 1L))      
      }
 }

In this example, going to /hello.dispatch will execute the handleRequest() method and atempt to render either a GSP or JSP view at grails-app/views/hello.(jsp|gsp)

URI Re-writing onto any URI

You can now re-write any request URI onto any other URI using the following syntax in your grails-app/conf/UrlMappings.groovy file:

 "/hello"(uri:"/hello.dispatch")

This feature can be used to provide pretty URIs for Spring MVC controllers (see above) or static resources.

Per-method transactions with @transactional

Building on the component scanning features you can now use the Spring org.springframework.transaction.annotation.Transactional annotation on Grails service classes to configure transaction properties and have per-method transaction definitions:

  import org.springframework.transaction.annotation.*

  class BookService {
       @Transactional(readOnly = true)
       def listBooks() {
           Book.list()
       }

      @Transactional
      def updateBook() {
          // ...
      }
 }

{code}

Fine-grained control over DataSource properties

The DataSource.groovy file now provides control over all of the underlying DataSource bean's properties:

 dataSource {
     pooled = true
     dbCreate = "update"
     url = "jdbc:mysql://localhost/yourDB"
     driverClassName = "com.mysql.jdbc.Driver"
     username = "yourUser"
     password = "yourPassword"
     properties {
         maxActive = 50
         maxIdle = 25
         minIdle = 5
         initialSize = 5
         minEvictableIdleTimeMillis = 60000
         timeBetweenEvictionRunsMillis = 60000
         maxWait = 10000
   }
}

Global Configuration of GORM defaults

GORMs default mapping settings are now globally configurable inside @grails-app/conf/Config.groovy@:

  grails.gorm.default.mapping = {
      cache true
      id generator:'sequence'
      'user-type'( type:org.hibernate.type.YesNoType, class:Boolean )
  }

The default values for constraints is also globally configurable:

  grails.gorm.default.constraints = {
       '*'(nullable:true, blank:false, size:1..20)
  }

You can even define named constraint groups:

 grails.gorm.default.constraints = {
      myConstraints(nullable:true, blank:false, size:1..20)
 }

And then reuse them inside your domain classes:

 static constraints = {
      myProperty shared:"myConstraints"
 }

Improved Dynamic Finders for Boolean properties

GORM dynamic finders have been improved with an easier notation for handling boolean properties. For example given a domain class of:

  class Book {
      String title
      String author
      Boolean paperback
 }

You can do:

   def results = Book.findAllPaperbackByAuthor("Douglas Adams")

or

  def results = Book.findAllNotPaperbackByAuthor("Douglas Adams")

In this case the boolean value is implicitly inferred from the method signature.

Named Query Support

GORM now supports defining named queries in a domain class. For example, given a domain class like this:

  class Publication {
           String title
           Date datePublished

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

              publicationsWithBookInTitle {
                 like 'title', '%Book%'
              }
           }
  }

You can do:

  // get all recent publications
  def recentPubs = Publication.recentPublications.list()

  // get up to 10 recent publications, skip the first 5...
  def recentPubs = Publication.recentPublications.list(max: 10, offset: 5)

  // get the number of recent publications...
  def numberOfRecentPubs = Publication.recentPublications.count()

  // get a recent publication with a specific id...
  def pub = Publication.recentPublications.get(42)

  // dynamic finders are supported
  def pubs = Publication.recentPublications.findAllByTitle('Some Title')

Support for SQL restriction in criteria builder

The criteria builder now supports arbitrary SQL expressions:

  def c = Person.createCriteria()

  def peopleWithShortFirstNames = c.list {
      sqlRestriction "char_length( first_name ) <= 4"
  }

Support for hasOne mapping

GORM now supports @hasone@ mapping where the foreign key is stored in the child instead of the parent association. For example:

  class Person { 
     String name 
     static hasOne = [address: Address]
  }
  class Address {
     String street
     String postCode
  }

In the above case a foreign key column called @person_id@ will be created in the @address@ table rather than the default where an @address_id@ is created in the @person@ table.

Strict Validation Errors

There is a new @failOnError@ argument available on the @save()@ method that will throw an exception if a validation error occurs:

  try {
     book.save(failOnError:true)
  }
  catch(ValidationException e) {
     // handle
  }

Improved support for annotated entities

You can now use annotated entities instead of the GORM syntax inside domains located in grails-app/domain. These entities can use Grails constraints and events just like normal GORM entities for those who prefer annotations over GORM syntax:

  import javax.persistence.*

  @Entity
  @Table(name = "animal")
  class Animal {

     @Id @GeneratedValue
     int id
     String name
     @ManyToOne
     @JoinColumn
     Owner owner

     static constraints = {
        name blank:false
     }
  }

Precompilation of Groovy Server Pages in WAR deployment

GSPs are now pre-compiled when producing a WAR file meaning less permgen space is used at deployment time for Grails applications.

Improved handling of i18n class and property names

You can now put entries in your i18n messages.properties file for all class and property names in your application. For example:

  book.label = Libro
  book.title.label = Título del libro

These are then picked up by Grails' default error messages and scaffolded views.

Tomcat & Multiple Embedded Containers Supported

Grails now supports multiple embedded containers with Tomcat being the default. Grails will by default install the Tomcat plugin into your application. You can easily switch containers by switching plugins:

  grails uninstall-plugin tomcat
  grails install-plugin jett...
Read more

Grails 1.1.2

16 Jan 07:55
Compare
Choose a tag to compare

Further information about the release can be obtained using the links below:

Grails 1.1.1

16 Jan 07:50
Compare
Choose a tag to compare

Further information about the release can be obtained using the links below:

For Windows users, if you get a java.lang.NoClassDefFoundError: org/codehaus/gant/GantBinding be advice; do not download TAR/GZ, but ZIP instead (it seems like some scripts are different somehow)

New features in 1.1.1 are described below. Also see the article and screencast demonstrating AppEngine support on the SpringSource teamblog.

New Features

Google AppEngine Support

Grails applications can now be deployed to Google AppEngine using Grails 1.1.1 and the Grails [AppEngine plugin|http://grails.org/plugin/app-engine]. Refer the to the plugin documentation for more information.

Secured Plugin Repositories

You can now configure secure plugin repositories in @~/.grails/settings.groovy@ or @grails-app/conf/BuildConfig.groovy@ for example:

 grails.plugin.repos.discovery.myRepo="https://user01:[email protected]"

Improved GSP Performance

Groovy Server Pages (GSP) is now around 30% over performance in 1.1 resulting in an overall performance boost for Grails.