Micronaut PropertySourceLoader resolution unpredictable when using micronaut.config.files
- Dominant language
- Groovy
- Stars
- 2.9k
- Forks
- 975
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 92
Description
### Expected Behavior
When using Micronaut beans (conditional beans in my case) in a Grails application and micronaut.config.files for external configuration files, resolution of config items within the external configuration file should be consistent.
### Actual Behaviour
With the introduction of MicronautYamlPropertySourceLoader in Grails 6.0, config resolution is unpredictable for Micronaut beans in Grails applications when using micronaut.config.files configuration.
Micronaut's DefaultEnvironment#evaluatePropertySourceLoaders can only populate a single PropertySourceLoader per extension which it stores in `loaderByFormatMap`. The PropertySourceLoader that is populated seems random based on the order in which the classloader finds matching service configurations in META-INF/services files.
Depending on which order the service configurations are loaded the map may end up with one of MicronautYamlPropertySourceLoader OR YamlPropertySourceLoader.
MicronautYamlPropertySourceLoader requires the config be nested under `environments.`, while YamlPropertySourceLoader requires the config to be at the top level and not nested.
I'm unaware of a way to influence the order in which the classloader loads those service configurations, and Micronaut doesn't seem to take into account the Orderable nature of the PropertySourceLoaders when storing them in the map.
When loading PropertySources from default locations ie classpath:/ and file:config/, Micronaut will attempt to use each PropertySourceLoader in sequence, whereas when processing any files configured in micronaut.config.files it will only use the PropertySourceLoader stored in the `loaderByFormatMap`.
I suspect that a fix will be required in Micronaut but this appears to only impact Grails applications because of Grails custom PropertySourceLoader implementations that clash with the ones provided by Micronaut itself.
### Steps To Reproduce
1. Create a conditional Micronaut bean based on some property being enabled.
2. Configure the bean to be disabled in grails-app/conf/application.yml
3. Create an application-foo.yml somewhere outside of the classpath of the application which sets config to enable the bean with the config nested under `environments.foo` and also at the root level. Comment out the root level configuration.
4. Start the application with environment variables configuring MICRONAUT_CONFIG_FILES to point to the absolute path of application-foo.yml and GRAILS_ENV set to 'foo'. You can also set MICRONAUT_ENVIRONMENTS to 'foo' but it makes no difference.
5. Observe that the bean is not enabled (Consider setting io.micronaut.context.condition log level to DEBUG). If the bean is enabled, comment out the config enabling it that is nested under `environments.foo` and uncomment the root level config.
You can observe the functionality working by removing MICRONAUT_CONFIG_FILES and application-foo.yml is either on the classpath or in the config directory relative to the running application.
### Environment Information
OS: Pop!OS 22.04
Java: 11.0.11-hs-adpt
### Example Application
N/A
### Version
6.1.2
Contributor guide
Assessment
This issue has not been assessed yet.