Problem After upgrade from Spring Boot 3.3 to Spring Boot 3.4 a property which uses custom loader and contains placeholder inside it is not resolved properly.
application.yaml:
spring:
config:
import: sm-stub://
app:
environment: qa
a-service-url: ${sm-stub\://projects/my-project/secrets/${app.environment}_a-service_url/versions/latest}
In the application:
@Value("${app.a-service-url}")
private String aServiceUrl;
The resolved value is "//projects/my-project/secrets/qa_a-service_url/versions/latest" [NOK]
Expected value is the one returned by the custom property source for the "projects/my-project/secrets/qa_a-service_url/versions/latest" location.
Minimal reproducible example https://github.com/semeiskii/spring-boot-property-resolving-bug
Comment From: bclozel
It looks like a duplicate of #34124. Please check the discussion there for best practices. Also, this should be "fixed" in Spring Framework 6.2.2 already so you can verify that your application works with that version right now.
Comment From: semeiskii
Hello @bclozel,
34124 is about the ':' char in placeholder which should be escaped: "sm\://...".
I updated the minimal reproducible example: * it does escape ':' in the placeholder * if forced to use Spring 6.2.2
The problem is still present.
Comment From: snicoll
Thanks for the report and the sample.
As pointed out in the related issue, : is a reserved character that you shouldn't be using. That double indirection that you use makes ${sm-stub://projects/my-project/secrets/${app.environment}_a-service_url/versions/latest} very artificial.
If you insist on it, you can escape the separator. However, you need to double backslash it for the backslah to be taken into account, i.e.:
app.a-service-url:${sm-stub\\://projects/my-project/secrets/${app.environment}_a-service_url/versions/latest}
Unfortunately, this makes me discover another regression in the parser so I'll use this issue to fix it.
Comment From: semeiskii
Hello @snicoll,
In the minimal reproducible example I provided the ':' is already escaped with one backslash:
app.a-service-url:${sm-stub\://projects/my-project/secrets/${app.environment}_a-service_url/versions/latest}
If I try to escape it with double backslash as you mentioned, the custom property source (SecretManagerStubPropertySource#getProperty) is called with the parameter name="sm-stub://projects/my-project/secrets/".
Expected, it will first be called with the parameter name="sm-stub://projects/my-project/secrets/qa_a-service_url/versions/latest".
I guess this is bug you refering to (and using this ticket to solve it)?
UPD
even if I change my example to use double backslash
application.properties:
app.a-service-url=${sm-stub\\://projects/my-project/secrets/${app.environment}_a-service_url/versions/latest}
SecretManagerStubPropertySource:
@Override
public Object getProperty(String name) {
if ("sm-stub://projects/my-project/secrets/qa_a-service_url/versions/latest".equals(name)) {
return EXPECTED_VALUE;
}
return null; //<--don't throw an exeption
}
The resolved value is still wrong: "qa_a-service_url/versions/latest"
Comment From: snicoll
provided the ':' is already escaped with one backslash:
Please read my previous comment, I mentioned that two backslashes are necessary in properties file (nothing to do with this issue)
If I try to escape it with double backslash as you mentioned,
Thanks, but we don't need any confirmation of what was already confirmed. I am aware that there is another problem when you escape the separator correctly. This is what this issue is all about.