Most of the setters in BasicDataSource can be configured from application.yml. https://commons.apache.org/proper/commons-dbcp/apidocs/org/apache/commons/dbcp2/BasicDataSource.html#setConnectionProperties-java.lang.String- cannot be configured.
Both Hikari and Tomcat have ways of configuring the properties that get sent to the driver but dbcp2 does not as this setter seems not to get registered by the @ConfigurationProperties annotation.
This limits the configurability of a dbcp2 datasource via spring boot
Comment From: snicoll
Both Hikari and Tomcat have ways of configuring the properties that get sent to the driver but dbcp2 does not as this setter seems not to get registered by the
@ConfigurationPropertiesannotation.
I am not sure what you mean by that but there is nothing that Spring Boot does specifically for Hikari or Tomcat. connectionProperties setter uses a String but the getter is a Properties. There is not much we can do about that I am afraid as we don't own the code.
Can we take a step back and can you describe what you're trying to do concretely?
Comment From: jbotuck
I would like to configure the datasource with the property enableRowsetSupport=1.
The way I would like to do it is by setting a spring boot property. spring.datasource.dbcp2.connection-properties=enableRowsetSupport=1;
Spring boot allows this kind of configuration for both hikari and tomcat using spring.datasource.hikari.data-source-properties and spring.datasource.tomcat.connection-properties.
If its not possible to bring dbcp2 up to parity with the other datasources because dbcp2 violates the javabean spec then how should I configure these properties in a spring boot application?
Comment From: snicoll
Spring boot allows this kind of configuration for both hikari and tomcat using spring.datasource.hikari.data-source-properties and spring.datasource.tomcat.connection-properties.
Again, as I've mentioned previously, there is nothing that Spring Boot does specifically for those two properties. Both Hikari and Tomcat exposes an accessor named "connection-properties" and that's about it.
If its not possible to bring dbcp2 up to parity with the other datasources because dbcp2 violates the javabean spec then how should I configure these properties in a spring boot application?
I've copy/pasted spring.datasource.dbcp2.connection-properties=enableRowsetSupport=1; in application.properties of a fresh app configured from start.spring.io and I can see via the debugger that BasicDataSource#setConnectionProperties is invoked with enableRowsetSupport=1;. It should be noted though that, because this property is unusual, there is no code assistance in the IDE.
I am going to close this now as there is no indication of a problem in Spring Boot.
Comment From: jbotuck
Can we add the property to the documentation here? https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#data-properties.
I'd feel better about using this if it wasn't some undocumented feature that can be removed at any time.
Comment From: snicoll
Can we add the property to the documentation here? https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#data-properties.
I am afraid we can't. Because it isn't really a valid property, it isn't detected and therefore not documented.
I'd feel better about using this if it wasn't some undocumented feature that can be removed at any time.
Documenting it wouldn't change anything to the fact that the DBCP2 project may decide to remove or change it at any time. We don't have any control on that.
Comment From: jbotuck
Documenting it wouldn't change anything to the fact that the DBCP2 project may decide to remove or change it at any time. We don't have any control on that.
I'm more worried about whatever logic spring boot has for discovering setters at runtime suddenly becoming as strict as whatever logic spring boot has for discovering accessors when generating metadata.
Comment From: jbotuck
I guess what I really want here is an additional entry here https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json for this property. But I get it if you don't want to do that.
Comment From: mdeinum
Spring (nor Spring Boot) uses any logic, it is all deferred to plain Java using introspection and the JDK introspection won't detect properties for non matching set/get types. As this isn't detected spring isn't capable of setting this value. This is just how introspection, based on the java beans specification, works. There is nothing Spring nor Spring Boot could do about that.
Adding a property to that json wouldn't be helpful either as that is for documentation purpose and IDE support (AFAIK) and even adding it wouldn't help (nor are all the Hikari or Tomcat JDBC properties in there).
To work around your issue you could register a BeanPostProcessor for a BasicDataSource and use the addConnectionProperty method to set the desired additional properties. Important is to use the postProcessBeforeInitialization else setting the property might be too late.
Comment From: wilkinsona
@mdeinum Thanks for trying to help but "as this isn't detected spring isn't capable of setting this value" isn't accurate. As @snicoll described above, the binder can set the property despite it appearing to be write-only from a JavaBeans perspective due to the unconventional getter.
I'm wondering if we should update the annotation processor or add some manual metadata for this one after all. The asymmetry of what is documented and what can be bound doesn't feel quite right to me.
Comment From: snicoll
I have some sympathy for that argument Andy. The fact that the binder can do things the annotation processor doesn't detect is annoying but, on the other hand, I think we need to draw a line somewhere.
Updating the AP to be more lenient if there is a getter/setter and the type does not match could be an option but I am not keen at all to expose properties that only have a setter. This is most probably going to break users that are relying on the current conventions to only expose what they want.
Thinking about this one so more, I think the problem is to do with third party class binding. Sure that's convenient and we make sure that the version we test against has "all the properties" exposed without us having to change any code but:
- Not having documentation for those is annoying and users have been reported that in the past several times
- We're at the mercy of whatever our 3rd party binding does. Although I find the API for connection properties a bit weird, we can't expect the DBCP2 project to align with our conventions
- We've moved away from third party binding for other features. Flyway comes to mind.
My opinion is that we should stop changing things for the third party binding use case and we should keep the current JavaBean standard expectations. Although it is a lot of work, I suggest we create a separate issue to remove third party binding for all connection pools and do the mapping ourselves. We could document the properties and add a test that checks that for every javabean property found via reflection we have a mapping.
Thanks @jbotuck for bearing with me!
Comment From: mdeinum
@mdeinum Thanks for trying to help but "as this isn't detected spring isn't capable of setting this value" isn't accurate. As @snicoll described above, the binder can set the property despite it appearing to be write-only from a JavaBeans perspective due to the unconventional getter.
Totally read over that comment, so sorry for the pollution and the setter will be invoked even if it isn't documented (did the same in the past with other DataSource related properties which weren't documented at the time).