I am using Spring Boot 3.1.4 (tested on 3.0.5 as well) and noticed something that caused problems downstream. I am not sure if this is a bug in SpringBoot or misuse from my side (if so, please advise what should be the appropriate way)
I have a multitenant application where I need to configure DataSource for each tenant. For that, I used configuration properties under spring.datasource
by autowiring bean DataSourceProperties
.
When I try to get all XA datasource properties which are defined under spring.datasource.xa.properties
they are mapped to Map<String, String>
(so for instance if I define property spring.datasource.xa.properties.my-first-property=firstValue
in application.properties
that will be mapped to map as my-first-property:firstValue
).
And when all properties are read only from application.properties
there are no problems.
The interesting part comes when I override some of configuration properties via environment variable (that is the case when I deploy the application to the Kubernetes cluster for instance). Property defined via environment variable is defined exactly as SpringBoot recommends in relaxed binding section here.
When this occurs, I get "duplicate" keys in map - one key is coming from application.properties
and is mapped as-is (camelCase or kebab-case, whatever is defined in configuration file) and other is all lowercase without dashes. But both keys have value which is defined in environment variable (as it should be).
So for instance, if I defined in application.properties
parameter spring.datasource.xa.properties.my-first-property=firstValue
and I also define environment variable as SPRING_DATASOURCE_XA_PROPERTIES_MYFIRSTPROPERTY=newValue
I would have two entries in map - my-first-value
and myfirstvalue
, both having the value newValue
.
I'll share relevant classes that demonstrate such behavior:
@Configuration
public class MySimpleConfiguration {
@Autowired
DataSourceProperties dataSourceProperties;
@Bean
public String myDummyBean() {
Map<String, String> xaProperties = dataSourceProperties.getXa().getProperties();
System.out.println("XA PROPERTY:\n" + xaProperties);
return "myDummyBean";
}
}
spring.datasource.xa.properties.my-first-property=firstValue
spring.datasource.xa.properties.my-second-property=secondValue
I run it via IntelliJ IDEA with such configuration: https://i.stack.imgur.com/yrzAL.png
And the logs I get when this is run are:
2023-11-09 12:02:47,320 [,] DEBUG o.s.b.f.s.DefaultListableBeanFactory Creating shared instance of singleton bean 'myDummyBean'
XA PROPERTY:
{myfirstproperty=newFirstValue, my-first-property=newFirstValue, my-second-property=secondValue}
I would expect that value from environment variable is overridden in Map
but that only one key exist - one which is contained in configuration file application.properties
.
Why is this causing trouble for me? When I extract all XA properties and pass them through to actual DB Driver (in my case IBM DB2 driver), autobinding of parameters fail with exception that there is no matching key with all lowercase without dashes. I overcame this by explicitly removing such properties from map, but again, why are they "duplicated" in the first place?