Tomcat's Default DB Connection Pool

05 Oct 2020

Table of Contents


Introduction

How do I configure Tomcat 9 to use its default connection pool? It is slightly unclear from the documentation what the difference is between the Tomcat DBCP 2 pool and the other Tomcat JDBC pool. How to configure them? And what’s the difference? And which to use?

Summary

Both of the following approaches will use DB connection pools:

  • Use Tomcat’s newer, default DBCP 2 pool with type="javax.sql.DataSource".
  • Use Tomcat’s older JDBC pool with factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" and type="org.apache.tomcat.jdbc.pool.DataSource".

I don’t know enough about the differences to give any strong recommendations re. using one over the other.

The Default DBCP 2 Tomcat Pool

To make use of the default Tomcat DB connection pool, via a JNDI resource, you should follow the instructions provided on this Tomcat documentation page: JNDI Datasource How-To

Specifically, you need to use type="javax.sql.DataSource".

Config Example

Here is a very basic resource configuration, based on MySQL - not suitable for production, but useful to illustrate the approach:

XML
1
2
3
4
5
6
7
8
<Resource name="jdbc/my_db"
          auth="Container"
          type="javax.sql.DataSource"
          initialSize="5"
          username="db_user"
          password="***"
          driverClassName="com.mysql.cj.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/mytestdb" />

A Java connection would then follow the usual approach for using JNDI:

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

...

try {
    InitialContext ctx = new InitialContext();
    ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/my_db");
} catch (NamingException ex) {
    // log the error...
}

Or, if preferred, you can use the @Resource annotation from javax.annotation.Resource, applied to a field:

Java
1
2
@Resource(name = "java:/comp/env/jdbc/my_db")
private DataSource ds;

When using initialSize="5", I saw the 5 expected connections on the DB server.

In the JVM, a connection pool was created - as shown in this VisualVM heap dump:

Here we can see that the pool is created, it has 5 connection objects, and it is using Tomcat DBCP - which, in turn, is a fork of Apache Commons DBCP 2.

DBCP 2 provides support for JDBC 4.1 (it is a pure-Java JDBC driver).

Tomcat's Home-Grown JDBC Pool

If you look at the Tomcat documentation on this other page - The Tomcat JDBC Connection Pool - you will see different guidance.

Specifically it states that you need both of the following in your <Resource>:

1
2
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="org.apache.tomcat.jdbc.pool.DataSource"

If you use this, you will also be using a DB connection pool - but it will be based on the older Tomcat JDBC pool package:

[![enter image description here][4]][4]

In this example, I used initialSize="3".

In the Tomcat documentation this is presented as “a new connection pool” (it was a replacement for the previously used Commons DBCP 1.x). It’s not as new as the Tomcat default DBCP 2 solution.

I think the documentation wording is out-of-date, now. And somewhat confusing, because of that.

Additional Notes

Notes from a member of the Tomcat commit team (see here):

Tomcat JDBC is Tomcat’s “home grown” database connection pooling and does not use poolPreparedStatements

Tomcat DBCP is Tomcat’s package renamed fork of Apache Commons DBCP 2.

Tomcat DBCP is used by default.

You can always choose to implement a pool directly in your code, without using a JNDI <Resource> annotation. There are many available options. I have used Hikari a few times without any issues.