views:

160

answers:

2

I have the following simplified model in Grails:

  • A DataBlock consists of a number of sorted ConfigPreset objects.

In ConfigPreset I have

static belongsTo = [dataBlock: DataBlock]

and the DataBlock class contains:

List presets
static hasMany = [presets: ConfigPreset]

DataBlock() {
    addToPresets(new ConfigPreset())
}

The overloaded constructor returns: No signature of method: [...].addToPresets() is applicable for argument types: (ConfigPreset) values: [ConfigPreset : null].

But why is my ConfigPreset instance null? If I try to create a DataBlock object in e.g. BootStrap.groovy with an unmodified ctor and call addToPresets(...) on it, it works.

+1  A: 

Grails instantiates your domain classes (and other artifacts) at least once during startup for its initialization code. This happens before the dynamic methods are added, hence the exception. It works in BootStrap since everything's configured at this point. Note that nothing is null - you're just seeing the toString() of the domain class which prints the name and id, and since it's a new instance the id is null.

You can use the beforeInsert callback for this though, see - http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html#5.5.1%20Events%20and%20Auto%20Timestamping

Burt Beckwith
A: 

Your example cannot work.

Specifying static belongsTo = [dataBlock: DataBlock] inside ConfigPreset means that you cannot create a ConfigPresetinstance without specifying the DataBlock owner.

So basically the following statement

new ConfigPreset() will always return null unlike

new ConfigPreset(dataBlock: aDataBlock) that will return a valid ConfigPreset instance.

The method addToXXX is basically doing the following :

  1. Create the XXX instance (as described below)
  2. Add the newly created XXX instance to this instance

In your case, it cannot create the ConfigPreset (step 1) since the DataBlock instance is not yet created (your are in the constructor)

If you want to associate automatically a ConfigPreset whenever you create a DataBlock, you can do it by using Gorm Events, adding a callbalck to beforeInsert event.

Or you can remove belongsTo and new ConfigPreset() will work.

fabien7474