Oracle DB connections not releasing from connection pool in Tomcat 8 - jdbc

We are migrating Tomcat6, java 6 and Oracle 10g web-applications to Tomcat 8, Java 8 and Oracle 10g. Our applications working fine after migrated, but initial connections (initialSize="5") available in connection pool not released after Tomcat shut down. When second time starting tomcat, its creating 5 more initial connections to pool. I am using below resource configuration in server.xml
<Resource name="TestAppDataSource"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
initialSize="5"
maxActive="40"
maxIdle="40"
minIdle="5"
timeBetweenEvictionRunsMillis="30000"
minEvictableIdleTimeMillis="30000"
maxWait="10000"
testWhileIdle="true"
testOnBorrow="true"
testOnReturn="false"
validationQuery="SELECT 1 from dual"
validationInterval="30000"
logAbandoned="true"
removeAbandonedTimeout="30"
removeAbandonedOnBorrow="true"
removeAbandonedOnMaintenance="true"
suspectTimeout="300"
maxAge="60000"
url="jdbc:oracle:thin:#//IP_ADDRESS:1521/SCHEMA_NAME"
username="USER_NAME"
password="PASSWORD" />
And below resource link configuration in application META_INF/context.xml
<ResourceLink
name="APP_TEST"
global="TestAppDataSource"
type="javax.sql.DataSource"
/>
I am using ojdbc7.jar for oracle driver. Please help whether i missed any configuration..

try with the follow option:
removeAbandoned = true
(boolean) Flag to remove abandoned connections if they exceed the
removeAbandonedTimeout. If set to true a connection is considered
abandoned and eligible for removal if it has been in use longer than
the removeAbandonedTimeout Setting this to true can recover db
connections from applications that fail to close a connection. See
also logAbandoned The default value is false.
Tomcat now use JDBC Connection Pool org.apache.tomcat.jdbc.pool that is a replacement or an alternative to the Apache Commons DBCP connection pool.
removeAbandoned is a option for JDBC Connection Pool
https://tomcat.apache.org/tomcat-8.0-doc/jdbc-pool.html

You have to add closeMethod="close" to your JDBC resource in context.xml. That way, Tomcat properly releases pending connections to the database.

Nitpick: when tomcat is shut down, the JVM is shut down, hence all of its resources are "released" too, and there is no more connection pool - what you meant is that the connections are not properly being shut down, so the DB is not being notified that they're closed, and hence the sessions there are not being ended. This is either because the pool is not getting a shutdown command, or because something else is hanging in tomcat during shutdown and hence it's not getting to the point of shutting down the pool, being force-killed by the shutdown script after a wait timeout has expired. You can take thread dumps during shutdown to see what it's waiting on, and look at catalina.out for messages about leaked threads (...has started a thread ... that's not been shut down ...). It is a common problem that webapps will launch long-running threads without daemonizing them - such webapps need to implement a ServletContextListener that will stop this thread/resource when the ServletContext is stopped.

Related

Frustrated with configuring Tomcat v8 jdbc pool for Oracle 19c

We have an older application on Linux Tomcat v8, connecting to Oracle 19c database using Oracle 19c jdbc client library ojdbc8.jar and having trouble getting the right datasource settings in context.xml
Much of the online resources I've found are contradictory, but this is where I'm at right now:
<Resource
name="jdbc/myDatasource"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:#ldap://{LDAP_HOST}:389/{DBNAME},cn=OracleContext,dc={DOMAIN},dc=com"
username="*********"
password="*********"
maxTotal="50"
maxIdle="10"
connectionProperties="oracle.jdbc.ReadTimeout=5000"
/>
But I'm not trusting that we're using the right factory, since the classloader logging shows this:
[Loaded org.apache.tomcat.jdbc.pool.DataSourceFactory from file:/opt/apache-tomcat/apache-tomcat-8.5.31/lib/tomcat-jdbc.jar]
[Loaded org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory from file:/opt/apache-tomcat/apache-tomcat-8.5.31/lib/tomcat-dbcp.jar]
Feb 01, 2023 11:30:50 AM org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory getObjectInstance
Feb 01, 2023 11:30:53 AM org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory getObjectInstance
Feb 01, 2023 11:30:53 AM org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory getObjectInstance
It seems like the right factory gets loaded, but then the basic/default factory is being used to create the pools instead of the Tomcat DataSourceFactory. Am I reading this wrong?
Any pointers that I should look for? I'm scanning the application contents under /webapps to see if they have any embedded jdbc pools being created, but so far haven't found anything.
We're not trying to do anything fancy, we just want the basic/right/normal settings to start with for this connection scenario. All the settings we have now were passed down from previous Tomcat & Oracle versions, so everything is suspect.
Edited to add:
I found this buried in the application code, and when I comment it out I can see the "Basic" DataSourceFactory is no longer loaded, and the messages about the getObjectInstance are gone.
<resource-ref id="ResourceRef_1200664413729">
<description>data source</description>
<res-ref-name>jdbc/masked-name</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
But now if I specify the Tomcat factory for my context.xml datasources:
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
then we get bad pool behavior in a failover situation. The pool appears to get corrupted when one DB node goes down, requiring a restart.
But if I specify no factory, then the log again shows the DB2 BASIC factory being used, yet things seem to work right for failover.
So I don't understand why all the online documents seem to want me to use the Tomcat datasource factory. What's "right" ?

