Jerry,

On 12/8/2021 9:18 PM, Jerry Malcolm wrote:

On 12/1/2021 10:38 AM, Jerry Malcolm wrote:
Mark,

On 12/1/2021 12:21 AM, Mark Eggers wrote:
Jerry,

On 11/30/2021 10:06 PM, Jerry Malcolm wrote:
I'm circling back to this after a few months.  I am building on a Windows 10 box with 9.0.52 TC. But I'm running on an AWS Linux2 with 8.5.72.  This has never caused any problems so far, or at least as far as I can tell. But I'm hitting something strange with this relatively new BasicDataSource.restart() method.   My reference to restart() builds fine.  But when I run it on the 8.5.72 server I get: java.lang.NoSuchMethodError: 'void org.apache.tomcat.dbcp.dbcp2.BasicDataSource.restart()'

Rémy mentioned that it should be in TC 8.5.58+.   This is a relatively clean EC2 on AWS, not running much other than Tomcat. And I have not done in backdoor (non yum) installs of TC that might have left old jar files around.   I noticed that there are 2 dbcp2 jar files in TC's lib. One is from the java install. But the error message above is a tomcat path.  So I'm assuming it's tomcat's dbcp2 jar that's being referenced. I exploded the jar hoping there would be some version numbers somewhere inside telling me if I somehow have a backlevel jar.  But I couldn't find anything.  All I know is it's date is 2/25/2021 and it's 286,358 bytes.

Any other ideas come to mind why it's telling me the restart() method doesn't exist?

Thx as always.

Jerry


On 9/7/2021 2:49 PM, Jerry Malcolm wrote:

On 9/7/2021 2:35 PM, Christopher Schultz wrote:
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

Chris,

I'll definitely try this.  But I'm curious about the restart method. Is it some sort of a hidden method that's only available to reflection?  Seems it would be a lot more straightforward to just make the restart method public like it is in the apache version of BasicDataSource.  I'm not complaining.  If this works, then fine. Just curious.

Thx

Jerry

I haven't been following this thread, so I may be way off.

The last time I used an AWS EC2 instance "out of the box" with an AWS-supplied Tomcat, I ran into some very strange behavior.

It turns out that AWS packaged the 8.5.x Tomcat with the older (7.0.x) resource pool. I figured this out by looking at logs and seeing the complaints about my context.xml.

I raised the issue with AWS, and got silence back.

Ever since then, I package up my own version of Tomcat using releases from tomcat.apache.org.

Could you be experiencing some similar issue?

. . . just a random thought
/mde/

Honestly, that's what it looks like.  But I figured a mixed-package with AWS was too off-the-wall to be the real cause. With your experiences as well, it may be a real possibility.  I'm going to spin up a sandbox ec2 and do some playing.

Thanks for the info.

Jerry

Follow up on this. I have confirmed that yum on AWS Linux 2 omits tomcat-dbcp.jar from the package.  I installed TC (8.5.72) on a clean EC2 and that jar does not exist in the lib directory.   On my existing EC2 that's been around a couple of years, the file is there, but it's very old.  yum not only doesn't update the jar, it leaves an old one lying around.  I downloaded the 8.5.73 zip and copied that one jar to my development EC2, and the BasicDataSource restart() that I was originally getting Method Not Found is now working correctly.

From all indications, it just looks like yum left out a file. I'm assuming tomcat-dbcp.jar is still required since it's included in the 8.5.72 zip  (Correct?)  I'm just a bit concerned if there are other files that were omitted, and I'm running a mixed-version TC (??).  I've seen the other thread about the alternative to move off of yum and manage the TC install myself.  I'm not a fan of that.  But if I have any other problems it may be the only answer.  /mde/-- thanks for pointing me in the correct direction on this.  If you hear anything back from AWS regarding the yum package, let me know.

Jerry

Glad to have helped.

What I found is that on earlier versions of Tomcat 8 (Tomcat 8.0 - haven't checked Tomcat 8.5), yum installed an old version of tomcat-dbcp.jar

You can take a look at the JAR files and see if there's org.apache.tomcat.dbcp.dbcp2 (Tomcat distro) or org.apache.tomcat.dbcp.dbcp (if I remember correctly, from the yum installation). This will impact how context.xml JDBC resources are configured.

They may have fixed this, but I've not looked at it for a while since I run stock Tomcat.

I understand your reluctance to move from a distro-installed Tomcat. With the distro-installed Tomcat, you can automate updates using something like SaltStack. It's a bit more complex (but possible) using the Tomcat tar.gz file.

My real issue with AWS (or other cloud providers for that matter) is how servers in general are treated. In a traditional datacenter, servers are pretty bullet-proof. In a cloud infrastructure, servers are (or can be) ephemeral. I've had AWS mark servers for deletion due to server errors of some sort.

In order to get around this, you end up running multiple servers, preferably in multiple availability zones, behind a load balancer.

This complicates application updates. I've tried elastic groups and elastic beanstalk, but I've been not pleased with the update / rollback time. It's also tightly bound to AWS, making multi-cloud or migrating to a different cloud challenging. There are also potential developer buy-in issues, even when you automate roll-outs using something like Jenkins.

This is leading me down the path of Docker containers or similar technology. The Docker environment is portable across cloud providers, and cycle times are (at first pass) much faster. Further more, developers can run pretty much the same environment on their local machines, so there should be no deployment oddities.

I still have a long way to go. I need to manage distributed logging, database connections, database fail-over connections, and what happens when a region goes completely dark (like east-1 did the other day).

I have some ideas about all of that, but it needs to be seamless. That way developers can run locally, push to a test environment in the cloud, and finally push to production. All hopefully without someone like me being involved on a day to day basis. I do not want to be the single point of failure in a development to production process.

Then there's clustering without multicast. Right now we don't use sessions, so I am not concerned about clustering. However, we will have some applications in the near future that will require sessions. Clustering across availability zones, and recovering seamlessly from region outages remain problems to be solved (preferably inexpensively).

Oh, and don't even talk to me about microservices at this point. I don't know if our applications will refactor cleanly to microservices. I'm just starting down that path.

Lots to do . . . not nearly enough time to do it.

. . . just my two cents
/mde/

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

Reply via email to