Placeholder resolution no longer considers exact match before resolving the placeholder key #34124
Description
(Originally posted in spring-projects/spring-boot#43579)
Overview
Hello, I'm a maintainer of the Spring Framework on Google Cloud. We have recently been working on upgrading Spring Cloud to 2024.0 and Spring Boot to 3.4. So far, so good, except for our secretmanager
integration.
The way we support bean injections for this integration is by specifying properties with the syntax ${sm://secret_id}
, implying a request to the Secret Manager service.
Unfortunately, the colon :
character is now being interpreted differently since 00e05e6, with the resulting behavior being to interpret it as "property sm
with fallback value of //secret_id
". We have confirmed this in our code sample.
What have we tried so far
We have tried introducing our own static PropertySourcesPlaceholderConfigurer
bean (see bean declaration, see source), set up to be configured before the default PlaceholderConfigurer
autoconfiguration.
Interestingly, this works perfectly for @Value
annotations such as @Value("${sm://my_secret}")
(see example), but not for @Configuration
classes that reference a properties file (in our case, simply application.properties
). I confirmed that the following code has the default PropertySourcesPlaceholderConfigurer
(this.placeholdersResolver
in Binder.java
) when debugging my application:
More context
- We use a custom config data location resolver. I suspect this may have to do with how the properties file decides to resolve its placeholder.
Alternatives considered
We are also thinking of additionally supporting the ${sm//my_secret}
syntax (without the colon) as a workaround to escape the colon with a backslash, however we would like to avoid our users changing their code as much as possible.
Questions
My first question is: Why would the properties file be parsed with a different PlaceholderConfigurer
than what's specified in the static
bean? I believe this bean is meant to be a singleton, so I'm not sure where in the application it's decided to associate the default configurer to this configuration.
- PS: I found that Binder will by default create a plain PropertyPlaceholderHelper
My second question is: Is there a preferred way to adapt to this new behavior?