I'm trying to add one dynamic attribute to my Domain Class and I'm experimenting an extrange issue. When the database is empty, the first instance is saved with the property correctly set, but subsequent calls store the instance without that property. Any ideas?
Also note that I've set nullable:true by default in Config.groovy to allow adding new properties just where I need them
This is my domain
class UserBehaviour extends UserActivity{
Behaviour behaviour
Site site
int points
static belongsTo = [behaviour:Behaviour,site:Site]
}
This the code for saving with some println
UserBehaviour userBehaviour = new UserBehaviour(user:user,behaviour:behaviour,site:site,points:behaviour.points,date:new Date())
metadata.each{key,value->
println "metadata${key}"
userBehaviour["metadata${key}"] = value
println userBehaviour["metadata${key}"]
}
println metadata
if (!userBehaviour.save()){
throw new InvalidRequestException("invalid")
} else {
println "before-->"+UserBehaviour.countByMetadatalanguage("java")
//do some things....
println "after-->"+UserBehaviour.countByMetadatalanguage("java")
}
And this is the output of calling it twice
metadatalanguage
java
[language:java]
before-->0
after-->1
metadatalanguage
null
[language:java]
before-->1
after-->1
UPDATE 1 These are the stored documents, as you can see they're almost equal except for the _id and the date (both of them should have the metadatalanguage property...)
{
_id: 51d50ff5c6c3cf71b9fc2a38
_class: UserBehaviour
user: 519f0e14c6c3da4f668c1d3c
behaviour: 51d410a2c6c3934c7207df6b
metadatalanguage: java
points: 50
date: Thu Jul 04 08:02:29 CEST 2013
site: 519f0e15c6c3da4f668c1d75
version: 3
}
{
_id: 51d50ff7c6c3cf71b9fc2a3a
_class: UserBehaviour
user: 519f0e14c6c3da4f668c1d3c
behaviour: 51d410a2c6c3934c7207df6b
points: 50,
date: Thu Jul 04 08:02:31 CEST 2013
site: 519f0e15c6c3da4f668c1d75
version: 0
}
One strange thing I've just seen is the version number. I haven't modified any of these instances, so version should be 0 right?
UPDATE 2 I've created an small integration test that also fails when checking userBehaviour2.metadatalanguage.
void testAddDynamicProperty(){
setup:
def metadata = ["language":"java"]
Behaviour behaviour = Behaviour.list([max:1]).first()
User user = User.list([max:1]).first()
when:
UserBehaviour userBehaviour = new UserBehaviour(user:user,behaviour:behaviour,site:site,points:behaviour.points,date:new Date())
metadata.each{key,value->
userBehaviour."metadata${key}" = value
}
UserBehaviour userBehaviour2 = new UserBehaviour(user:user,behaviour:behaviour,site:site,points:behaviour.points,date:new Date())
metadata.each{key,value->
userBehaviour2."metadata${key}" = value
}
boolean valid1 = userBehaviour.save()
boolean valid2 = userBehaviour2.save()
then:
valid1 == true
valid2 == true
userBehaviour.metadatalanguage == "java"
userBehaviour2.metadatalanguage == "java"
}
I've found a workaround that consists in saving first the instance without the dynamic attribute and then update the instance with that dynamic attribute.
I've also raised a JIRA in case it's considered a bug: http://jira.grails.org/browse/GPMONGODB-306