Question

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"
}
Was it helpful?

Solution

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top