Archive for November, 2011

This Week in Grails (2011-47)

Monday, November 28th, 2011

Rob Fletcher wrote a very interesting post about his frustration with functional testing. It’s long but a good read, especially if you’ve done a fair bit of functional testing yourself. Also check out Luke Daley’s reply.

If you’re not a subscriber of the Groovy-Dev mailing list you should check out this thread on static compilation. There are a lot of replies (over 50) and it gets rather technical but it’s fascinating stuff.

This is old news (from two weeks ago) but it’s new to me; the Grails-based myBalsamiq has officially launched. It’s a cool-looking tool for doing collaborative UI mockups.


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There were no new plugins released but 17 updated:

  • browser-detection version 0.3. Provides a service and tag library for browser detection
  • fixtures version 1.1. Load test data via a convenient DSL
  • gemfire version 1.0.0.M4. The GemFire plugin provides integration with the GemFire in-memory distributed data management platform.
  • grails-ui version 1.2.2. Provides a standard UI tag library for ajaxy widgets using YUI
  • gwt version 0.6. Incorporates GWT into Grails
  • hibernate-search version 0.2. Integrates Hibernate Search for domain classes
  • jquery version 1.7. Integrates jQuery
  • knockoutjs version 1.2.1.2. Provides necessary Javascript files for using Knockoutjs (http://knockoutjs.com/)
  • notifications version 0.2.6. Implements a publish-subscribe model to push information to subscribers through different communication channels
  • scala version 0.6.4. Allows you to compile Scala sources in the /src/java and /src/scala folders of your application
  • spreadshirt version 0.6. Wrapper for the Spreadshirt API
  • spring-security-saml version 1.0.0.M7. SAML 2.x support for the Spring Security Plugin
  • spring-social-core version 0.1.31. Allows you to connect your applications with Software-as-a-Service (SaaS) providers such as Facebook and Twitter
  • spring-social-twitter version 0.1.31. Connect your applications with Twitter
  • svn version 1.0.0. Provides SVNKit as a dependency; an SvnClient class that makes it easier to work with Subversion; and integration with the Release plugin
  • webxml version 1.3. Add additional features to your web.xml, such as Filters, Config Listeners or Context Parameter definitions
  • zkui version 0.5.M2. Seamlessly integrates ZK with Grails’ infrastructures; uses the Grails’ infrastructures such as GSP, controllers rather than zk’s zul as in ZKGrails plugin

Interesting Tweets

User groups and Conferences



This Week in Grails (2011-46)

Sunday, November 20th, 2011

Devoxx and the first Australian Gr8Conf were this week, and both generated a lot of Twitter activity – see #gr8conf and #devoxx.

Be sure to get your ticket for the Groovy & Grails eXchange in London if you haven’t already, it’s coming up in just 3 weeks.

I wrote a couple more blog posts; check out Hibernate Bags in Grails 2.0 and Dynamic Controllers in Grails

I heard a rumor that Grails 2.0 RC2 might be released this week 🙂


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There were 3 new plugins released:

  • bb version 0.4. Support bb codes with KefirBB
  • simple-captcha version 0.7.1. Creates simple image CAPTCHAs that protect against automated completion and submission of HTML forms
  • jquery-bvalidator version 0.55.1. Plugin form validator for jQuery resource files

and 17 updated plugins:

  • aws version 1.2.12.1. Provide easy access to simpler functions of Amazon Web Services (AWS)
  • codenarc version 0.16.1. Static code analysis for Groovy
  • concordion version 0.1.1. Provides a convenient integration between the Concordion framework —an open source tool for writing automated acceptance tests in Java— and Grails applications
  • db-reverse-engineer version 0.4. Reverse-engineers a database to Grails domain classes.
  • drools-gorm version 0.5.5. Integrates Drools 5.2 and jBPM 5 and provides persistent storage using GORM
  • dynamic-controller version 0.3. Supports controller mixins, where action closures are retrieved from various sources including existing controllers, files, database source, etc. Can also create full controllers dynamically
  • jesque version 0.2.0. Groovier approach to using jesque
  • jesque-web version 0.2.0. Web interface to view and manage jesque queues, jobs and workers
  • joda-time version 1.3. Integrates the Joda Time date/time library into Grails
  • jquery-mobile version 1.0.3. Provides jQuery mobile framework resource files
  • markdown version 1.0.0.RC1. A tag library and service support for markdown
  • new-doc version 0.3.1. A backport of the additional functionality offered in the doc command in Grails 2.0.x
  • spring-security-saml version 1.0.0.M5. SAML 2.x support for the Spring Security Plugin
  • spring-social-core version 0.1.30. Allows you to connect your applications with Software-as-a-Service (SaaS) providers such as Facebook and Twitter
  • spring-social-twitter version 0.1.30. Connect your applications with Twitter
  • uploadr version 0.5.4. HTML5 Drag and Drop file uploader
  • wicket version 1.4.9. Use the Wicket framework as an alternative view rendering technology

Interesting Tweets

User groups and Conferences



Dynamic Controllers in Grails

Friday, November 18th, 2011

When I was working on the app-info plugin I was thinking about making it a modular plugin like I was then planning for the Spring Security plugins. In particular I wanted to keep the Hibernate aspects separate, but also make it convenient for other plugins to bolt onto this one and add extra pages. That led to the development of the dynamic-controller plugin which lets you create virtual controllers from various sources, breaking out of the restriction that controllers have to follow the standard Grails conventions (i.e. it has to be under grails-app/controllers, has to be written in Groovy, the name has to end in “Controller”, etc.)

I’ve seen reports that this wasn’t working in Grails 2.0, so I started looking at what the issues were. It turns out they were minor so I released version 0.3 today; it works with Grails 1.3 or 2.0 applications. While I was testing it I discovered that I had done a bad job documenting how to use it (and I couldn’t find the test application I used when developing it) so I had to re-learn how to use my own plugin. Doh.

How it works

The process is similar to an AOP mixin, where an existing controller is augmented with one or more additional actions. The plugin is flexible in how these actions are defined; currently you can create a ControllerMixin, “link” an action from an existing controller, or load a Closure from the database or a Resource (e.g. a file in the classpath). And you’re free to create your own source; just implement the ClosureSource interface or extend AbstractClosureSource.

In addition, you don’t even need an existing destination controller to mix into. If you declare the destination class and it doesn’t exist, the plugin will compile one for you and mix into that.

Controller Mixins

The easiest and most intuitive approach is to create a ControllerMixin. The plugin adds the grails-app/controllerMixins folder when it’s installed, and you create classes there like regular controllers. You define actions as Closures and have access to all of the MetaClass methods and properties added to “real” controllers (e.g. params, request, response, render, redirect, etc.). Dependency injection and reloading are also supported since a ControllerMixin is a custom Artifact.

While testing I also noticed that you can define actions in a ControllerMixin as methods in a Grails 1.3 application like you can in Grails 2.0. This is because the plugin only works with Closures, so to support Grails 2.0 method actions I create a Closure that calls the method, so it works in any supported version of Grails.

You need to define the destination(s) for each mixin, and this is done in Config.groovy. The syntax is a Map, where the keys are the full class name of the mixin, and the values are either a single String or a list of Strings defining which controller(s) to mix into.

For example with this configuration:

grails.plugins.dynamicController.mixins = [
   'test.FooControllerMixin': 'com.myapp.SomeController',
   'test.BarControllerMixin': ['com.myapp.SomeController',
                               'com.myapp.OtherController']
]

all of the actions in FooControllerMixin will be added to SomeController (and available under /appname/some/... URLs), and all of the actions of BarControllerMixin will be mixed into both SomeController and OtherController (available under /appname/some/... and /appname/other/... URLs). If SomeController and OtherController exist they’ll be added to, and if not they’ll be generated in-memory.

Linking to existing Controller Actions

Another option is to link to existing controller actions. This is a bit more work since it’s done programmatically; BootStrap.groovy is probably the best place to do this. You need access to the GrailsApplication but that’s easy to dependency-inject into BootStrap.groovy.

So given this existing controller:

package com.yourapp

class MyController {

   def actionAsClosure = {
      ...
   }

   def actionAsMethod() {
      ...
   }
}

you would link its actions into com.myapp.OtherController like this:

import com.burtbeckwith.grails.plugins.dynamiccontroller.ControllerClosureSource
import com.burtbeckwith.grails.plugins.dynamiccontroller.DynamicControllerManager

class BootStrap {

   def grailsApplication

   def init = { servletContext ->

      def controllerClassClosures = [
         foo: new ControllerClosureSource(
              SourceController.name, 'actionAsClosure', grailsApplication),

         bar: new ControllerClosureSource(
              SourceController.name, 'actionAsMethod', grailsApplication)
      ]

      DynamicControllerManager.registerClosures(
              'com.myapp.OtherController',
              controllerClassClosures, null, grailsApplication)
   }
}

The keys of the controllerClassClosures Map are the destination action names (they can be the same as the original or different – your choice) and the values are ControllerClosureSource instances that declare the class and action name to link.

Then just call DynamicControllerManager.registerClosures with the name of the destination controller and the map you created.

This will create new /appname/other/foo and /appname/other/bar URLs.

Actions stored in a database

You can also define action Closures as source code saved in a database table. The default implementation of the ClosureSource is DatabaseClosureSource and it expects that the table name is “closures” and that there are “action” and “controller” columns to specify the destination action name and controller class, and a “closure” column to hold the code. You can customize this by using your own subclass of DatabaseClosureSource or creating your own.

To make working with database records easier you can create a domain class that has the expected table and column names, e.g.

package com.yourapp

class DatabaseClosure {

   String action
   String controller
   String closure

   static mapping = {
      table 'closures'
      closure type: 'text'
   }
}

This is completely optional, and you can use JDBC or whatever you want to manage the database records. Note that the class name doesn’t matter since the table name is specified in the mapping block.

Database closures are parsed using a ConfigSlurper, which means they can be environment-aware if you like. So for example if you insert this data:

String closure = '''
environments {
   development {
      foo = {
         ...
      }
   }
   test {
      foo = {
         ...
      }
   }
   qa {
      foo = {
         ...
      }
   }
   production {
      foo = {
         ...
      }
   }
}
'''

new DatabaseClosure(action: 'actionName',
                    controller: 'com.myapp.OtherController',
                    closure: closure).save()

then the correct version for the current environment will be used (even with a custom environment like “qa”).

This example will create a new /appname/other/foo URL.

You don’t have to use environments though:

String closure = '''
foo = {
   ...
}
'''

new DatabaseClosure(action: 'actionName',
                    controller: 'com.myapp.OtherController',
                    closure: closure).save()

Once you have your closures defined in the database, you register them with DatabaseClosureSource.registerAll, typically in BootStrap.groovy:

import com.burtbeckwith.grails.plugins.dynamiccontroller.DatabaseClosureSource

class BootStrap {

   def dataSource
   def grailsApplication

   def init = { servletContext ->
      DatabaseClosureSource.registerAll dataSource, grailsApplication
   }
}

Resource-based actions

The final option that comes with the plugin is loading actions from text files or other resources. Like the database option above, the files are parsed with ConfigSlurper so they’re also environment-aware. The files can be in any reachable location that can be referenced as a org.springframework.core.io.Resource, with the most likely case being a org.springframework.core.io.ClassPathResource. This lets you to have actions defined in regular text files.

You can declare as many actions per file as you want. If you put them in src/java or grails-app/conf they’ll get copied into the classpath, so that’s your best bet. You could also store them in a jar file.

For example, if you have a file named resourceClosures.txt in the src/java/com/yourcompany folder with this content:

foo = {
   ...
}

bar = {
   ...
}

then you can register them in BootStrap.groovy like this:

import org.springframework.core.io.ClassPathResource

import com.burtbeckwith.grails.plugins.dynamiccontroller.DynamicControllerManager

class BootStrap {

   def grailsApplication

   def init = { servletContext ->

      DynamicControllerManager.registerClosures(
           'com.myapp.OtherController',
           new ClassPathResource('com/yourcompany/resourceClosures.txt'),
           null, grailsApplication)
   }
}

then the two actions will be available as /appname/other/foo and /appname/other/bar.


Check out the plugin page or the source code. Let me know if you find a creative use for this plugin.

This Week in Grails (2011-45)

Monday, November 14th, 2011

Groovy 1.8.4 and a beta of Groovy 2.0 (renamed from Groovy 1.9) were released this week. Check out Guillaume’s post on what’s new, including static type checking and support for Java 7’s invokedynamic.

Peter Ledbrook did a webinar on new features in Grails 2.0 (“Better Productivity: Grails 2.0”) and you can watch it here.

I wrote a few posts this week; it seems weird to write “real” posts instead of just these summaries 🙂 Check out Accessing the GrailsApplication and ApplicationContext from domain classes without holders, Overriding Groovy constructors, and Create your own Grails holder class.


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There were no new plugins released, but 12 were updated:

  • atmosphere version 0.4.1.2. Provides integration with the Atmosphere project, a portable AjaxPush/Comet and WebSocket framework
  • clover version 3.1.2. Integrates the Clover code coverage tool
  • code-coverage version 1.2.5. Generates code coverage reports using Cobertura
  • cxf-client version 1.2.2. Use existing (or new) Apache CXF wsdl2java generated content to invoke SOAP services
  • sanitizer version 0.7.0. Sanitizes markup(HTML, XHTML, CSS) using OWASP AntiSamy Filters
  • spring-security-twitter version 0.4. Twitter authentication as extension to the Spring Security Core plugin
  • struts-menu version 1.2. Basic Grails wrapper for Struts Menu
  • taggable version 1.0.1. Adds support for associating tags with domain classes
  • uploadr version 0.5.2. HTML5 Drag and Drop file uploader
  • website-optimizer version 0.2.1. Provides tags to easily integrate Google Website Optimizer experiments into your Grails application
  • yui-minify-resources version 0.1.4. Minifies static css and js resources using the YUI Compressor library
  • zkui version 0.5.M1. Seamlessly integrates ZK with Grails’ infrastructures; uses the Grails’ infrastructures such as GSP, controllers rather than zk’s zul as in ZKGrails plugin

Interesting Tweets

Jobs



User groups and Conferences



Hibernate Bags in Grails 2.0

Monday, November 14th, 2011

When I’ve talked in the past about collection mapping in Grails (you can see a video of a SpringOne/2GX talk here) I mentioned that the current approach of using Sets or Lists is problematic and provided workarounds. I mentioned at the time that Hibernate has support for Bags which don’t enforce uniqueness or order like Sets and Lists do, so if GORM supported Bags we could just use those. So I added support for Bags to GORM for Grails 2.0 and thought that was that.

I thought it’d be interesting to demo this at my GORM talk at this year’s SpringOne/2GX but when I created a small test application it wasn’t working like I remembered. In fact it was actually worse than the problems I was working around. So I put that away with a mental note to get back to this soon, and before 2.0 final is released.

It turns out there’s good news and bad news. The good news is that it’s not completely broken. The bad news is that it’s mostly broken.


First the good news. If you have a one-to-many that doesn’t use a join table, using a Bag works mostly as expected. As an example, consider an Author/Book mapping where a book has one author, and an author can have many books:

class Author {
   String name
   Collection books
   static hasMany = [books: Book]
}
class Book {
   String title
   static belongsTo = [author: Author]
}

Using the Map syntax for the belongsTo mapping is the key to avoiding the join table and relating the tables with a foreign key from the book table to the author table. If you run grails schema-export the output will be something like

create table author (
   id bigint generated by default as identity,
   version bigint not null,
   name varchar(255) not null,
   primary key (id)
);

create table book (
   id bigint generated by default as identity,
   version bigint not null,
   author_id bigint not null,
   title varchar(255) not null,
   primary key (id)
);

alter table book add constraint FK2E3AE9CD85EDFA
foreign key (author_id) references author;

If you run this initializing code in a Grails console with SQL logging enabled (add logSql = true in DataSource.groovy)

def author = new Author(name: 'Hunter S. Thompson')
author.addToBooks(title: 'Fear and Loathing in Las Vegas')
author.save()

you’ll see output like this:

insert into author (id, version, name) values (null, ?, ?)

insert into book (id, version, author_id, title) values (null, ?, ?, ?)

update author set version=?, name=? where id=? and version=?

which is ok; it inserts the author and the book, although it bumps the version of the Author. I’ll come back to that.

If you run this updating code:

def author = Author.get(1)
author.addToBooks(title: "Hell's Angels: A Strange and Terrible Saga")
author.save()

you’ll see output like this:

select author0_.id as id0_0_, author0_.version as version0_0_,
author0_.name as name0_0_ from author author0_ where author0_.id=?

insert into book (id, version, author_id, title) values (null, ?, ?, ?)

update author set version=?, name=? where id=? and version=?

This is also basically ok – it loads the author, inserts the book, and versions the author.

If you map the belongsTo with the non-map syntax (static belongsTo = Author) you’ll get this DDL:

create table author (
   id bigint generated by default as identity,
   version bigint not null,
   name varchar(255) not null,
   primary key (id)
);

create table author_book (
   author_books_id bigint,
   book_id bigint
);

create table book (
   id bigint generated by default as identity,
   version bigint not null,
   title varchar(255) not null,
   primary key (id)
);

alter table author_book add constraint FK2A7A111D3FA913A
foreign key (book_id) references book;

alter table author_book add constraint FK2A7A111DC46A00AF
foreign key (author_books_id) references author;

and running the initializing code above will result in output that’s similar to before, with the addition of inserting into the join table:

insert into author (id, version, name) values (null, ?, ?)

insert into book (id, version, title) values (null, ?, ?)

update author set version=?, name=? where id=? and version=?

insert into author_book (author_books_id, book_id) values (?, ?)

but running the updating code results in this:

select author0_.id as id4_0_, author0_.version as version4_0_,
author0_.name as name4_0_ from author author0_ where author0_.id=?

select books0_.author_books_id as author1_4_0_, books0_.book_id as
book2_0_ from author_book books0_ where books0_.author_books_id=?

select book0_.id as id3_0_, book0_.version as version3_0_,
book0_.title as title3_0_ from book book0_ where book0_.id=?

insert into book (id, version, title) values (null, ?, ?)

update author set version=?, name=? where id=? and version=?

delete from author_book where author_books_id=?

insert into author_book (author_books_id, book_id) values (?, ?)

insert into author_book (author_books_id, book_id) values (?, ?)

This is not good. It reads the author, then all of the books for that author (the part we’re trying to avoid), inserts the book, and then deletes every row from the join table for this author, and re-inserts rows for each element in the Bag. Ouch.


If you convert the relationship to a many-to-many with Bags on both sides:

class Author {
   String name
   Collection books
   static hasMany = [books: Book]
}
class Book {
   String title
   Collection authors
   static hasMany = [authors: Author]
   static belongsTo = Author
}

and run this initializing code:

def author = new Author(name: 'Hunter S. Thompson')
author.addToBooks(title: 'Fear and Loathing in Las Vegas')
author.save()

you get this output:

insert into author (id, version, name) values (null, ?, ?)

insert into book (id, version, title) values (null, ?, ?)

update author set version=?, name=? where id=? and version=?

update book set version=?, title=? where id=? and version=?

insert into author_books (author_id, book_id) values (?, ?)

It inserts the author and the book, then versions both rows, and inserts a row into the join table.

If you run this updating code:

def author = Author.get(1)
author.addToBooks(title: "Hell's Angels: A Strange and Terrible Saga")
author.save()

then the output is similar to the output for one-to-many with a join table:

select author0_.id as id0_0_, author0_.version as version0_0_,
author0_.name as name0_0_ from author author0_ where author0_.id=?

select books0_.author_id as author1_0_0_, books0_.book_id as book2_0_
from author_books books0_ where books0_.author_id=?

insert into book (id, version, title) values (null, ?, ?)

update author set version=?, name=? where id=? and version=?

update book set version=?, title=? where id=? and version=?

delete from author_books where author_id=?

insert into author_books (author_id, book_id) values (?, ?)

insert into author_books (author_id, book_id) values (?, ?)

It loads the author, then all of the book ids from the join table (to create proxies, which are lighter-weight than full domain class instances but there will still be N of them in memory), then inserts the new book, versions both rows, and again deletes every row from the join table and reinserts them. Ouch again.


So for the two cases where there are join tables, we have a problem. Hibernate doesn’t worry about duplicates or order in-memory, but the join tables can’t have duplicate records, so it has to pessimistically clear the data and reinsert it. This has all of the negatives of the non-Bag approach and adds another big one.

Even in the first case I described where there’s no join table, there’s still a problem. Since the Author’s version gets incremented when you add a Book (you’re editing a property of the Author, so it’s considered to be updated even though it’s a collection pointing to another table) there’s a high risk that concurrently adding child instances will cause optimistic locking exceptions for the Author, even though you just want to insert rows into the book table. And this is the case for all three scenarios.


So I guess I’m back to advocating the approach from my earlier talks; don’t map a collection of Books in the Author class, but add an Author field to the Book class instead:

class Author {
   String name
}
class Book {
   String title
   Author author
}

And for many-to-many case map the “author_books” table with a domain class:

class Author {
   String name
}
class Book {
   String title
}
class AuthorBook {
   Author author
   Book book
   ...
}

Create your own Grails holder class

Sunday, November 13th, 2011

I mentioned in an earlier post that using Grails *Holder classes should be avoided, and showed how to access the GrailsApplication, ApplicationContext, etc. from domain classes. But there are still cases where you need access to these objects and dependency injection and the approach I described aren’t sufficient. When all else fails you can always create your own holder class.

The reason this works in your application but not in Grails is that the static fields in your application are only accessed within your application. By using shared jars, multiple applications share static state held by shared classes, but this isn’t a problem for your code.

Since everything is reachable from the ApplicationContext and it’s easy to access, we’ll create a holder for that and expose the other objects from there.

Create a class called ApplicationContextHolder that implements ApplicationContextAware:

package com.yourcompany.yourapp

import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

@Singleton
class ApplicationContextHolder implements ApplicationContextAware {

   private ApplicationContext ctx

   void setApplicationContext(ApplicationContext applicationContext) {
       ctx = applicationContext
   }

   static ApplicationContext getApplicationContext() {
      getInstance().ctx
   }
}

and register it in resources.groovy so the ApplicationContext is injected (using the factoryMethod attribute since the class is a singleton):

import com.yourcompany.yourapp.ApplicationContextHolder

beans = {
   applicationContextHolder(ApplicationContextHolder) { bean ->
      bean.factoryMethod = 'getInstance'
   }
}

Now you can use the ApplicationContext from anywhere to access Spring beans. We can go further though, adding utility methods to expose other classes held by holders:

static Object getBean(String name) {
   getApplicationContext().getBean(name)
}

static GrailsApplication getGrailsApplication() {
   getBean('grailsApplication')
}

static ConfigObject getConfig() {
   getGrailsApplication().config
}

static ServletContext getServletContext() {
   getBean('servletContext')
}

static GrailsPluginManager getPluginManager() {
   getBean('pluginManager')
}

You can also add the ability to register mock beans for unit tests; here’s the complete class:

package com.yourcompany.yourapp

import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
import javax.servlet.ServletContext

import org.codehaus.groovy.grails.commons.GrailsApplication
import org.codehaus.groovy.grails.plugins.GrailsPluginManager
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

@Singleton
class ApplicationContextHolder implements ApplicationContextAware {

   private ApplicationContext ctx

   private static final Map <String, Object> TEST_BEANS = [:]

   void setApplicationContext(ApplicationContext applicationContext) {
       ctx = applicationContext
   }

   static ApplicationContext getApplicationContext() {
      getInstance().ctx
   }

   static Object getBean(String name) {
      TEST_BEANS[name] ?: getApplicationContext().getBean(name)
   }

   static GrailsApplication getGrailsApplication() {
      getBean('grailsApplication')
   }

   static ConfigObject getConfig() {
      getGrailsApplication().config
   }

   static ServletContext getServletContext() {
      getBean('servletContext')
   }

   static GrailsPluginManager getPluginManager() {
      getBean('pluginManager')
   }

   // For testing
   static void registerTestBean(String name, bean) {
      TEST_BEANS[name] = bean
   }

   // For testing
   static void unregisterTestBeans() {
      TEST_BEANS.clear()
   }
}

Note that the servletContext and pluginManager beans are available in a running application but not the Grails console.

Overriding Groovy constructors

Sunday, November 13th, 2011

It’s rare to create parameterized constructors in Groovy since the Map constructor that’s added to all classes reduces the need for “real” constructors. There’s still a case for defining constructors to enforce business rules, for example if an instance requires certain fields to be set in order for it to be valid. But in general we tend to just use the Map constructor.

But what if you want to override that constructor, replacing its implementation, or adding code before or after the default implementation? Also, Grails augments domain class constructors to support dependency injection from the Spring ApplicationContext, so is it possible to reimplement or augment that behavior?

One thing that’s important to point out is that the Map constructor relies on the default constructor that’s added to all classes that don’t define any explicit constructors. It calls that constructor, then sets properties from the provided Map (this is defined in MetaClassImpl.invokeConstructor() if you’re curious). But if you declare one or more parameterized constructors the compiler doesn’t generate an empty one for you, and the Map constructor fails.

For example, if you run this in a Groovy console, it will fail with an exception:

class Thing {
   Thing(String name) { this.name = name }
   String name
}

def t = new Thing(name: 'x')
println f.name

The fix is to add an empty constructor:

class Thing {
   Thing() {}
   Thing(String name) { this.name = name }
   String name
}

def t = new Thing(name: 'x')
println f.name

or not define any at all:

class Thing {
   String name
}

So how can we replace the Map constructor? It depends on whether we want to redefine the implementation, or add logic before or after the default implementation. Note – for these examples I assume you have a domain class named “User”.

To add behavior, we need to be able to call the constructor that Groovy adds:

def originalMapConstructor = User.metaClass.retrieveConstructor(Map)

User.metaClass.constructor = { Map m ->

   // do work before creation

   def instance = originalMapConstructor.newInstance(m)

   // do work after creation

   instance
}

If you want to redefine the behavior it’s simpler, just do that work in the Closure that will become the constructor:

User.metaClass.constructor = { Map m ->

   // do work before creation

   def instance = new User()

   // do initialization, e.g. "instance.properties = m"

   // do work after creation

   instance
}

Overriding the default constructor is a bit trickier, and only really applies to Grails, and really just domain class constructors. The problem is that it’s nontrivial to access the real default constructor that’s added by the compiler. In fact you can’t, but there’s a hackish workaround for that.

To just add behavior, we need to be able to access the behavior that Grails adds. DomainClassGrailsPlugin overrides the default constructor in its doWithDynamicMethods callback (doing the work in enhanceDomainClasses()) and takes advantage of the fact that domain classes are registered as prototype Spring beans. This means that requesting the associated bean gives you a new instance each time, and since it’s a bean any public fields that correspond to other Spring beans are populated via dependency injection.

So assuming you have access to the GrailsApplication (most likely via dependency injection with "def grailsApplication"), you can do this:

User.metaClass.constructor = { ->

   // do work before creation

   def instance = grailsApplication.mainContext.getBean(User.name)

   // do work after creation

   instance
}

If you want to redefine the behavior, ideally you could call the compiler-generated default constructor. But that’s not available, having been replaced in the MetaClass. So you can use a trick, unfortunately only available in a Sun or JRockit JDK:

import sun.reflect.ReflectionFactory

def objectConstructor = Object.getConstructor()

User.metaClass.constructor = { ->
   def factory = ReflectionFactory.reflectionFactory
   def cleanConstructor = factory.newConstructorForSerialization(
      User, objectConstructor)
   cleanConstructor.accessible = true

   // do work before creation

   def instance = cleanConstructor.newInstance()

   // do work after creation

   instance
}

You can also go further and trigger dependency injection:

import sun.reflect.ReflectionFactory
import org.springframework.beans.factory.config.AutowireCapableBeanFactory

def objectConstructor = Object.getConstructor()

User.metaClass.constructor = { ->
   def factory = ReflectionFactory.reflectionFactory
   def cleanConstructor = factory.newConstructorForSerialization(
      User, objectConstructor)
   cleanConstructor.accessible = true

   // do work before creation

   def instance = cleanConstructor.newInstance()

   // trigger dependency injection
   def ctx = grailsApplication.mainContext
   def beanFactory = ctx.autowireCapableBeanFactory
   beanFactory.autowireBeanProperties(instance,
         AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, false)
   
   // do work after creation

   instance
}

Note that since the constructor is bypassed, field initializations won’t run. So for example if your class looks like this:

class User {
   String name
   Integer foo = 5
   def something = new Something()
   def userService
}

then the ‘foo’ and ‘something’ fields will be null. ‘userService’ will be populated only if you retain the default dependency injection behavior or call it yourself.

Accessing the GrailsApplication and ApplicationContext from domain classes without holders

Saturday, November 12th, 2011

The various holder classes in Grails (ApplicationHolder, ConfigurationHolder, etc.) are now deprecated and the plan was to remove them at some point since static variables cause problems. One example is deploying multiple Grails applications with the --nojars option, using jar files in the server’s shared classpath. If a class with a static field is loaded by the shared classloader, its value is shared by all callers. Kaboom.

We’re working on a fix but it doesn’t look like it’ll be ready for 2.0 final, so it’s still best to avoid their use. In practice this isn’t really that much of a problem since you can use dependency injection to inject the GrailsApplication into any artifact (controllers, services, Quartz jobs, etc.) with def grailsApplication. From there you can get the configuration (grailsApplication.config) and the ApplicationContext (grailsApplication.mainContext). From there you can get any Spring bean, including the ServletContext (registered as the "servletContext" bean).

Dependency injection isn’t an option for regular classes in src/groovy or src/java, but they don’t exist in isolation. They have to be called from somewhere, and that’s most likely going to be an artifact that can use dependency injection. So instead of auto-injecting into your Groovy class, just pass the application, config, or context (or specific beans) to the class when you call it.

I described a way to add a getGrailsApplication method (both static and instance) to the MetaClass of your domain classes in an answer to this StackOverflow question, and it’s still a good option. One caveat – adding a getFoo instance method allows you to call it like it’s a property (thing.foo) but that doesn’t work with static methods. You have to use the getter syntax: Thing.getFoo().

But it turns out this is all possible in 2.0 without changes. There’s a new getDomainClass instance method in domain classes (it returns the GrailsDomainClass artifact API class), and from there you can access the GrailsApplication with its getGrailsApplication method. So if you need access to the configuration, GrailsApplication, or ApplicationContext from a static method, you can reach everything from a new instance of your domain class:

class Book {
   ...
   static someMethod() {
      def grailsApplication = new Book().domainClass.grailsApplication
      def ctx = grailsApplication.mainContext
      def config = grailsApplication.config
      def fooService = ctx.fooService
      ...
   }
}

This Week in Grails (2011-44)

Monday, November 07th, 2011

Lots of Groovy/Grails conferences happening currently. It sounds like folks had a good time at Greach from what I can tell from Twitter. And the schedule for the Groovy & Grails eXchange (coming up next month) was updated – it looks like it’s going to be an interesting couple of days.

In the plugins section the Hibernate Search plugin is listed as being updated, but the original release was only a simple proof of concept and the current one is completely new. It looks like it’s a good alternative to the Searchable plugin.


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There was 1 new plugin released:

  • struts-menu version 1.1. Basic Grails wrapper for Struts Menu

and 12 updated plugins:

  • cxf-client version 1.1. Use existing (or new) Apache CXF wsdl2java generated content to invoke SOAP services
  • dojo version 1.6.1.2. Integrates the Dojo javascript toolkit
  • flash-player version 1.4. Provides a Grails TagLib wrapper around the JW FLV Media Player
  • hibernate-search version 0.1. Integrates Hibernate Search for domain classes
  • json-rest-api version 1.0.11. JSON RESTful API for GORM
  • spring-security-facebook version 0.3. Plugin for Facebook Authentication, as extension to Grails Spring Security Core plugin
  • spring-security-twitter version 0.3.4. Twitter authentication as extension to the Spring Security Core plugin
  • swfobject version 2.2.1. Resources and tags for swfobject
  • twitter-bootstrap version 1.4.0.12. Twitter Bootstrap CSS framework resource files
  • weceem version 1.1.SNAP4. A content management system
  • xwiki-rendering version 0.3. Convert texts using XWiki Rendering Framework
  • yui version 2.8.2.1. Provides integration with the Yahoo! UI Library

Interesting Tweets

Jobs



User groups and Conferences



Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.