This is an automated email from the ASF dual-hosted git repository. borinquenkid pushed a commit to branch test/abstract-datastore-initializer in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit eee486fbc05baffe0bb220037be74d078b8c5f0b Author: Walter Duque de Estrada <[email protected]> AuthorDate: Thu Aug 13 17:12:19 2026 -0500 Fix enableReload being silently ignored; remove dead grailsPlugin property Two different verdicts from git archaeology on these Hibernate5/7 initializer properties: enableReload (real bug, same class as databaseName/defaultDataSourceBeanName): HibernateGrailsPlugin sets springInitializer.enableReload = Environment.isDevelopmentMode() to enable Hibernate's runtime-reload support by default in dev mode, but the field was never read - it has a genuine, still-live destination in HibernateConnectionSourceSettings. enableReload, populated via the same generic PropertyResolver-binding mechanism proven by the databaseName fix. Adds applyEnableReloadFallback(), called at the top of getBeanDefinitions() for the same reason as the Mongo fix, injecting an `enableReload` fallback property only when customized away from its default and not already explicitly configured. Verified end-to-end against HibernateDatastore's actual connection source settings, which also confirms the unprefixed `enableReload` config key empirically (not just by static tracing). grailsPlugin (dead, same class as registerApplicationIfNotPresent): git blame traces this to a 2016 fix (133ca44374) that conditionally kept GrailsHibernateTransactionManager alive for Grails-plugin bootstrapping while a parallel refactor moved standalone usage to deriving the transaction manager from the datastore instead. A follow-up commit five months later (415d1c6a8e, Jan 2017) dropped the conditional entirely in favor of the datastore-derived approach unconditionally, but left the grailsPlugin field and its two HibernateGrailsPlugin call sites behind. Removed all four references. Co-Authored-By: Claude Sonnet 5 <[email protected]> --- .../HibernateDatastoreSpringInitializer.groovy | 22 ++++++++++++- .../plugin/hibernate/HibernateGrailsPlugin.groovy | 1 - .../HibernateDatastoreSpringInitializerSpec.groovy | 38 ++++++++++++++++++++++ .../HibernateDatastoreSpringInitializer.groovy | 22 ++++++++++++- .../plugin/hibernate/HibernateGrailsPlugin.groovy | 1 - .../HibernateDatastoreSpringInitializerSpec.groovy | 38 ++++++++++++++++++++++ 6 files changed, 118 insertions(+), 4 deletions(-) diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy index 9342779524..66eab17784 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy @@ -23,6 +23,7 @@ import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationEventPublisher import org.springframework.context.support.GenericApplicationContext import org.springframework.core.env.ConfigurableEnvironment +import org.springframework.core.env.MapPropertySource import org.springframework.core.env.PropertyResolver import org.springframework.transaction.PlatformTransactionManager @@ -54,7 +55,6 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { String defaultDataSourceBeanName = ConnectionSource.DEFAULT Set<String> dataSources = [defaultDataSourceBeanName] as Set<String> boolean enableReload = false - boolean grailsPlugin = false HibernateDatastoreSpringInitializer(PropertyResolver configuration, Collection<Class> persistentClasses) { super(configuration, persistentClasses) @@ -128,7 +128,27 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { return applicationContext } + /** + * Applies {@link #enableReload} as an {@code enableReload} fallback on {@link #configuration} + * when it was customized away from its default and the configuration does not already specify + * it explicitly. + */ + protected void applyEnableReloadFallback() { + if (!enableReload || configuration.containsProperty('enableReload')) { + return + } + if (configuration instanceof ConfigurableEnvironment) { + ((ConfigurableEnvironment) configuration).propertySources.addFirst( + new MapPropertySource('hibernateDatastoreSpringInitializer.enableReload', [enableReload: true]) + ) + } + else if (configuration instanceof Map) { + ((Map) configuration).put('enableReload', true) + } + } + Closure getBeanDefinitions(BeanDefinitionRegistry beanDefinitionRegistry) { + applyEnableReloadFallback() ApplicationEventPublisher eventPublisher = super.findEventPublisher(beanDefinitionRegistry) Closure beanDefinitions = { def common = getCommonConfiguration(beanDefinitionRegistry, 'hibernate') diff --git a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy index 552eadfd0f..e7944e4fc6 100644 --- a/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy +++ b/grails-data-hibernate5/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy @@ -88,7 +88,6 @@ class HibernateGrailsPlugin extends Plugin { def springInitializer = new HibernateDatastoreSpringInitializer((PropertyResolver) config, domainClasses) springInitializer.enableReload = Environment.isDevelopmentMode() - springInitializer.grailsPlugin = true dataSourceNames = springInitializer.dataSources def beans = springInitializer.getBeanDefinitions((BeanDefinitionRegistry) applicationContext) diff --git a/grails-data-hibernate5/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy b/grails-data-hibernate5/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy index 760171dfbf..e50b485d0a 100644 --- a/grails-data-hibernate5/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy +++ b/grails-data-hibernate5/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy @@ -115,6 +115,44 @@ class HibernateDatastoreSpringInitializerSpec extends Specification{ datastoreInitializer.dataSources == ['primary'] as Set<String> } + void "Test applyEnableReloadFallback injects a fallback when customized and not already configured"() { + given: + def datastoreInitializer = new HibernateDatastoreSpringInitializer([:], Person) + datastoreInitializer.enableReload = true + + when: + datastoreInitializer.applyEnableReloadFallback() + + then: + datastoreInitializer.configuration.getProperty('enableReload', Boolean) == true + } + + void "Test applyEnableReloadFallback does not override an already-configured value"() { + given: + def datastoreInitializer = new HibernateDatastoreSpringInitializer(['enableReload': 'false'], Person) + datastoreInitializer.enableReload = true + + when: + datastoreInitializer.applyEnableReloadFallback() + + then: + datastoreInitializer.configuration.getProperty('enableReload', Boolean) == false + } + + void "Test enableReload is honored end-to-end as a fallback on the default connection's settings"() { + given: "an initializer with enableReload customized and no explicit config for it" + def datastoreInitializer = new HibernateDatastoreSpringInitializer( + ['dataSource.url': 'jdbc:h2:mem:enableReloadFallback;LOCK_TIMEOUT=10000'], Person) + datastoreInitializer.enableReload = true + + when: "the application is configured" + applicationContext = (ConfigurableApplicationContext) datastoreInitializer.configure() + def settings = applicationContext.getBean(HibernateDatastore).connectionSources.defaultConnectionSource.settings + + then: "the fallback reaches the datastore's own connection source settings" + settings.enableReload + } + void "Test the Map/Collection<Class> constructor bootstraps GORM"() { given: "An initializer built from a Collection of persistent classes" def datastoreInitializer = new HibernateDatastoreSpringInitializer( diff --git a/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy b/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy index 2f0b4221ba..d4b7b30c7b 100644 --- a/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy +++ b/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy @@ -24,6 +24,7 @@ import org.springframework.context.ApplicationContext import org.springframework.context.ApplicationEventPublisher import org.springframework.context.support.GenericApplicationContext import org.springframework.core.env.ConfigurableEnvironment +import org.springframework.core.env.MapPropertySource import org.springframework.core.env.PropertyResolver import org.springframework.transaction.PlatformTransactionManager @@ -56,7 +57,6 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { String defaultDataSourceBeanName = ConnectionSource.DEFAULT Set<String> dataSources = [defaultDataSourceBeanName] as Set<String> boolean enableReload = false - boolean grailsPlugin = false Closure beanDefinitions protected ApplicationContext applicationContext @@ -146,7 +146,27 @@ class HibernateDatastoreSpringInitializer extends AbstractDatastoreInitializer { return applicationContext } + /** + * Applies {@link #enableReload} as an {@code enableReload} fallback on {@link #configuration} + * when it was customized away from its default and the configuration does not already specify + * it explicitly. + */ + protected void applyEnableReloadFallback() { + if (!enableReload || configuration.containsProperty('enableReload')) { + return + } + if (configuration instanceof ConfigurableEnvironment) { + ((ConfigurableEnvironment) configuration).propertySources.addFirst( + new MapPropertySource('hibernateDatastoreSpringInitializer.enableReload', [enableReload: true]) + ) + } + else if (configuration instanceof Map) { + ((Map) configuration).put('enableReload', true) + } + } + Closure getBeanDefinitions(BeanDefinitionRegistry beanDefinitionRegistry) { + applyEnableReloadFallback() ApplicationEventPublisher eventPublisher = super.findEventPublisher(beanDefinitionRegistry) return { -> def common = getCommonConfiguration(beanDefinitionRegistry, 'hibernate') diff --git a/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy index 5b99ed5a06..4e2da888e9 100644 --- a/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy +++ b/grails-data-hibernate7/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy @@ -88,7 +88,6 @@ class HibernateGrailsPlugin extends Plugin { def springInitializer = new HibernateDatastoreSpringInitializer((PropertyResolver) config, domainClasses) springInitializer.enableReload = Environment.isDevelopmentMode() - springInitializer.grailsPlugin = true dataSourceNames = springInitializer.dataSources def beans = springInitializer.getBeanDefinitions((BeanDefinitionRegistry) applicationContext) diff --git a/grails-data-hibernate7/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy b/grails-data-hibernate7/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy index f8a68aedee..8262cfae53 100644 --- a/grails-data-hibernate7/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy +++ b/grails-data-hibernate7/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy @@ -113,6 +113,44 @@ class HibernateDatastoreSpringInitializerSpec extends Specification{ datastoreInitializer.dataSources == ['primary'] as Set<String> } + void "Test applyEnableReloadFallback injects a fallback when customized and not already configured"() { + given: + def datastoreInitializer = new HibernateDatastoreSpringInitializer([:], Person) + datastoreInitializer.enableReload = true + + when: + datastoreInitializer.applyEnableReloadFallback() + + then: + datastoreInitializer.configuration.getProperty('enableReload', Boolean) == true + } + + void "Test applyEnableReloadFallback does not override an already-configured value"() { + given: + def datastoreInitializer = new HibernateDatastoreSpringInitializer(['enableReload': 'false'], Person) + datastoreInitializer.enableReload = true + + when: + datastoreInitializer.applyEnableReloadFallback() + + then: + datastoreInitializer.configuration.getProperty('enableReload', Boolean) == false + } + + void "Test enableReload is honored end-to-end as a fallback on the default connection's settings"() { + given: "an initializer with enableReload customized and no explicit config for it" + def datastoreInitializer = new HibernateDatastoreSpringInitializer( + ['dataSource.url': 'jdbc:h2:mem:enableReloadFallback;LOCK_TIMEOUT=10000'], Person) + datastoreInitializer.enableReload = true + + when: "the application is configured" + applicationContext = (ConfigurableApplicationContext) datastoreInitializer.configure() + def settings = applicationContext.getBean(HibernateDatastore).connectionSources.defaultConnectionSource.settings + + then: "the fallback reaches the datastore's own connection source settings" + settings.enableReload + } + void "Test the Map/Collection<Class> constructor bootstraps GORM"() { given: "An initializer built from a Collection of persistent classes" def datastoreInitializer = new HibernateDatastoreSpringInitializer(
