在Grails和MongoDB中有一个非常奇怪的问题,在生产环境中出现以下错误。

java.lang.IllegalArgumentException: Property [location] is not a valid property of class [domain].Tracking 
        at org.grails.datastore.mapping.reflect.FieldEntityAccess$FieldEntityReflector.getPropertyReader(FieldEntityAccess.java:268) 
        at org.grails.datastore.mapping.reflect.FieldEntityAccess$FieldEntityReflector.getProperty(FieldEntityAccess.java:286) 
        at grails.gorm.validation.PersistentEntityValidator.validatePropertyWithConstraint(PersistentEntityValidator.groovy:319) 
        at grails.gorm.validation.PersistentEntityValidator.validate(PersistentEntityValidator.groovy:76) 
        at org.grails.datastore.gorm.GormValidationApi.doValidate(GormValidationApi.groovy:124) 
        at org.grails.datastore.gorm.GormValidationApi.validate(GormValidationApi.groovy:153) 
        at org.grails.datastore.gorm.GormValidateable$Trait$Helper.validate(GormValidateable.groovy:71) 
        at org.grails.datastore.gorm.GormValidateable$Trait$Helper$validate$1.call(Unknown Source) 
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:136) 
        at [domain].Tracking.validate(Tracking.groovy) 
        at org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy:332) 
        at org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy) 
        at sun.reflect.GeneratedMethodAccessor113.invoke(Unknown Source) 
        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:98) 
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) 
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1225) 
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) 
        at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:947) 
        at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:930) 
        at org.codehaus.groovy.runtime.InvokerHelper.invokeMethodSafe(InvokerHelper.java:92) 
        at org.grails.datastore.gorm.GormInstanceApi$_save_closure5.doCall(GormInstanceApi.groovy:179) 
        at sun.reflect.GeneratedMethodAccessor112.invoke(Unknown Source) 
        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:98) 
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) 
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:264) 
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) 
        at groovy.lang.Closure.call(Closure.java:418) 
        at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:54) 
        at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124) 
        at com.sun.proxy.$Proxy111.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:178) 
        at org.grails.datastore.gorm.GormEntity$Trait$Helper.save(GormEntity.groovy:151) 
        at org.grails.datastore.gorm.GormEntity$Trait$Helper$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:116) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:136) 
        at [domain].Tracking.save(Tracking.groovy) 
        at [domain].Tracking.save(Tracking.groovy) 
        at org.grails.datastore.gorm.GormEntity$save$0.call(Unknown Source) 
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:128) 
        at autovision.web.BootStrap$_closure1.doCall(BootStrap.groovy:139) 
        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:98) 
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) 
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:264) 
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) 
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1099) 
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1034) 
        at groovy.lang.Closure.call(Closure.java:418) 
        at groovy.lang.Closure.call(Closure.java:412) 
        at grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:541) 
        at grails.util.Environment.executeForEnvironment(Environment.java:534) 
        at grails.util.Environment.executeForCurrentEnvironment(Environment.java:510) 
        at org.grails.web.servlet.boostrap.DefaultGrailsBootstrapClass.callInit(DefaultGrailsBootstrapClass.java:74) 
        at org.grails.web.servlet.context.GrailsConfigUtils.executeGrailsBootstraps(GrailsConfigUtils.java:65) 
        at org.grails.plugins.web.servlet.context.BootStrapClassRunner.onStartup(BootStrapClassRunner.groovy:53) 
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy:261) 
        at grails.boot.config.GrailsApplicationPostProcessor.onApplicationEvent(GrailsApplicationPostProcessor.groovy) 
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) 
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) 
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) 
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393) 
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347) 
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883) 
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144) 
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) 
        at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) 
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) 
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) 
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) 
        at grails.boot.GrailsApp.run(GrailsApp.groovy:84) 
        at grails.boot.GrailsApp.run(GrailsApp.groovy:393) 
        at grails.boot.GrailsApp.run(GrailsApp.groovy:380) 
        at grails.boot.GrailsApp$run.call(Unknown Source) 
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116) 
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:136) 
        at autovision.web.Application.main(Application.groovy:8) 

当我尝试将新的跟踪对象插入数据库时​​,就会发生这种情况:
  Tracking tp = new Tracking() 
  tp.setUser(user) 
  nowCal.add(Calendar.MINUTE,i++) 
  tp.setCreated(nowCal.getTime()) 
  tp.setSpeed(10f) 
  tp.setLocation(new Point(points[1],points[0])) 
  tp.save(flush:true) 
 
  user.addToTracking(tp); 

