Configuring a datasource-proxy in Spring Boot

Have you ever heard about datasource proxies? No worries, it’s not complicated at all.

Let’s say you want to access the database from an application. First you have to configure a DataSource object which creates the actual Connections to the underlying database. With the Connection objects you can execute queries, get the metadata of the database and you can do other things as well.

Of course, not many people are using the Connection class directly as there are many frameworks (for example JPA implementations) which are hiding it for us. Now let’s say you want to add some metrics and measure the execution time of the queries you are sending to the database, or let’s say you wanna log the queries. For this type of task, altering the behavior of the Connection object is the best candidate and it can be easily done by creating a custom DataSource object – which acts as a factory to create Connection objects but now it will create custom Connection objects with the additional logic. However, we are not discarding any of the existing functionality but we are going to extend it using the Proxy design pattern. I don’t want to go into the details of the pattern as there are plenty of good articles about it and it’s relatively simple to understand.

In this article, I’m going to use an existing library called datasource-proxy which has multiple features built-in like query logging, query metrics, slow query detection. Configuring this in a standard application is not complicated and can be done with a few lines of code:

where originalDataSource is the actual DataSource object which is creating the Connections.

Configuration issue with Spring Boot

Okay, now we know how to configure the proxy DataSource object. In a standard Spring application one could do the following way:

Spring Boot is a really great tool as it’s easy to use, almost no configuration is necessary and everything is working out-of-the-box. There is no difference with the DataSource objects. Spring Boot is built on top of so called AutoConfigurations which are working when certain classes are on the classpath or certain type of beans are already defined, etc.

If you try to define a custom DataSource bean in your Spring Boot app, the AutoConfiguration will be aware that “oh there is a custom DataSource bean, I don’t want to override that” and it won’t do the automatic configuration. In this case, you have to manually configure a DataSource which is a pain in the ass when we have Spring Boot, right?

BeanPostProcessor for the help

BeanPostProcessors are a great things, you can read more about them here. Long story short, you can define classes implementing the BeanPostProcessor interface that have two methods. The method we care about is the  postProcessAfterInitialization which will be called by the Spring container after the a bean is fully configured. Here we can simply check whether the bean instance is a DataSource and if yes, we can simply wire in our custom proxy DataSource object. After we have the class, we can simply register this class as a bean into the container.

Now, if you execute a simple test which does some database operation you can see the following log message:

This simple trick with the BeanPostProcessor can be easily used by any Spring application whether it’s Boot or not.

The source can be found on GitHub. Feel free to reach me out in case of questions in the comments or on Twitter.

5 Replies to “Configuring a datasource-proxy in Spring Boot”

  1. Nice article

    I assume there is some overhead when logging the queries using the proxy and that one would like to only see the metrics in pre-production environment or in very limited cases production?
    From my understanding the bean post processor would be picked up by spring boot for every environment, when looking at the example.

    Do you not think that a @Profile with @Configuration (for constructing the proxy data source) would work better for the specific environment that you are testing rather than the bean post processor?

    1. You can always add the proper profile over the DatasourceProxyBeanPostProcessor instead of creating separate configuration for it – Cheers mate !:)

    2. It definitely have an overhead, I haven’t measured it though.

      If you want, you can create custom configurations for different environments but you can also add the @Profile annotation to the BeanPostProcessor to run only in the specified environments.

Leave a Reply

Your email address will not be published. Required fields are marked *