SQL DB sessions leakage issue on tomcat 9.0.43

we are upgrading our application from tomcat 9.0.22 to 9.0.43 version. but we are struggling with session leakage issue on tomcat 9.0.43. we have same configuration for JDBC connection but no idea why database sessions not releasing on tomcat 9.0.43. but application works fine on 9.0.22 version. kindly help upgradation must required as there is vulnerability find by InfoSec. below is configuration for JDBC connection. application hosted on windows server 2019 and SQL standard edition
<Resource name="jdbc/abcDb"
auth="Container"
type="javax.sql.DataSource"
driverClassName="net.sourceforge.jtds.jdbc.Driver"
url="jdbc:jtds:sqlserver://10.xxx.xxx.xx:1433/Prod"
username="xxxx"
password="XXXXXXXXX"
maxWaitMillis="40000"
maxTotal="1000"
maxIdle="233"
minIdle="89"
timeBetweenEvictionRunsMillis="68000"
minEvictableIdleTimeMillis="110000"
validationQuery="SELECT 1"
testWhileIdle="true"
testOnReturn="true"
testOnBorrow="false"
removeAbandonedOnBorrow="true"
removeAbandonedOnMaintenance ="true"
logAbandoned="false"
removeAbandonedTimeout="55" />

Is preparedstatement cache at connection pool level better than setting cache at jdbc driver level in a multi threaded env?

Was exploring the HikariCP connection pooling library, currently in an application we use Apache DBCP2 for providing a connection pool,which allows setting the preparedstatement cache at connection pooling level by specifiying these properties:
<property name="poolPreparedStatements" value="true"/>
<property name="maxOpenPreparedStatements" value="20"/>
But HikariCP clearly mentions in the wiki, that such feature is not supported in the library and instead relies on the corresponding jdbc driver to setup the cache for preparedstatement.
Since connection pools will be shared across threads I think connection level cache for preparedstatements would be the way to go,I am not sure of the behavior of the cache at jdbcdriver level, if it does locking of some sort for the preparedstatement,causing some contention?
Any suggestions on which would be way to go if the application would need to handle high volumes of queries as part of a routine which will be executed daily?
Please note that PreparedStatement is cached at connection level, when using a connection pool(dbcp2 in this case), connections can be created and closed rapidly due to eviction,idle timeout operations based on the settings.
Thus in order to enable proper caching of preparedStatement I had to set:
<property name="poolPreparedStatements" value="true"/>
<property name="maxOpenPreparedStatements" value="20"/>
Before setting these, even though I tried to use a preparedStatement(via JDBCTemplate) the database would hardparse every query when tested under load of 8 threads with 2 queries over the same table with 10000 rows.
For HikariCP I didn't get a chance to check out the behavior.

JDBC Connection pool configuration in Tomcat 7

I added following properties in our context.xml file, under tomcat 7x
validationQuery="SELECT 1 FROM DUAL"
testOnBorrow="true"
logValidationErrors="true"
driverClassName="oracle.jdbc.driver.OracleDriver"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
logAbandoned="true"
maxActive="50"
maxIdle="20"
removeAbandoned="true"
removeAbandonedTimeout="180"
type="javax.sql.DataSource"
and I had shut down my Oracle database, and tried to connect the database through the application and I was getting exceptions as
### Error updating database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException:Could not get JDBC Connection; nested exception is java.sql.SQLException: Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
Which I think is an expected error.
After that, I brought back the Oracle and tried to connect the database through application, with out restarting tomcat. My expectation is, the application should be able to get the connection from the pool and work as normal. However, I saw
### Cause: java.sql.SQLRecoverableException: Closed Connection
; SQL []; Closed Connection; nested exception is java.sql.SQLRecoverableException: Closed Connection
Is the SQLRecoverableException, expected here. Do I need to restart tomcat, to establish a successfull connection back to database? In a typical production environments, if DB is shutdown for any reason and was brought back, should the application servers also need to be restarted. I think, it is not required.
Did I miss any other property in Context.xml that enables this ?
Thanks
you need to specify a url attribute that allows the connections to connect to the DB

Redis as a session store in glassfish

I got an open-source component called tomcat-redis-session-manager can store http session in redis, to provide high-availability in many tomcat servers.
So I want to find if there is a way to store glassfish http session in redis or memcached.
But I have not find what is the http session creation or acquire interceptor in glassfish.
Can anyone tell me how?
Tomcat does it by adding the following in context.xml
<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
host="localhost"
port="6379"
database="0"
maxInactiveInterval="60"
/>

Resources