-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Richard,

On 3/25/19 14:15, Richard Huntrods wrote:
> <sigh> It's time to update my application to use "real" (i.e.
> current best practices) data connection pooling.

:)

> My application is Java Servlets, no beans, no JSP. Database is
> MySQL.
> 
> System etc. details: Ubuntu live server 18.04.2, built March 6,
> 2019.
> 
> MySQL - latest installed via 'apt-get install mysql-server' after
> system build.

So... MariaDB, then? Or does Ubuntu still stock MySQL binaries?

> OpenJVM - 11? - again, latest version installed via 'apt-get
> install default-jdk' at same time.

Should be pretty easy to determine this:

$ java -version

> Tomcat 8.5.39 - just updated the same day it came out.

Sounds good so far.

> This system has been running in production since the early 2001's.
> OS has changed over the years from Sun Solaris 8.x to Solaris 10.x
> and now to Ubuntu 18.04 (server). Java has been updated over the
> years as well, as has Tomcat and MySQL. Through all that the system
> works quite perfectly.
> 
> Except... there are occasional hangs that implicate the 'home
> grown' data connection pool.  I wrote this by hand (in Java) back
> in 2001 because there was nothing much available back then. Since
> it kept working, I didn't have the time/inclination to change over
> the years.

You may find that your home-grown connection pool is actually okay,
but it's being used incorrectly by client code (which is also your
code). IF you have problems with the client code, the "real"
connection-pool can help you tolerate them, but it won't magically fix
them.

> But the latest connector (mysql-connector-java-8.0.15.jar, a.k.a. 
> "com.mysql.cj.jdbc.Driver" is giving me some hiccups. I thought
> rather than trying to debug my own connection pool, it was time to
> switch over to a proper "modern" supported connection pooling
> system.
> 
> Which brings me to my question.
> 
> Would the community please weigh in on the BEST tutorials /
> documents regarding creating a Tomcat/MySQL database connection
> pool for Servlets (not JSP or beans) with some good code examples
> and server.xml examples?
> 
> I've already done some extensive internet searches, but when you
> are doing something for the first time it's hard to tell the
> difference between "really really good" and "blogger who has not
> really tried it".

You will want Tomcat to create the connection pool for you. Anything
else is a waste of time. Here's what happens:

1. During application startup, Tomcat creates a javax.sql.DataSource
object and squirrels it away using a path in the JNDI space that you
get to specify the tail-end of.

2. When your application needs a connection, you grab the DataSource
from JNDI (it's like a singleton in-memory Map of URLs to objects) and
ask it for a java.sql.Connection object.

3. When you are done with the connection, you call Connection.close on
it and it goes back into the pool.

So, fairly simple.

It's all fairly easy, though changing all your code to work with it
might not be. Here's basically what you need.

1. Tomcat configuration. This goes into META-INF/context.xml:

   <Resource name="jdbc/myDS"
    description="My database connection"
        auth="Container"
        type="javax.sql.DataSource"
        maxActive="1"
        maxIdle="1"
        maxWait="10000"
        url="jdbc:mysql://host/database"
        username="scott"
        password="tiger"
        driverClassName="com.mysql.jdbc.Driver"
        removeAbandoned="true"
        removeAbandonedTimeout="30"
        logAbandoned="true"
        testOnBorrow="true"
        validationQuery="/* ping */ SELECT 1"
        initialSize="1"
        maxTotal="1"
        maxWaitMillis="10000"
        removeAbandonedOnBorrow="true"
        closeMethod="close"
    />

You can look-up the meanings of all of the above settings here:
https://commons.apache.org/proper/commons-dbcp/configuration.html

Note that I have the above configured for "Development Mode" which
means that there is exactly 1 connection in the pool, period. If you
have bad code which fails to return the connection (leaks) or tries to
check out more than one connection from the pool (potential deadlock),
then your application will freeze in development.

In production, feel free to crank-up the maxActive, maxIdle, and
maxTotal settings.

2. Get a connection object in your code:

    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    import javax.sql.DataSource;

    ...

    Connection conn = null;
    try {
      try
      {
          Context ctx = new InitialContext();

          DataSource ds =
(DataSource)ctx.lookup("java:/comp/env/jdbc/myDS"); // NOTE: Suffix
matches <Resource name="[name]"

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

          conn = ds.getConnection();
      }
      catch (NamingException ne)
      {
          // Error "Cannot obtain database connection"
      }
      catch (SQLException sqle)
      {
          // Error "Cannot obtain database connection"
      }

      // Your code goes here
    } finally {
      try { conn.close(); } catch (SQLException sqle)
      { /* whatever you want */ }
    }

3. Actually, the Connection.close is up there in the example above.

I would highly recommend that you create a "getConnection" method
which handles the details of fetching the DataSource and Connection
and the various Exceptions that can be thrown in there. You don't want
all that garbage to get in the way of your "real code" in your
data-access methods.

Always remember to close the connection in a finally block. And your
Statement and ResultSets as well.

Hope that helps.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAlyaTIkACgkQHPApP6U8
pFjpEw/7BeomASCkf1O86Wlx8mz0DxIB09yCQxVw7VhsR41/oB5UHomBO9fTMQRg
uOnLJjdy1SjSCPHUahB/AL+La9Vzx3+qmlfABCQmZ7SatQ7aocivUVzfI/ZYyAmO
9QcA3bdz+qHJdegD4t+jcqFM6lctjR0OE4CpO2Ik6OgizStk/oUOPDgoHvs25+Zd
zWOVMdXtomjZ/dmIYvj0NNVqksGF/RNAz0JOQN2T/AT97U677y4rfO+cdhR+urOA
aW4LmynPFdb2D+y3MCYgxerZkBQZluDtM3B2R0w1Hb0EL/7Ew8SKsBB1QA3CikeF
qQFqlSDOZzpRoua6pP+r94ZKWXvAGULQJFFw4tgyYJka2BLxKOFr1paIa/E3SEcW
io6OmLKn/m6iA7AI0G7peSdHPkc4byXWVEQAq9jN0boD3RKw6Sz1+HfM6mAxPEmh
BDbtg2/m5lwb4jO4xNF5ybxR5sU065Pc4Su5polJ/c8QuLLiCJMmpGM5UuhTpQBV
uUsl+cdsNud+ruoAu36au33YTIw3aImlEXXb3ZlntUpaGearXoV3vtJ5QmYVuKVm
dyCTAZALgNiPFYGOr7PGvZZ7jD2w0l+9trCfzZE0JwnydIi8yhX2kUWqjl6N2bou
C2iswKlBZp+wAwgSGa4+hAMLgUlpOjLiXvwLaE4idxWVjpAm7wY=
=/swK
-----END PGP SIGNATURE-----

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

Reply via email to