grails / gorm-mongodb

GORM for MongoDB
Apache License 2.0
68 stars 31 forks source link

Unable to update embedded class field #125

Open Tirla-Alin opened 4 years ago

Tirla-Alin commented 4 years ago

Task List

Steps to Reproduce

  1. Create a simple grails 4.0.1, gorm 7.0.2.RELEASE (with mongo plugin support) application
  2. Create one class in the groovy/src folder
    
    //import grails.gorm.dirty.checking.DirtyCheck

//@DirtyCheck class EmbeddedClass { String aField }

3. Create a domain class in grails-app

class DomainClass implements Serializable {

EmbeddedClass embeddedClass

static embedded = ['embeddedClass']

static constraints = {
}

}

4. Insert an entity

DomainClass.withNewTransaction { def domain = new DomainClass() domain.embeddedClass = new EmbeddedClass() domain.embeddedClass.aField = "ogValue" domain.save(flush: true, failOnError: true) }

5. Try to update domain.embeddedClass.aField
@Secured(['IS_AUTHENTICATED_ANONYMOUSLY'])
def updateEmbedded() {
    def domainClass = DomainClass.findById(1)
    domainClass.embeddedClass = new EmbeddedClass()
    domainClass.embeddedClass.aField = "anothervalue"
    domainClass.save(flush:true, failOnError: true)

    return respond("response": "response")
}
6. Check the value in the db.

### Expected Behaviour

Ability to update embedded class field.

### Actual Behaviour

Unable to update embedded class field. Tried with new entity (provided example), update only the field, tried to add (DirtyCheck annotation) as I saw in some other issue -> that will throw an exception. Relevant stacktrace is as follows:

java.lang.IllegalStateException: Either class [org.avora.lib.models.EmbeddedClass] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity. at org.grails.datastore.gorm.GormEnhancer.stateException(GormEnhancer.groovy:467) at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:298) at org.grails.datastore.gorm.GormEnhancer.findStaticApi(GormEnhancer.groovy:294) at org.grails.datastore.mapping.mongo.engine.codecs.PersistentEntityCodec.encodeUpdate(PersistentEntityCodec.groovy:285) at org.grails.datastore.mapping.mongo.engine.codecs.PersistentEntityCodec.encodeUpdate(PersistentEntityCodec.groovy:203) at org.grails.datastore.mapping.mongo.engine.codecs.PersistentEntityCodec.encodeEmbeddedUpdate(PersistentEntityCodec.groovy:443) at org.grails.datastore.mapping.mongo.engine.codecs.PersistentEntityCodec.encodeUpdate(PersistentEntityCodec.groovy:251) at org.grails.datastore.mapping.mongo.engine.codecs.PersistentEntityCodec.encodeUpdate(PersistentEntityCodec.groovy) at org.grails.datastore.mapping.mongo.MongoCodecSession.flush(MongoCodecSession.groovy:158) at org.grails.datastore.mapping.mongo.AbstractMongoSession.flush(AbstractMongoSession.java:74) at org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy:368) at org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1217) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041) at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:1011) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:994) at org.codehaus.groovy.runtime.InvokerHelper.invokeMethodSafe(InvokerHelper.java:97) at org.grails.datastore.gorm.GormInstanceApi$_save_closure5.doCall(GormInstanceApi.groovy:180) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:101) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323) at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:263) at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041) at groovy.lang.Closure.call(Closure.java:405) at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50) at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:122) at com.sun.proxy.$Proxy112.doInSession(Unknown Source) at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:319) at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:40) at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:179) at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:153) at org.grails.datastore.gorm.GormEntity$Trait$Helper$save$4.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135) at org.mypackage.DomainClass.save(DomainClass.groovy) at org.mypackage.DomainClass.save(DomainClass.groovy) at org.grails.datastore.gorm.GormEntity$save.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:127)



### Environment Information

- **Operating System**: macOS Catalina 10.15.4
- **GORM Version:** 7.0.2.RELEASE
- **Grails Version (if using Grails):** 4.0.1
- **JDK Version:** 1.8.0_231

### Example Application

- TODO: link to github repository with example that reproduces the issue
Tirla-Alin commented 4 years ago

Update: Setting grails.mongodb.engine=mapping in application.properties seems to fix the issue. As far as I understood from documentation this will affect performance, so I am still looking for the correct solution to this.

puneetbehl commented 4 years ago

I think the root problem is that it is assuming EmbeddedClass as PersistentEntity whereas it is NOT. So, if you either annotate the Embedded class with @grails.gorm.annotation.Entity or move it to the grails-app/domains folder.