Spring Throws "ERROR SqlExceptionHelper: Already closed" after timeout - java

I have a spring application hosted on to the server (Tomcat 8.5). It goes idle if no one uses it. I already knew that timeout will occur if the DB is in idle state for 8 hours (Default timeout of MySQL). As mentioned in Spring Autoreconnect and Connection lost overnight post i have tried the solution available here.I have tried configuring application.properties but that doesn't bring any solution to the problem.
(PS:I'm not changing anything other than application.properties in my Spring Application).

Well if this
spring.datasource.testWhileIdle = true
spring.datasource.timeBetweenEvictionRunsMillis = 60000
spring.datasource.validationQuery = SELECT 1
or this
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
didnt work maybe try this
Post SpringBoot 1.4 names have changed
They have defined new specific namespaces for the four connections pools spring supports: tomcat, hikari, dbcp, dbcp2.
spring.datasource.tomcat.testOnBorrow=true
spring.datasource.tomcat.validationQuery=SELECT 1

If problem doesn't solve even after including properties as in application.properties, Then problem will be solved when including testOnBorrow,validationQuery in application-context.xml located in src/main/resources
<bean name="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driver.classname}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="initialSize" value="2"/>
<property name="maxActive" value="50"/>
<property name="maxIdle" value="5"/>
<property name="maxWait" value="-1"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="600"/>
<property name="logAbandoned" value="true"/>
<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />
</bean>
The solution is to validate connection thread when it is borrowed from thread pool by enabling testOnBorrow and providing validationQuery.

Related

Queries take too long after MySQL fail-over

I have an application that uses MySQL fail-over via a connection url:
jdbc:mysql://172.17.0.4:3306,172.17.0.3:3306/db_name?autoReconnect=true&failOverReadOnly=false
Now when primary db is down then it should move to secondary connection and application flow should work as expected.
Now the problem happens when moving to secondary db. It takes too long to move/execute the queries, causing the flow to take much longer than expected.
I have checked already with db and there's no slow query issues. I guess it's something to do with fail-over and with checking the states. So, any idea what might be causing this issue or how to resolve this delay?
I am also using c3p0 to manage the connections pools. Already tried with initialTimeout and maxReconnects but no luck so far.
DataSource
<bean id="productionDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="description" value="integration_ds"/>
<!-- configuration pool via c3p0-->
<property name="acquireIncrement" value="${datasource.acquireIncrement}"/>
<property name="idleConnectionTestPeriod" value="${datasource.idleConnectionTestPeriod}"/>
<!-- seconds -->
<property name="maxPoolSize" value="${datasource.maxPoolSize}"/>
<property name="maxStatements" value="${datasource.maxStatements}"/>
<property name="maxStatementsPerConnection" value="${datasource.maxStatementsPerConnection}"/>
<property name="minPoolSize" value="${datasource.minPoolSize}"/>
<property name="initialPoolSize" value="${datasource.initialPoolSize}"/>
<property name="maxIdleTime" value="${datasource.maxIdleTime}"/>
<property name="acquireRetryAttempts" value="${datasource.acquireRetryAttempts}"/>
<property name="acquireRetryDelay" value="${datasource.acquireRetryDelay}"/>
<property name="breakAfterAcquireFailure" value="${datasource.breakAfterAcquireFailure}"/>
<property name="debugUnreturnedConnectionStackTraces" value="true"/>
</bean>
Properties
datasource.acquireIncrement=1
datasource.idleConnectionTestPeriod=1000
datasource.maxPoolSize=10
datasource.maxStatements=600
datasource.minPoolSize=5
datasource.initialPoolSize=5
datasource.maxIdleTime=7200
#datasource.acquireRetryAttempts=5
datasource.acquireRetryAttempts=1
#datasource.acquireRetryDelay=5000
#datasource.acquireRetryDelay=1000
datasource.acquireRetryDelay=100
datasource.breakAfterAcquireFailure=false
datasource.maxStatementsPerConnection=3
datasource.checkoutTimeout=100
DAO
private static final String findByAppIdHql = "select app from AppImpl app where app.appId = ?";
final Query query = sf.getCurrentSession().createQuery(findByAppIdHql).setString(0, appId);
query.setCacheable(true);
query.setCacheRegion("app_query_cache");
query.setCacheMode(CacheMode.NORMAL);
List<App> apps = query.list();

Connection pooling in spring jdbc

I have implemented spring jdbc in my project. I am just curious to know how connection pooling in handled in spring jdbc? If spring is taking care of connections, then where can I specify the max number of connections allowed for my application?
Another question is how is connection pooling handled in simple jdbc.
Please clarify.
You can use own custom datasource, like this:
<bean id="springDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="url" value="jdbc:oracle:thin:#localhost:1521:SPRING_TEST" />
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="removeAbandoned" value="true"/>
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
</bean>
//Dao class configuration in spring
<bean id="EmployeeDatabaseBean" class="com.test.EmployeeDAOImpl">
<property name="dataSource" ref="springDataSource"/>
</bean>
Official documentation
Here or here described pretty simple.

jdbc connection string with c3p0

I have jdbc configured with c3p0.
However, I am worried about possible conflicts, since some of the parameters in jdbc string and c3p0 are similar.
Here is my jdbc string:
jdbc:mysql://1.1.1.1:3306/db?useSSL=true&requireSSL=true&connectTimeout=15000&socketTimeout=30000&autoReconnect=true
We decided to include connectTimeout, socketTimeout, autoReconnect
because otherwise it took too long to switch to the replica if master crashes. ( We are using MySQL RDS Multi-AZ ).
Here are my c3p0 properties:
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="10"/>
<property name="maxIdleTime" value="3600"/>
<!-- 1 hour -->
<property name="maxConnectionAge" value="7200"/>
<property name="maxIdleTimeExcessConnections" value="600"/>
<property name="idleConnectionTestPeriod" value="180"/>
<property name="testConnectionOnCheckin" value="true"/>
<property name="testConnectionOnCheckout" value="false"/>
Any ideas / suggestions?
Maybe someone has production-ready configuration?
Best Regards,
Maksim

Database query hangs after some time

I have following database configuration in a Spring project -
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.jdbc.url}" />
<property name="username" value="${db.user}" />
<property name="password" value="${db.password}" />
<property name="maxActive" value="75" />
<property name="initialSize" value="10" />
<property name="testOnBorrow" value="true" />
<property name="validationQuery" value="SELECT 1" />
<property name="maxWait" value="10000"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
autowire="byName">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
The application runs for some time (30 mins to 2 hours, it varies) and after a while it starts to hang. i.e. The browser keeps on waiting for the server to respond. On checking the logs I found that the application is hung on a database query -
01/22 16:56:03 3024208 [http-bio-8080-exec-2] DEBUG DEBUG org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [SELECT * FROM mytable where id = ?]
The connection to the database is proper as I'm able to interact with it and run queries from commandline or mysql workbench.
What could be the source of the problem? At this point I'm totally at a loss as to which direction I should look in, since no exception gets thrown and there is no stacktrace. What approach would you use to attack this problem?
Have you tried creating a thread dump at the moment that your application hangs?
If you're on linux you could try to do:
$ kill -3 <pid>
The thread dump is written to the standard output. It may logged in the console or /logs/stdout or /logs/catalina.out.

Can't open connection

I develop an applivation with very load(request).
I used following technologies in my appliation:
Jpa/Hibernate as persistense layer
Spring and Spring Dao
C3p0 as connection pooling
my problem is : I run my application , when number of request increase, throw exception in
persistense layer that"Cannt open connection"
I increase oracle max session but my problem not solve
I indept in C3p0 document and test its options but my problem not solve.
Thank you for your attention
You increased max sessions on Oracle, but you didn't increase the max size of your connection pool. The exception is telling you that your pool is exhausted. Either find what's holding connections open and get them released sooner, or increase the number of max active connections in the pool.
Is it possible for you to post the Spring configuration for your DataSource. I would expect something like:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
<property name="jdbcUrl" value="${jdbc.connection.url}"/>
<property name="user" value="${jdbc.connection.username}"/>
<property name="password" value="${jdbc.connection.password}"/>
<property name="initialPoolSize" value="5"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="100"/>
</bean>
With another bean configured where the dataSource is passed by reference:
<bean id="mySampleDao" class="com.example.dao.MySampleDao">
<property name="dataSource" ref="dataSource" />
</bean>
Is this what you have?
What version of Oracle are you using?

Categories