From f1c6862587a3d2690164db133cb1817e0f90a534 Mon Sep 17 00:00:00 2001 From: David Kron Date: Tue, 8 Jun 2021 10:54:31 +0200 Subject: [PATCH 1/4] Added tests that verify the issue #11767 --- grails-core/build.gradle | 3 +++ .../ConfigBindingExampleConfiguration.java | 13 +++++++++++++ .../plugins/ConfigBindingExampleProperties.java | 17 +++++++++++++++++ .../GrailsPluginConfigurationClass.groovy | 6 +++++- .../PluginGroovyPropertySourceLoaderSpec.groovy | 12 ++++++++++++ .../PluginYamlPropertySourceLoaderSpec.groovy | 11 +++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleConfiguration.java create mode 100644 grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleProperties.java diff --git a/grails-core/build.gradle b/grails-core/build.gradle index 3ba34d2c948..5097e1c096e 100644 --- a/grails-core/build.gradle +++ b/grails-core/build.gradle @@ -61,6 +61,9 @@ dependencies { api "org.grails:grails-datastore-core:$datastoreVersion" + testAnnotationProcessor "io.micronaut:micronaut-runtime:$micronautVersion" + testAnnotationProcessor "io.micronaut:micronaut-inject-java:$micronautVersion" + testImplementation("org.springframework:spring-jdbc:${springVersion}") { exclude group: 'commons-logging', module:'commons-logging' } diff --git a/grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleConfiguration.java b/grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleConfiguration.java new file mode 100644 index 00000000000..a1d58c4a823 --- /dev/null +++ b/grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleConfiguration.java @@ -0,0 +1,13 @@ +package org.grails.plugins; + +import org.springframework.context.annotation.Configuration; + +@Configuration +class ConfigBindingExampleConfiguration { + + private final ConfigBindingExampleProperties configBindingExampleProperties; + + ConfigBindingExampleConfiguration(ConfigBindingExampleProperties configBindingExampleProperties) { + this.configBindingExampleProperties = configBindingExampleProperties; + } +} diff --git a/grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleProperties.java b/grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleProperties.java new file mode 100644 index 00000000000..3c1cd1d35d8 --- /dev/null +++ b/grails-core/src/test/groovy/org/grails/plugins/ConfigBindingExampleProperties.java @@ -0,0 +1,17 @@ +package org.grails.plugins; + +import io.micronaut.context.annotation.ConfigurationProperties; + +@ConfigurationProperties("example") +class ConfigBindingExampleProperties { + + private String bar = "default"; + + public String getBar() { + return bar; + } + + public void setBar(String bar) { + this.bar = bar; + } +} diff --git a/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy b/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy index 1fd454192d9..602141478fa 100644 --- a/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy +++ b/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy @@ -1,5 +1,6 @@ package org.grails.plugins +import grails.boot.config.GrailsAutoConfiguration import grails.core.DefaultGrailsApplication import grails.core.GrailsApplication import grails.plugins.GrailsPlugin @@ -14,7 +15,7 @@ import org.springframework.core.io.Resource @CompileStatic @Configuration -class GrailsPluginConfigurationClass { +class GrailsPluginConfigurationClass extends GrailsAutoConfiguration { public static Boolean YAML_EXISTS = false public static Boolean GROOVY_EXISTS = true @@ -57,12 +58,15 @@ class GrailsPluginConfigurationClass { File file = new File(tempDir, "plugin.yml") file.write("bar: foo\n") file.append("foo: one\n") + file.append("example:\n") + file.append(" bar: foo\n") return new FileSystemResource(file) } if (GROOVY_EXISTS && path == PLUGIN_GROOVY_PATH) { File file = new File(tempDir, "plugin.groovy") file.write("bar = 'foo'\n") file.append("foo = 'one'\n") + file.append("example.bar = 'foo'\n") return new FileSystemResource(file) } return null diff --git a/grails-core/src/test/groovy/org/grails/plugins/PluginGroovyPropertySourceLoaderSpec.groovy b/grails-core/src/test/groovy/org/grails/plugins/PluginGroovyPropertySourceLoaderSpec.groovy index 0e41ee59432..0f099f5870b 100644 --- a/grails-core/src/test/groovy/org/grails/plugins/PluginGroovyPropertySourceLoaderSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/plugins/PluginGroovyPropertySourceLoaderSpec.groovy @@ -1,6 +1,7 @@ package org.grails.plugins import grails.boot.GrailsApp +import grails.boot.config.GrailsAutoConfiguration import io.micronaut.spring.context.env.MicronautEnvironment import org.springframework.context.ConfigurableApplicationContext import spock.lang.Specification @@ -46,5 +47,16 @@ class PluginGroovyPropertySourceLoaderSpec extends Specification { environment.getProperty("bar", String.class) == 'foo' environment.getProperty("abc", String.class) == 'xyz' } + + void "test that the configuration binding of plugin.groovy using @ConfigurationProperties is working inside the micronaut context"() { + + given: + GrailsApp app = new GrailsApp(GrailsPluginConfigurationClass.class, GrailsAutoConfiguration.class, ConfigBindingExampleConfiguration.class) + ConfigurableApplicationContext context = app.run() + ConfigBindingExampleProperties properties = context.parent.getBean(ConfigBindingExampleProperties.class) + + expect: + properties.bar == 'foo' + } } diff --git a/grails-core/src/test/groovy/org/grails/plugins/PluginYamlPropertySourceLoaderSpec.groovy b/grails-core/src/test/groovy/org/grails/plugins/PluginYamlPropertySourceLoaderSpec.groovy index 03de1579e45..32cb279d87e 100644 --- a/grails-core/src/test/groovy/org/grails/plugins/PluginYamlPropertySourceLoaderSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/plugins/PluginYamlPropertySourceLoaderSpec.groovy @@ -46,4 +46,15 @@ class PluginYamlPropertySourceLoaderSpec extends Specification { environment.getProperty("bar", String.class) == 'foo' environment.getProperty("abc", String.class) == 'xyz' } + + void "test that the configuration binding of plugin.yml using @ConfigurationProperties is working inside the micronaut context"() { + + given: + GrailsApp app = new GrailsApp(GrailsPluginConfigurationClass.class, ConfigBindingExampleConfiguration.class) + ConfigurableApplicationContext context = app.run() + ConfigBindingExampleProperties properties = context.parent.getBean(ConfigBindingExampleProperties.class) + + expect: + properties.bar == 'foo' + } } From 3745d178ce8f9afcb97c17befd6641e5f355b8c6 Mon Sep 17 00:00:00 2001 From: David Kron Date: Tue, 8 Jun 2021 11:00:18 +0200 Subject: [PATCH 2/4] Add the plugin specific configurations earlier in the application lifecycle so that the Micronaut context can pick them up (fixes #11767) --- .../main/groovy/grails/boot/GrailsApp.groovy | 27 ---------------- .../GrailsApplicationPostProcessor.groovy | 32 +++++++++++++++++++ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy index 41bf14ae693..15590f8c1df 100644 --- a/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy +++ b/grails-core/src/main/groovy/grails/boot/GrailsApp.groovy @@ -104,8 +104,6 @@ class GrailsApp extends SpringApplication { log.debug("Application directory discovered as: {}", IOUtils.findApplicationDirectory()) log.debug("Current base directory is [{}]. Reloading base directory is [{}]", new File("."), BuildSettings.BASE_DIR) - loadPluginConfigurationsToMicronautContext(applicationContext) - if(environment.isReloadEnabled()) { log.debug("Reloading status: {}", environment.isReloadEnabled()) enableDevelopmentModeWatch(environment, applicationContext) @@ -115,31 +113,6 @@ class GrailsApp extends SpringApplication { return applicationContext } - @SuppressWarnings("GrMethodMayBeStatic") - private void loadPluginConfigurationsToMicronautContext(ConfigurableApplicationContext applicationContext) { - GrailsPluginManager pluginManager = applicationContext.getBean(GrailsPluginManager) - ConfigurableApplicationContext parentApplicationContext = (ConfigurableApplicationContext) applicationContext.parent - ConfigurableEnvironment parentContextEnv = parentApplicationContext.getEnvironment() - if (parentContextEnv instanceof MicronautEnvironment) { - if (log.isDebugEnabled()) { - log.debug("Loading configurations from the plugins to the parent Micronaut context") - } - final io.micronaut.context.env.Environment micronautEnv = ((io.micronaut.context.env.Environment) parentContextEnv.getEnvironment()) - final GrailsPlugin[] plugins = pluginManager.allPlugins - Integer priority = AbstractPropertySourceLoader.DEFAULT_POSITION - Arrays.stream(plugins) - .filter({ GrailsPlugin plugin -> plugin.propertySource != null }) - .forEach({ GrailsPlugin plugin -> - if (log.isDebugEnabled()) { - log.debug("Loading configurations from {} plugin to the parent Micronaut context", plugin.name) - } - micronautEnv.addPropertySource(PropertySource.of("grails.plugins.$plugin.name", (Map) plugin.propertySource.source, --priority)) - }) - micronautEnv.refresh() - applicationContext.setParent(parentApplicationContext) - } - } - @Override protected ConfigurableApplicationContext createApplicationContext() { setAllowBeanDefinitionOverriding(true) diff --git a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy index 53e2771b9ed..a28400df2dc 100644 --- a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy @@ -14,6 +14,9 @@ import grails.util.Environment import grails.util.Holders import groovy.transform.CompileStatic import groovy.util.logging.Slf4j +import io.micronaut.context.env.AbstractPropertySourceLoader +import io.micronaut.context.env.PropertySource +import io.micronaut.spring.context.env.MicronautEnvironment import org.grails.config.NavigableMap import org.grails.config.PrefixedMapPropertySource import org.grails.config.PropertySourcesConfig @@ -156,6 +159,10 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces config.setConversionService( conversionService ) } ((DefaultGrailsApplication)grailsApplication).config = config + + if (applicationContext instanceof ConfigurableApplicationContext) { + loadPluginConfigurationsToMicronautContext(applicationContext) + } } } @@ -283,4 +290,29 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces } } + @SuppressWarnings("GrMethodMayBeStatic") + private void loadPluginConfigurationsToMicronautContext(ConfigurableApplicationContext applicationContext) { + GrailsPluginManager pluginManager = applicationContext.getBean(GrailsPluginManager) + ConfigurableApplicationContext parentApplicationContext = (ConfigurableApplicationContext) applicationContext.parent + ConfigurableEnvironment parentContextEnv = parentApplicationContext.getEnvironment() + if (parentContextEnv instanceof MicronautEnvironment) { + if (log.isDebugEnabled()) { + log.debug("Loading configurations from the plugins to the parent Micronaut context") + } + final io.micronaut.context.env.Environment micronautEnv = ((io.micronaut.context.env.Environment) parentContextEnv.getEnvironment()) + final GrailsPlugin[] plugins = pluginManager.allPlugins + Integer priority = AbstractPropertySourceLoader.DEFAULT_POSITION + Arrays.stream(plugins) + .filter({ GrailsPlugin plugin -> plugin.propertySource != null }) + .forEach({ GrailsPlugin plugin -> + if (log.isDebugEnabled()) { + log.debug("Loading configurations from {} plugin to the parent Micronaut context", plugin.name) + } + micronautEnv.addPropertySource(PropertySource.of("grails.plugins.$plugin.name", (Map) plugin.propertySource.source, --priority)) + }) + micronautEnv.refresh() + applicationContext.setParent(parentApplicationContext) + } + } + } From d28190f8bcb68f528df45f64e275c89f8b9945bf Mon Sep 17 00:00:00 2001 From: David Kron Date: Tue, 8 Jun 2021 18:13:18 +0200 Subject: [PATCH 3/4] fix tests --- .../boot/config/GrailsApplicationPostProcessor.groovy | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy index a28400df2dc..9de746d7e8f 100644 --- a/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy +++ b/grails-core/src/main/groovy/grails/boot/config/GrailsApplicationPostProcessor.groovy @@ -292,6 +292,12 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces @SuppressWarnings("GrMethodMayBeStatic") private void loadPluginConfigurationsToMicronautContext(ConfigurableApplicationContext applicationContext) { + String[] beanNames = applicationContext.getBeanNamesForType(GrailsPluginManager) + if (beanNames.length == 0) { + // do not continue if PluginManager is not available + return + } + GrailsPluginManager pluginManager = applicationContext.getBean(GrailsPluginManager) ConfigurableApplicationContext parentApplicationContext = (ConfigurableApplicationContext) applicationContext.parent ConfigurableEnvironment parentContextEnv = parentApplicationContext.getEnvironment() @@ -314,5 +320,4 @@ class GrailsApplicationPostProcessor implements BeanDefinitionRegistryPostProces applicationContext.setParent(parentApplicationContext) } } - } From 1c61fb2a855082fd54f408f4df66df4ee2ed4856 Mon Sep 17 00:00:00 2001 From: David Kron Date: Tue, 8 Jun 2021 21:33:02 +0200 Subject: [PATCH 4/4] try fixing tests (are the different plugin.(yml|groovy) files generated in temp interferring with each other?) --- .../test/groovy/org/grails/plugins/BinaryPluginSpec.groovy | 4 +++- .../grails/plugins/GrailsPluginConfigurationClass.groovy | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy b/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy index 1f3d7b1476e..545205fae76 100644 --- a/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/plugins/BinaryPluginSpec.groovy @@ -9,6 +9,8 @@ import org.springframework.core.io.Resource import spock.lang.Shared import spock.lang.Specification +import java.nio.file.Files + class BinaryPluginSpec extends Specification { @Shared @@ -95,7 +97,7 @@ class MockConfigBinaryGrailsPlugin extends BinaryGrailsPlugin { } protected Resource getConfigurationResource(Class pluginClass, String path) { - String tempDir = System.getProperty("java.io.tmpdir") + File tempDir = Files.createTempDirectory("MockConfigBinaryGrailsPlugin").toFile() if (YAML_EXISTS && path == PLUGIN_YML_PATH) { File file = new File(tempDir, "plugin.yml") file.write("foo: bar") diff --git a/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy b/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy index 602141478fa..6f413170fce 100644 --- a/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy +++ b/grails-core/src/test/groovy/org/grails/plugins/GrailsPluginConfigurationClass.groovy @@ -13,6 +13,8 @@ import org.springframework.context.annotation.Configuration import org.springframework.core.io.FileSystemResource import org.springframework.core.io.Resource +import java.nio.file.Files + @CompileStatic @Configuration class GrailsPluginConfigurationClass extends GrailsAutoConfiguration { @@ -53,7 +55,7 @@ class GrailsPluginConfigurationClass extends GrailsAutoConfiguration { } protected Resource getConfigurationResource(Class pluginClass, String path) { - String tempDir = System.getProperty("java.io.tmpdir") + File tempDir = Files.createTempDirectory("MockTestGrailsPlugin").toFile() if (YAML_EXISTS && path == PLUGIN_YML_PATH) { File file = new File(tempDir, "plugin.yml") file.write("bar: foo\n") @@ -89,7 +91,7 @@ class GrailsPluginConfigurationClass extends GrailsAutoConfiguration { } protected Resource getConfigurationResource(Class pluginClass, String path) { - String tempDir = System.getProperty("java.io.tmpdir") + File tempDir = Files.createTempDirectory("MockTestTwoGrailsPlugin").toFile() if (YAML_EXISTS && path == PLUGIN_YML_PATH) { File file = new File(tempDir, "plugin.yml") file.write("bar: foo2\n")