When a YAML configuration using explicit type tags is loaded, org.yaml.snakeyaml.constructor.ConstructorException
is thrown.
Spring Boot version: 2.2.6.RELEASE JDK 8 and 11 produces the same issue Used to work with 1.5.1.RELEASE
Example YAML configuration:
exampleConfig:
example: !!example.DefaultExampleType
property: 'test'
The issue occurs when property: 'test'
is converted, which should be a String
.
This is the exception stack trace:
java.lang.IllegalStateException: Failed to load property source from location 'classpath:/application.yml'
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:545)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadForFileExtension(ConfigFileApplicationListener.java:494)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:464)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.lambda$null$7(ConfigFileApplicationListener.java:443)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.lambda$load$8(ConfigFileApplicationListener.java:443)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:440)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.lambda$load$0(ConfigFileApplicationListener.java:335)
at org.springframework.boot.context.config.FilteredPropertySource.apply(FilteredPropertySource.java:54)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:323)
at org.springframework.boot.context.config.ConfigFileApplicationListener.addPropertySources(ConfigFileApplicationListener.java:214)
at org.springframework.boot.context.config.ConfigFileApplicationListener.postProcessEnvironment(ConfigFileApplicationListener.java:198)
at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEnvironmentPreparedEvent(ConfigFileApplicationListener.java:188)
at org.springframework.boot.context.config.ConfigFileApplicationListener.onApplicationEvent(ConfigFileApplicationListener.java:176)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76)
at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53)
at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:345)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at example.YamlExampleApplication.loadSpringBoot(YamlExampleApplication.java:84)
at example.YamlExampleApplication.main(YamlExampleApplication.java:48)
Caused by: org.yaml.snakeyaml.constructor.ConstructorException: Cannot create property=property for JavaBean=DefaultMatcher{property=null}
in 'reader', line 3, column 14:
example: !!example.DefaultExampleType
^
argument type mismatch
in 'reader', line 4, column 19:
property: 'test'
^
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.constructJavaBean2ndStep(Constructor.java:270)
at org.yaml.snakeyaml.constructor.Constructor$ConstructMapping.construct(Constructor.java:149)
at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:309)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:216)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:205)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:94)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:465)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:184)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:446)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:521)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:216)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:205)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:94)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping2ndStep(BaseConstructor.java:465)
at org.yaml.snakeyaml.constructor.SafeConstructor.constructMapping2ndStep(SafeConstructor.java:184)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructMapping(BaseConstructor.java:446)
at org.yaml.snakeyaml.constructor.SafeConstructor$ConstructYamlMap.construct(SafeConstructor.java:521)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObjectNoCheck(BaseConstructor.java:216)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:205)
at org.springframework.boot.env.OriginTrackedYamlLoader$OriginTrackingConstructor.constructObject(OriginTrackedYamlLoader.java:94)
at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:164)
at org.yaml.snakeyaml.constructor.BaseConstructor.getData(BaseConstructor.java:129)
at org.yaml.snakeyaml.Yaml$1.next(Yaml.java:548)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:160)
at org.springframework.beans.factory.config.YamlProcessor.process(YamlProcessor.java:134)
at org.springframework.boot.env.OriginTrackedYamlLoader.load(OriginTrackedYamlLoader.java:75)
at org.springframework.boot.env.YamlPropertySourceLoader.load(YamlPropertySourceLoader.java:50)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.loadDocuments(ConfigFileApplicationListener.java:562)
at org.springframework.boot.context.config.ConfigFileApplicationListener$Loader.load(ConfigFileApplicationListener.java:518)
... 26 common frames omitted
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
The original cause is java.lang.IllegalArgumentException: argument type mismatch
. It is thrown because the type of value test
of property: 'test'
is not converted to String
, but remains OriginTrackedValue$OriginTrackedCharSequence
.
I have created an example project showcasing this. It also shows how the YAML files are parsed by SnakeYAML if manually loaded and not by the Spring Boot auto configuration.
Unsure if related to #8540.
Comment From: philwebb
21596 has recently been applied to further restrict the use of custom types as a security precaution so it may not be possible to make things work in same way as they did in 1.5.
@kappmeier Can you explain a bit more about your use-case? We need to be able to ultimately map a YAML document to a flat PropertySource
and we didn't anticipate custom types would be used.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: kappmeier
I create a list of matchers. The matcher type is an interface, but there are multiple implementing classes, and as far as I know I have to provide the exact type.
If this is forbidden in the future there will certainly be ways to initialize the object in a different way.
Regarding #21596 it is at least a good thing to throw some kind of error explaining that certain YAML features are not supported.
Comment From: wilkinsona
Thanks for your patience. How do you expect your custom types to be mapped to entries in a property source and then potentially bound to a @ConfigurationProperties
class? Perhaps you could share a small sample that reproduces the failure and illustrates what you're trying to do?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.