Skip to content

Inconsistency between binder property paths #17615

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

Closed
copitz opened this issue Jul 24, 2019 · 4 comments
Closed

Inconsistency between binder property paths #17615

copitz opened this issue Jul 24, 2019 · 4 comments
Labels
status: duplicate A duplicate of another issue

Comments

@copitz
Copy link

copitz commented Jul 24, 2019

TL;DR:
The keys of nested properties bound to a Map<String, String> look like "foo.0.bar" but should be "foo[0].bar".

Further explanation:
This one took me hours to figure out and I managed to work around it by replacing all "\\.([0-9]+)(\\.|$)"with [$1]$2 in the keys of the map - anyway I think that it could help someone stumbling upon this and especially when it could be fixed:

To enable polymorph configuration property bindings (and also retrieve such bindings from other sources like a database or webservice) I let spring boot bind (nested) properties under a certain path to a Map<String, String> and use this as MapConfigurationPropertySource for the new Binder API to bind them to the concrete classes.

This worked fine until I stumbled upon collections/arrays leading to weired behaviors of the binder (e.g. keeping dots in the property path). After a while I found out that this was caused by the wrong form of the property paths.

Please let me know if I should add some code / test case to make this clearer.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 24, 2019
@mbhave
Copy link
Contributor

mbhave commented Jul 24, 2019

@copitz I'm not sure I fully understood the issue. A minimal sample that showcases the issue or a test case would be very useful.

@mbhave mbhave added the status: waiting-for-feedback We need additional information before we can continue label Jul 24, 2019
@copitz
Copy link
Author

copitz commented Jul 24, 2019

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Jul 24, 2019
copitz pushed a commit to copitz/spring-boot-issue-17615 that referenced this issue Jul 24, 2019
@mbhave
Copy link
Contributor

mbhave commented Jul 24, 2019

Thanks for the sample @copitz. I took a look and this is the expected behavior:

When ApplicationBinderTest runs, the first binding that occurs is binding properties under the acme prefix to ExampleProperties. Properties are bound to a Map<String, Map<String, String>>. When the binder binds properties to a Map, it removes everything that is not an alpha-numeric character. In this case, [ and ] get removed and the values in the Map end up being entity-filters.products.0.pattern and entity-filters.products.0.include. This is documented here

When binding to Map properties, if the key contains anything other than lowercase alpha-numeric characters or -, you need to use the bracket notation so that the original value is preserved. If the key is not surrounded by [], any characters that are not alpha-numeric or - are removed.

This is why it works when you add the [ ] for the second test.

When you use Spring Boot's @ConfigurationProperties to bind directly to StoreApplication, it has the key in the original form (since you are directly binding keys under acme.applications.foo ).

One way to avoid manually fixing the property names would be to specify the properties using the convention mentioned in the docs linked above. Using acme.applications.foo.[entity-filters.products[0].pattern] would work as the original [0] would be preserved.

We have an open issue #13404 for investigating if map keys can preserve their original value without having to surround them with [ ]. I'll close this one in favor of that.

@mbhave mbhave closed this as completed Jul 24, 2019
@mbhave mbhave added status: duplicate A duplicate of another issue and removed status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged labels Jul 24, 2019
@copitz
Copy link
Author

copitz commented Jul 25, 2019

Thank you @mbhave for the clarification

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: duplicate A duplicate of another issue
Projects
None yet
Development

No branches or pull requests

3 participants