我的Tracking类的定义如下:
import grails.mongodb.geo.Point 
 
class Tracking { 
 
    Point location 
 
    Date created 
 
    float speed 
 
    static belongsTo = [user:User] 
 
    static constraints = { 
        speed nullable:true 
    } 
 
    static mapping = { 
        location geoIndex:'2dsphere' 
    } 
} 

我真的看不到问题出在哪里,我想我已经按照GORM文档中的说明正确定义了所有内容: http://gorm.grails.org/latest/mongodb/manual/#geoSpatial

另一件事是,此代码在非生产模式下运行时效果很好。

所以执行 grails run-app可以,但是 grails prod run-app不能。

任何帮助将非常感激。

谢谢

请您参考如下方法:

我遇到了同样的问题,经过两天的调试终于找到了解决方法。
该问题是由以下原因引起的:

  • 有一个称为org.grails.datastore.mapping.reflect.FieldEntityAccess的Grails实用程序类,显然用于通过反射访问实体字段。该类具有一个内部类FieldEntityReflector。每次创建FieldEntityAccess实例时,都会在内部创建一个FieldEntityReflector实例。所有这些实例都存储在名为REFLECTORS的静态映射中,其键是实体名称,这显然是出于性能原因。
  • 在bean初始化期间,mongoDatastore bean为每个实体创建一个FieldEntityAccess,并传递DocumentPersistentEntity作为构造函数参数。
  • 以相同的方式,不知道grailsDomainClassMappingContextmongoDatastore bean为每个实体创建自己的FieldEntityAccess,将KeyValuePersistentEntity传递为参数。这些FieldEntityAccess实例及其对应的EntityReflectors不了解mongo,因此不支持Point这样的mongo特定类型。
  • 鉴于REFLECTORS映射键是实体名称,最后为同一实体创建的EntityReflectors,覆盖先前创建的反射器,并且所有EntityReflector实例都使用它。
  • 当最后创建grailsDomainClassMappingContext反射器时,它们在mongo尝试持久化和实体化并因此引发错误时使用。

  • 简而言之,在 grailsDomainClassMappingContext bean之后初始化 mongoDatastore bean时引发错误。
    在开发模式下, UrlMappingsGrailsPlugin插件创建了一些用于重新加载url映射的bean。这些bean会在 grailsDomainClassMappingContext bean之前触发 mongoDatastore bean的实例化。在以后创建mongo bean时,不会引发错误。但是,在生产模式下,不会创建这些bean,而是在 mongoDatastore之前创建 grailsDomainClassMappingContext,因此引发错误。
    潜在的解决方案
  • grailsDomainClassMappingContext之前强制mongoDatastore bean实例化:我几次尝试后都无法执行此操作,可能是由于grails bean实例化逻辑所致。
  • 即使在生产模式下也要强制UrlMappingsGrailsPlugin实例化:由于可能会影响性能,所以我不喜欢这样做。
  • 在系统初始化后,使用clearReflectors的静态方法FieldEntityAccess清除所有反射器:**我决定这样做,系统开始工作。我尚未对其进行深入测试,但能够正确持久保留Point

  • 为了调用该方法,我根据 grailsDomainClassMappingContextmongoDatastore创建了一个bean,并将其称为 FieldEntityAccess.clearReflectors()
    package app.utils 
     
    import org.grails.datastore.mapping.mongo.MongoDatastore 
    import org.grails.datastore.mapping.reflect.FieldEntityAccess 
    import org.grails.datastore.mapping.model.MappingContext 
     
    class MongoDatastoreHolder { 
     
        MongoDatastore mongo 
     
        MappingContext context 
     
        MongoDatastoreHolder(MappingContext context, MongoDatastore mongo) { 
            this.context = context 
            this.mongo = mongo 
            FieldEntityAccess.clearReflectors() 
        } 
    } 
    
    并在 resources.groovy中定义了该bean:
    import app.utils.MongoDatastoreHolder 
     
    beans = { 
        mongoDatastoreHolder(MongoDatastoreHolder, ref('grailsDomainClassMappingContext'), ref('mongoDatastore')) { bean -> 
            bean.lazyInit = false 
        } 
    } 
    
    希望对您有所帮助,对于我的英语不好,这是我的第一个StackOverflow答案。


    评论关闭
    IT序号网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!