1.1 What's new in Grails 2.4? - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 2.4.4
1.1 What's new in Grails 2.4?
Groovy 2.3
Grails 2.4 comes with Groovy 2.3 which includes many new features and enhancements.For more information on Groovy 2.3, see the comprehensive release notes.Spring 4.0
Grails 2.4 comes with Spring 4.0.4 which includes many new features and enhancements. See the Spring documentation.Hibernate 4.3
Grails 2.4 now uses Hibernate 4.3.5 by default (Hibernate 3 is still available as an optional install).Standalone GORM and GSP
GORM and GSP can now be used outside of Grails. See the following guides / examples for more information:The Asset-Pipeline replaces Resources to serve static assets.
The asset-pipeline provides a new, easier to manage, faster means of managing your JavaScript, CSS, and images, while also bringing compiled client languages in to the fray as first-class citizens (e.g. CoffeeScript, LESS, SASS).All your assets should now live in thegrails-app/assets subfolders. Three folders are made for you by default:
- javascript
- stylesheets
- images
//= require jquery
//= require_self
//= require file_a
//= require_tree .console.log('some javascript');<asset:javascript src="application.js"/> <asset:stylesheet href="application.css"/> <asset:image src="grails_logo.png" height="60" />
Static Compilation
Groovy is a dynamically dispatched, dynamically typed language by default but also has great support for static type checking and static compilation. See these notes on Groovy static compilation. In general, Grails supports Groovy's static compilation but there are a lot of special situations which are common in a Grails app which cannot be statically compiled. For example, if a method marked with@CompileStatic contains code which invokes a GORM dynamic finder the code will not compile because the Groovy compiler cannot verify that the dynamic finder is valid. Grails 2.4 improves on this by allowing code to be statically compiled and still do things like invoke GORM dynamic finders.The grails.compiler.GrailsCompileStatic annotation behaves much like the groovy.transform.CompileStatic annotation and provides special handling to recognize Grails specific constructs.The following controller is marked with @GrailsCompileStatic. All of the code that can be statically compiled will be statically compiled. When the compiler encounters code which can not be statically validated, normally that would result in a compile error. The Grails compiler will allow certain things to be considered valid and dynamically dispatch those instructions.// grails-app/controllers/com/demo/PersonController.groovy package com.demoimport grails.compiler.GrailsCompileStatic@GrailsCompileStatic class PersonController { def showKids() { def kids = Person.findAllByAgeLessThan(16) // … } }
import grails.compiler.GrailsCompileStatic import groovy.transform.TypeCheckingMode@GrailsCompileStatic class SomeClass { def update() { // this method will be statically compiled } @GrailsCompileStatic(TypeCheckingMode.SKIP) def save() { // this method will not be statically compiled } def delete() { // this method will be statically compiled } }
More Advanced Subqueries in GORM
The support for subqueries has been extended. You can now usein with nested subqueries:def results = Person.where {
firstName in where { age < 18 }.firstName
}.list()def results = Person.withCriteria {
notIn "firstName", Person.where { age < 18 }.firstName
}def results = Person.where {
age > where { age > 18 }.avg('age')
}def employees = Employee.where {
region.continent in ['APAC', "EMEA"]
}.id()def results = Sale.where {
employee in employees && total > 100000
}.employee.list()def query = Employee.where {
def em1 = Employee
exists Sale.where {
def s1 = Sale
def em2 = employee
return em2.id == em1.id
}.id()
}
def results = query.list()GORM for Hibernate in Unit tests
It is no longer necessary to create integration tests in order to test GORM interactions with Hibernate. You can now instead useHibernateTestMixin:import grails.test.mixin.TestMixin import grails.test.mixin.gorm.Domain import grails.test.mixin.hibernate.HibernateTestMixin import spock.lang.Specification @Domain(Person) @TestMixin(HibernateTestMixin) class PersonSpec extends Specification { void "Test count people"() { expect: "Test execute Hibernate count query" Person.count() == 0 sessionFactory != null transactionManager != null session != null } }
dependencies {
test "org.grails:grails-datastore-test-support:1.0-grails-2.4"
}plugins {
runtime ':hibernate4:4.3.5.4'
}Views For Namespaced Controllers
The views for namespaced controllers may now be defined in thegrails-app/views/<namespace name>/<controller name>/ directory. See the Models And Views section for more details.Improved Programmatic Transactions
Transaction attributes may now be specified when invokingwithTransaction.// the keys in the Map must correspond to properties
// of org.springframework.transaction.support.DefaultTransactionDefinitionAccount.withTransaction([propagationBehavior: TransactionDefinition.PROPAGATION_REQUIRES_NEW,
isolationLevel: TransactionDefinition.ISOLATION_REPEATABLE_READ]) {
// …
}New Maven Plugin
The Maven plugin has been rewritten to use Aether for dependency resolution and can now be used with both Grails 2.3.x and Grails 2.4.x without releasing a new version of the plugin.This means that the Maven plugin version number is no longer tied to the version number of Grails and new releases of the Maven plugin will not come out with each new Grails release. Instead, users can continue to use the 2.4.0 version of the plugin for any version of Grails going forward.Unit Testing improvements
There is a Grails "unit testing runtime" that is based on the previous TestMixin based solution. It now separates the TestMixin classes and the actual runtime that handles the lifecycle of the Grails unit testing runtime. State of the runtime is not kept in static fields of the TestMixin classes anymore. The Groovy AST transformation behind the TestMixin annotation integrates to JUnit and Spock test classes by adding JUnit Rule fields to the class. In the previous solution, Before/BeforeClass and After/AfterClass annotations on AST added mix-in methods were used for the integration.Some of the main features:- The programming model remains the same for unit testing of Grails applications
- Setup/teardown method ordering is now deterministic because the integration is now using a single JUnit Rule field and the test runtime uses eventing internally to setup and teardown resources
- There are doWithSpring and doWithConfig callbacks for unit tests - these callback methods get called before the grailsApplication instance in the unit test runtime gets initialized.
- It's possible to register a Spock Mock as a bean to the application context of the Grails unit test runtime application - you can replace a collaborator bean with a mock
- It's possible to reuse a single application context for several test classes and control that so that tests can be made faster when required
- The Grails unit testing runtime has an event-based plugin architecture. It's possible to add new test runtime "features" with new test runtime plugin classes. The test runtime plugin API is due to change. Changes will be made based on feedback from the Grails community. The main interfaces of the API are currently documented in the javadocs: TestPlugin, TestEventInterceptor and TestEvent. Custom test plugins are currently limited since there isn't a solution for scanning for available test plugins. It's now possible to add custom test plugins in a static initialization block of a test class by calling TestRuntimeFactory.addPluginClass .
Improved Unit Testing Support For allowedMethods
The allowedMethods property is now respected in unit tests.// grails-app/controllers/com/demo/DemoController.groovypackage com.democlass DemoController { static allowedMethods = [save: 'POST', update: 'PUT', delete: 'DELETE'] def save() {
render 'Save was successful!'
} // …
}// test/unit/com/demo/DemoControllerSpec.groovy package com.demoimport grails.test.mixin.TestFor import spock.lang.Specification import static javax.servlet.http.HttpServletResponse.*@TestFor(DemoController) class DemoControllerSpec extends Specification { void "test a valid request method"() { when: request.method = 'POST' controller.save() then: response.status == SC_OK response.text == 'Save was successful!' } void "test an invalid request method"() { when: request.method = 'DELETE' controller.save() then: response.status == SC_METHOD_NOT_ALLOWED } }

