Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback with placeholder is evaluated even if the fallback is not required #26268

Closed
FrancoCorleone opened this issue Dec 14, 2020 · 4 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@FrancoCorleone
Copy link

Hello all,
used spring boot: 2.2.1.RELEASE
Problem: When defining application.yml properties I want to use something like:
property: ${FOO:someFallbackWithEnv_${BAR}}

someOtherProperty: ${property}

With @ConfigurationProperties it works as expected but with injection via @Value or in application.yml (someOtherProperty) it fails with "could not resolve BAR". I think it is not expected as FOO was defined as env variable so the other part should not be processed at all IMO.

@wilkinsona
Copy link
Member

This is standard behaviour for Spring Framework's PropertyPlaceholderHelper where it recursively resolves the value before considering any default value separated by :. The reason it works with configuration properties is that they use a lenient PropertyPlaceholderHelper that ignores unresolvable placeholders where as @Value processing does not.

I'm not aware of the reasons behind the default value being processed in full before it's then discarded. On the face of it, it feels less efficient than it could be, but there may well be something that I've overlooked. We'll get the Framework team to take a look.

@snicoll snicoll transferred this issue from spring-projects/spring-boot Dec 14, 2020
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 14, 2020
@FrancoCorleone
Copy link
Author

Great, I did a quick workaround of setting empty in nested env variable and checked it myself in the code, but it doesn't feel like an intuitive behavior. Thanks

@rstoyanchev rstoyanchev added the in: core Issues in core modules (aop, beans, core, context, expression) label Nov 11, 2021
@snicoll snicoll changed the title Default value for configuration in application.yml is parsed even when defined env variable is there Fallback with placeholder is evaluated even if the fallback is not required Nov 29, 2023
@snicoll snicoll added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 29, 2023
@snicoll snicoll self-assigned this Nov 29, 2023
@snicoll snicoll added this to the 6.1.x milestone Nov 29, 2023
@snicoll
Copy link
Member

snicoll commented Nov 29, 2023

That looks like a bug to me and I wish we'd resolve the fallback lazily. I'll see what we can do.

@snicoll snicoll modified the milestones: 6.1.x, 6.2.x Dec 22, 2023
@snicoll
Copy link
Member

snicoll commented Dec 22, 2023

Unfortunately, fixing it goes in the direction of rewriting the parser for supporting the escape of placeholder and separator. This is ongoing but need a new feature release, see #9628

@snicoll snicoll modified the milestones: 6.2.x, 6.2.0-M1 Dec 29, 2023
snicoll added a commit to snicoll/spring-framework that referenced this issue Feb 2, 2024
This commit provides a rewrite of the parser for properties containing
potentially placeholders.

Assuming a source where `firstName` = `John` and `lastName` = `Smith`,
the "${firstName}-${lastName}" property is evaluated as "John-Smith".

Compared with the existing implementation in PropertyPlaceholderHelper,
the new implementation offers the following extra features:

1. Placeholder can be escaped using a configurable escape character.
When a placeholder is escaped it is rendered as is. This does apply to
any nested placeholder that wouldn't be escaped. For instance,
"\${firstName}" is evaluated as "${firstName}".
2. The default separator can also be escaped the same way. When the
separator is escaped, the left and right parts are not considered as
the key and the default value respectively. Rather the two parts
combined, including the separator (but not the escape separator) are
used for resolution. For instance, ${java\:comp/env/test} is looking
for a "java:comp/env/test" property.
3. Placeholders are resolved lazily. Previously, all nested placeholders
were resolved before considering if a separator was present. This
implementation only attempts the resolution of the default value if the
key does not provide a value.
4. Failure to resolve a placeholder are more rich, with a dedicated
PlaceholderResolutionException that contains the resolution chain.

See spring-projectsgh-9628
See spring-projectsgh-26268
snicoll added a commit that referenced this issue Feb 15, 2024
This commit provides a rewrite of the parser for properties containing
potentially placeholders.

Assuming a source where `firstName` = `John` and `lastName` = `Smith`,
the "${firstName}-${lastName}" property is evaluated as "John-Smith".

Compared with the existing implementation in PropertyPlaceholderHelper,
the new implementation offers the following extra features:

1. Placeholder can be escaped using a configurable escape character.
When a placeholder is escaped it is rendered as is. This does apply to
any nested placeholder that wouldn't be escaped. For instance,
"\${firstName}" is evaluated as "${firstName}".
2. The default separator can also be escaped the same way. When the
separator is escaped, the left and right parts are not considered as
the key and the default value respectively. Rather the two parts
combined, including the separator (but not the escape separator) are
used for resolution. For instance, ${java\:comp/env/test} is looking
for a "java:comp/env/test" property.
3. Placeholders are resolved lazily. Previously, all nested placeholders
were resolved before considering if a separator was present. This
implementation only attempts the resolution of the default value if the
key does not provide a value.
4. Failure to resolve a placeholder are more rich, with a dedicated
PlaceholderResolutionException that contains the resolution chain.

See gh-9628
See gh-26268
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants