-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Thanks to the team for taking the time.
Affects: 5.3.18 and main branch
Affected code
Lines 482 to 502 in 28ca0dd
| if (this.propertySourceNames.contains(name)) { | |
| // We've already added a version, we need to extend it | |
| PropertySource<?> existing = propertySources.get(name); | |
| if (existing != null) { | |
| PropertySource<?> newSource = (propertySource instanceof ResourcePropertySource ? | |
| ((ResourcePropertySource) propertySource).withResourceName() : propertySource); | |
| if (existing instanceof CompositePropertySource) { | |
| ((CompositePropertySource) existing).addFirstPropertySource(newSource); | |
| } | |
| else { | |
| if (existing instanceof ResourcePropertySource) { | |
| existing = ((ResourcePropertySource) existing).withResourceName(); | |
| } | |
| CompositePropertySource composite = new CompositePropertySource(name); | |
| composite.addPropertySource(newSource); | |
| composite.addPropertySource(existing); | |
| propertySources.replace(name, composite); | |
| } | |
| return; | |
| } | |
| } |
Discussion
The addPropertySource method is affected by a bug IMO where the effect of the if statement is reverted by the fact that PropertySources are hashed using their name property.
When code reaches the affected if-statement, it means that a PropertySource of name foo is already registered in the Spring context, and that PropertySource is assigned to the existing variable. The idea is to replace (L499) the old property source with name foo with the CompositePropertySource containing both.
The problem is, given that
CompositePropertySourceholds a Set of PropertySources- PropertySources are hashed by their
getName(), which is not extended currently - Both PropertySources to compose have same name
In the end, the second PropertySource won't be added and CompositePropertySource will hold only one PropertySource of name foo
Affected case
We found a problem when multiple teams work on different Java libraries, each declaring some property sources from classpath files.
In the end, we discovered that if two libraries hold the same env.yaml in different packages, but the associated PropertySource name is computed by the file name (not fully qualified path), two libraries define a PropertySource named env.yaml and clash.
We expect this to happen even if teams define any kind of MapPropertySource with the same non-unique name. We have implemented a workaround by using the fully qualified resource URL.
Suggested solution
Have CompositePropertySource use List than Set?
Test case
Not yet available