Skip to content

PropertySourcesPlaceholderConfigurer placeholder resolution fails in several scenarios #34861

Closed
@sbrannen

Description

@sbrannen

Overview

In summary, the implementation of the placeholder resolution algorithm in PropertySourcesPlaceholderConfigurer fails in several scenarios, and the root cause for this category of failures has existed since PropertySourcesPlaceholderConfigurer was introduced in Spring Framework 3.1.

if (this.environment != null) {
this.propertySources.addLast(
new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
@Override
public String getProperty(String key) {
return this.source.getProperty(key);
}
}
);
}

In the original code above, we see that a PropertySource is implemented as an anonymous inner class which delegates to Environment#getProperty, which in turn delegates to an internal PropertySourcesPropertyResolver, which in turn performs placeholder resolution.

And... that anonymous PropertySource is added to the MutablePropertySources managed by PropertySourcesPlaceholderConfigurer, which wraps those MutablePropertySources in its own PropertySourcesPropertyResolver, which in turn performs placeholder resolution.

Thus, we effectively have always had a top-level PropertySourcesPropertyResolver that indirectly delegates to a nested PropertySourcesPropertyResolver, which results in double placeholder parsing and resolution.

And that is what leads to a whole category of bugs.

In #27947, I realized that we were lacking proper support for ignoreUnresolvablePlaceholders in the nested PropertySourcesPropertyResolver, and due to #34315 and #34326 it became apparent that we are currently (as of Spring Framework 6.2.6) lacking support for the configured escapeCharacter in the nested PropertySourcesPropertyResolver as well.

Analysis

My research into #34315 and #34326 led me to realize that the reported bug for escaped placeholders being evaluated despite the escaping was in fact due to the same underlying flaw in the core logic of PropertySourcesPlaceholderConfigurer.

Namely, we should never have indirectly used or directly created a nested PropertySourcesPropertyResolver.

Instead, properties from property sources from the Environment should be accessed directly without duplicate/nested placeholder resolution, since the top-level PropertySourcesPropertyResolver already handles placeholder resolution.

Related Issues

Metadata

Metadata

Assignees

Labels

in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions