Grails 4迁移后无法运行集成测试用例
你遇到的核心错误是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:
- 注入
grailsDomainClassMappingContextbean,这是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

