You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 4迁移后无法运行集成测试用例

解决Grails 3.3.11迁移到4.0.6后集成测试加载ApplicationContext失败的问题

你遇到的核心错误是java.lang.IllegalStateException: Failed to load ApplicationContext,追根溯源是groovy.lang.MissingPropertyException: No such property: mappingStrategy for class: org.grails.core.DefaultGrailsDomainClass,这个问题出在hibernate-filter插件的初始化逻辑里。

问题根源

从Grails 3.2.x版本开始,官方废弃了旧的Grails Domain Class API,转而使用Mapping Context API。这个变更的目的是避免GORM和Grails重复解析类元数据,减少应用启动时间。

关键的变化是:

  • 旧的GrailsDomainClass和GrailsDomainClassProperty相关API不再支持在应用上下文加载前访问
  • 领域类的元数据需要等到应用上下文完全加载完成后才能获取
  • 你的hibernate-filter插件还在使用旧的方式,在doWithSpring方法(上下文加载前执行的阶段)里直接访问GrailsDomainClass的mappingStrategy属性,这在Grails 4里已经不再支持。

解决方案

1. 调整代码执行时机

把所有依赖领域类元数据的逻辑,从上下文加载前的阶段(比如插件的doWithSpring方法),迁移到上下文加载完成后的阶段,比如插件的doWithApplicationContext方法。

2. 替换为Mapping Context API

放弃使用旧的GrailsDomainClass和GrailsDomainClassProperty,改用新的Mapping Context相关API:

  • 注入grailsDomainClassMappingContext bean,这是Mapping Context的核心实例
  • 用PersistentEntity替代原来的GrailsDomainClass
  • 用PersistentProperty替代原来的GrailsDomainClassProperty

代码示例(插件改造)

假设你原来的插件代码是这样的(在doWithSpring里):

domainClasses.findAll { it.mappingStrategy }

需要改造成在doWithApplicationContext里执行:

void doWithApplicationContext(ApplicationContext applicationContext) {
    def mappingContext = applicationContext.getBean('grailsDomainClassMappingContext')
    // 获取所有持久化实体(对应原来的领域类)
    def persistentEntities = mappingContext.persistentEntities
    
    // 替代原来的逻辑,用PersistentEntity的API处理
    persistentEntities.findAll { entity ->
        // 这里根据你的需求,用PersistentEntity的方法替代mappingStrategy相关判断
        // 比如获取实体的映射信息可以通过entity.mapping
    }
}

3. 处理第三方插件

如果hibernate-filter是第三方插件,你需要确认该插件是否有适配Grails 4的版本,如果没有,可能需要自己fork插件并按照上面的方式改造代码,或者寻找替代方案。

内容的提问来源于stack exchange,提问作者Soven K Rout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 08:28:12