Last updated by
3 years ago
Page: 1.2-RC1 Release Notes, Version:0
Grails 1.2-RC1 Release Notes
XXX of December 2009Grails 1.2 RC1 is not out yet, this page is a placeholdergrails.project.dependency.resolution = { inherits "global" // inherit Grails' default dependencies repositories { grailsHome() mavenCentral() } dependencies { runtime 'com.mysql:mysql-connector-java:5.1.5' }}[SpringSource|http://www.springsource.com] are pleased to announce the 1.2 Release Candidate 1 release of the [Grails|http://grails.org] web application development framework.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. Further information about the release can be obtained using the links below:* Changelog: [http://jira.codehaus.org/browse/GRAILS?report=com.atlassian.jira.plugin.system.project:changelog-panel] * Download: [http://grails.org/Download] . * Documentation: [http://grails.org/doc/1.2.x] New features in 1.2 RC1 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:def init = { ServletContext ctx -> environments { production { ctx.setAttribute("env", "prod") } development { ctx.setAttribute("env", "dev") } } ctx.setAttribute("foo", "bar") }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.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|http://grails.org/doc/1.2.x/guide/6.%20The%20Web%20Layer.html#6.3.7%20Tag%20return%20value] 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 Lari Hotari for his significant contributions to Grails in this area.BootStrap environments
TheBootStrap.groovyclass now has environment support:@Controller class SpringController { @Autowired SessionFactory sessionFactory @RequestMapping("/hello.dispatch") ModelMap handleRequest() { def session = sessionFactory.getCurrentSession() return new ModelMap(session.get(Person, 1L)) }}h3. Spring 3 UpgradeGrails now also supports Spring annotation prototypes through component scanning such as @Service, @Component etc.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:"/hello"(uri:"/hello.dispatch")In this example, going to/hello.dispatchwill 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 yourgrails-app/conf/UrlMappings.groovyfile:import org.springframework.transaction.annotation.*class BookService { @Transactional(readOnly = true) def listBooks() { Book.list() } @Transactional def updateBook() { // … } }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:h3. Fine-grained control over DataSource propertiesThe DataSource.groovy file now provides control over all of the underlying DataSource bean's properties:"code">"error">code: nulldataSource { 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@:The default values for constraints is also globally configurable:grails.gorm.default.mapping = { cache true id generator:'sequence' 'user-type'( type:org.hibernate.type.YesNoType, class:Boolean ) }You can even define named constraint groups:grails.gorm.default.constraints = { '*'(nullable:true, blank:false, size:1..20) }And then reuse them inside your domain classes:grails.gorm.default.constraints = { myConstraints(nullable:true, blank:false, size:1..20) }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:You can do:class Book { String title String author Boolean paperback }In this case the boolean value is implicitly inferred from the method signature.def results = Book.findAllPaperbackByAuthor("Douglas Adams")ordef results = Book.findAllNotPaperbackByAuthor("Douglas Adams")Named Query Support
GORM now supports defining named queries in a domain class. For example, given a domain class like this:You can do:class Publication { String title Date datePublished static namedQueries = { recentPublications { def now = new Date() gt 'datePublished', now - 365 } publicationsWithBookInTitle { like 'title', '%Book%' } }}// get all recent publications… def recentPubs = Publication.recentPublications()// get all recent publications (alternate syntax)… def recentPubs = Publication.recentPublications.list()// get up to 10 recent publications, skip the first 5… def recentPubs = Publication.recentPublications(max: 10, offset: 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)Support for hasOne mapping
GORM now supportshasOnemapping where the foreign key is stored in the child instead of the parent association. For example:In the above case a foreign key column calledclass Person { String name static hasOne = [address: Address] } class Address { String street String postCode }person_idwill be created in theaddresstable rather than the default where anaddress_idis created in thepersontable.Strict Validation Errors
There is a newfailOnErrorargument available on thesave()method that will throw an exception if a validation error occurs:try { book.save(failOnError:true) }catch(ValidationException e) { // handle }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:These are then picked up by Grails' default error messages and scaffolded views.book.label = Libro book.title.label = TÃtulo del libroTomcat & 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:The Tomcat plugin comes with built in remote deployment commands:grails uninstall-plugin tomcat grails install-plugin jettygrails tomcat deploy grails tomcat undeployWeb Flow as a plugin
Grails' support for Spring Web Flow has been extracted into a plugin. To install simply type:If you are migrating from older versions of Grails and use Web Flow you will need to run the above command. If you don't wish to use Web Flow in your application you can uninstall it:grails install-plugin webflowgrails uninstall-plugin webflowNew Web Flow Events
Grails' Web Flow DSL now supports more of the common Web Flow events such asonEntry@, @onRenderand so on:def searchFlow = { onStart { println "started" } onEnd { println "ended" } displaySearchForm { onRender { println "rendering" } onEntry { println "entered" } onExit { println "exited" } on("submit") { [results: Book.findAllByTitle(params.title)] }.to "displayResults" } displayResults() }Named URL Mappings
Grails now supports named URL mappings and associated dynamic tags for view layer URL rewriting. For example:The above creates a named URL mapping called "productDetail" this can be linked to from the view with:name productDetail: "/showProduct/$productName/$flavor?" { controller = "product" action = "show" }<link:productDetail productName="licorice" flavor="strawberry">Strawberry Licorice</link:productDetail>Better JSONBuilder
JSONBuilder has been re-written, better documented and improved in general. Rendering JSON responses is now as simple as:Which will produce:render(contentType:"text/json") { categories = [ { a = "A" }, { b = "B" } ] }This is breaking change from previous versions of Grails, if you want backwards compatibility set grails.json.legacy.builder=true in Config.groovy{"categories":[ {"a":"A"} , {"b":"B"}] }nullBetter Date parsing
If you submit a date from a <g:datePicker name="foo" /> tag, obtaining theDateobject is now as simple as looking it up from theparamsobject by name (eg.params.foo)REST improvements
The <g:form> tag can now pass other methods beside POST and GET:This works by creating a hidden field called _method. Now browser clients can also pass the X-HTTP-Method-Override HTTP header<g:form method="DELETE">Project Documentation Engine
The same documentation engine that powers the Grails reference documentation is now available in your projects. Simply create your documentation inside thesrc/docs/refandsrc/docs/guidedirectories of your project. See the Grails documentation source for an example.Zip-only plugin releases
If you prefer to use Git/Mercurial/etc. to version control your plugin you can now distribute only the zipped release of the plugin in the central repository and continue to manage the actual sources outside of SVN:grails release-plugin --zipOnlyPlugin Metadata Generator
When releasing a plugin into the Grails central repository metadata is generated about the methods and properties added to Grails classes at runtime.This metadata is put into the plugin.xml descriptor and can be read by IDEs and documentation engines.If your plugin doesn't add methods at runtime you can skip the metadata generation process by doing:grails release-plugin --skipMetadataformatNumber and formatDate taglib improvements
g:formatNumber and g:formatDate taglibs are now feature compatible with JSTL formatNumber and formatDate tags.