Skip to content

How to debug connection pool configurations with springboot?

1. The purpose of this post

Sometimes, you may want to know what connection pool you are using with Spring Boot. This demo shows how to debug the connection pooling configurations when using Spring Boot applications. It’s very easy to do this job—let’s get started.

2. Environments

  • Spring Boot 1.x and 2.x
  • Java 1.8+

3. The solution

3.1 Add AspectJ to your POM.xml

To inspect the datasource configurations, we will use the Spring AOP solution. It depends on these artifacts:

pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.12</version>
</dependency>

To demonstrate different connection pooling configurations, we add this connection pool implementation as follows:

pom.xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.2.0</version>
</dependency>

3.2 Write an aspect to intercept the process

Suppose we have a DAO class com.sb1jt.dao.CityDao like this:

CityDao.java
package com.sb1jt.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class CityDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public City getCity(Integer id) {
// Call jdbcTemplate here
}
}

We must write an aspect to intercept the datasource calling process like this:

ConnectionAspect.java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Aspect
@Configuration
public class ConnectionAspect {
private static Logger logger = LoggerFactory.getLogger(ConnectionAspect.class);
@Autowired
private DataSource ds;
@Before("execution(* com.sb1jt.dao.*.*(..))")
public void logBeforeConnection(JoinPoint jp) throws Throwable {
if (ds instanceof org.apache.tomcat.jdbc.pool.DataSource) { // Default connection pool of Spring Boot 1.x
org.apache.tomcat.jdbc.pool.DataSource tomcatDs = (org.apache.tomcat.jdbc.pool.DataSource) ds;
logger.info("Datasource props: {}", tomcatDs.getPoolProperties());
} else if (ds instanceof com.zaxxer.hikari.HikariDataSource) { // Default connection pool of Spring Boot 2.x
com.zaxxer.hikari.HikariDataSource hikariDs = (com.zaxxer.hikari.HikariDataSource) ds;
logger.info("Datasource props: {}", hikariDs.getDataSourceProperties());
}
}
@After("execution(* com.sb1jt.dao.*.*(..))")
public void logAfterConnection(JoinPoint jp) throws Throwable {
String methodName = jp.getTarget().getClass().getName() + ":" + jp.getSignature().getName();
if (ds instanceof org.apache.tomcat.jdbc.pool.DataSource) {
org.apache.tomcat.jdbc.pool.DataSource tomcatDs = (org.apache.tomcat.jdbc.pool.DataSource) ds;
logger.info("After method call: " + methodName + " : number of connections in use by the application (active): " + tomcatDs.getNumActive());
logger.info("After method call: " + methodName + " : the number of established but idle connections: " + tomcatDs.getNumIdle());
logger.info("After method call: " + methodName + " : number of threads waiting for a connection: " + tomcatDs.getWaitCount());
} else if (ds instanceof com.zaxxer.hikari.HikariDataSource) {
com.zaxxer.hikari.HikariDataSource hikariDs = (com.zaxxer.hikari.HikariDataSource) ds;
logger.info("Other props: {}", hikariDs.getDataSourceProperties());
}
}
}

3.3 Run the code

When you run the code, you will get output similar to this:

console
2019-05-12 16:12:08.357 INFO 14842 --- [nio-8080-exec-1] c.sb1jt.config.ConnectionAspect : ds type: org.apache.tomcat.jdbc.pool.DataSource
2019-05-12 16:12:08.767 INFO 14842 --- [nio-8080-exec-1] c.sb1jt.config.ConnectionAspect : other props: ConnectionPool[defaultAutoCommit=true; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=com.mysql.jdbc.Driver; maxActive=30; maxIdle=2; minIdle=1; initialSize=9; maxWait=20000; testOnBorrow=true; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=true; password=********; url=jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8; username=root; validationQuery=SELECT 1; validationQueryTimeout=5000; validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; ignoreExceptionOnPreLoad=false; useStatementFacade=true;
2019-05-12 16:12:08.801 INFO 14842 --- [nio-8080-exec-1] c.sb1jt.config.ConnectionAspect : after method call : com.sb1jt.dao.CityDao:listCities : number of connections in use by the application (active) : 0
2019-05-12 16:12:08.802 INFO 14842 --- [nio-8080-exec-1] c.sb1jt.config.ConnectionAspect : after method call : com.sb1jt.dao.CityDao:listCities : the number of established but idle connections : 9
2019-05-12 16:12:08.802 INFO 14842 --- [nio-8080-exec-1] c.sb1jt.config.ConnectionAspect : after method call : com.sb1jt.dao.CityDao:listCities : number of threads waiting for a connection : 0

4. Conclusion

As demonstrated, you can write an aspect to intercept the DAO calling process. Before and after the method call, you can view the datasource’s connection pooling configurations. This approach is particularly useful for debugging and optimizing connection pool settings in Spring Boot applications.

5. Summary

In this post, we explored how to debug connection pool configurations in Spring Boot applications using AspectJ. By adding the necessary dependencies and writing an aspect, you can intercept and log connection pool details before and after method calls. This technique is invaluable for understanding and optimizing your application’s connection pool behavior.

Final Words + More Resources

My intention with this article was to help others who might be considering solving such a problem. So I hope that’s been the case here. If you still have any questions, don’t hesitate to ask me by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!