Jerry, Rémy,

On 9/3/21 07:15, Rémy Maucherat wrote:
On Fri, Sep 3, 2021 at 2:46 AM Jerry Malcolm <techst...@malcolms.com> wrote:

I have a requirement to start a new log database on the first of every
month.  I still need to have access to older monthly log databases.   I
do not want to create a bunch of hardcoded manually configured
individual datasources, one for each month.  I have a dynamic datasource
solution that is completely implemented and working except for one
little thing.

I access the BasicDataSource implementation class for the datasource.  I
have an algorithm that substitutes yyyy_MM at the appropriate spot in
the configured URL and then updates the url in the datasource.   All of
this works great.  I can live with the fact that the datasource can only
point to one database at a time.  My concern is that once I transition
to another database, there are existing connections in the pool that are
already attached to the old database.  I need to clear those out and
start over.  But I don't have the luxury of bouncing tomcat to clean it up.

The apache commons BasicDataSource has a restart() method.  But
unfortunately that method is omitted from the Tomcat version. There is a
close() method on the BasicDataSource.  But I don't see anything that
will re-open it after closing.  I thought about changing maxActive to 0,
and waiting for it to drain, then setting it back to the original
value.  None of these sound like an ideal solution.  Without a restart()
method, is there any other way to force all existing connections to
close and start clean?

The code is kept in sync with DBCP (with a bit of lag maybe), so these
lifecycle methods were also added to Tomcat one year ago (9.0.38+ and
8.5.58+).

We are using this at $work to bounce our database connection pools after TLS client certificate changes. This is the code we are using to reload the pool:

  try
  {
      Context ctx = new InitialContext();

      DataSource ds = (DataSource)ctx.lookup(getJNDIPath());

      if(null == ds)
          throw new ServiceException("Cannot obtain DataSource");

      if(isInstanceOf(ds, "org.apache.tomcat.dbcp.dbcp2.BasicDataSource")
         || isInstanceOf(ds, "org.apache.commons.dbcp2.BasicDataSource")) {

          return call(ds, "restart");
      }
  } catch (Exception e) {
org.apache.log4j.Logger.getLogger(this.getClass()).error("Failed to reload DataSource " + getJNDIPath());
  }

The call() method simply encapsulates all of the work to make a reflective method call to BasicDataSource.restart().

As Rémy points out, it requires a Tomcat version 9.0.38+ or 8.5.58+.

Hope that helps,
-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to